13 Commits

Author SHA1 Message Date
Raj b2994ac369 Add container machine for managing persistent Linux VMs (#1662)
## Type of Change
- [ ] Bug fix
- [x] New feature  
- [ ] Breaking change
- [ ] Documentation update

## Motivation and Context
`container` runs each workload in an ephemeral VM, so there's no
built-in way to keep a persistent Linux environment you can log into and
work in. `container machine` adds one.

A container machine is a lightweight, persistent, and integrated Linux
environments that feel like an extension of your Mac, created from
standard OCI images with a familiar UX. The login user matches your host
account with passwordless `sudo`, your home directory is mounted inside
the VM, and each machine keeps its filesystem and runs the image's own
init system (such as`systemd` or `openrc`).

```bash
container machine create alpine:3.22 --name my-machine
container machine run -n my-machine # interactive shell
container machine set -n my-machine cpus=4 memory=8G
```

Subcommands: `create`, `run`, `list` (`ls`), `inspect`, `set`,
`set-default`, `logs`, `stop`, `delete` (`rm`); `m` aliases `machine`.
Docs added to `docs/command-reference.md` (Machine Management) and
`docs/how-to.md` ("Use container machines").

## Testing
- [x] Tested locally
- [x] Added/updated tests
- [x] Added/updated docs

Signed-off-by: Raj Aryan Singh <rajaryan_singh@apple.com>
Co-authored-by: Jaewon Hur <jaewon_hur@apple.com>
Co-authored-by: John Logan <john_logan@apple.com>
Co-authored-by: Michael Crosby <michael_crosby@apple.com>
Co-authored-by: Eric Ernst <eric_ernst@apple.com>
Co-authored-by: Danny Canter <danny_canter@apple.com>
2026-06-08 11:38:49 -07:00
Danny Canter 796630258b kill: Wait for container to exit after sigkill (#1589)
Today when we send a signal we don't wait for the container to exit, as
we don't know what signals the program will actually do anything with.
However, sigkill does not fit this mold, and we should wait for the
container to exit (or be removed for --rm containers).
2026-06-02 14:26:17 -07:00
Danny Canter 8a25213190 Deps: Bump CZ to 0.32.0 (#1498)
Signals changed from being raw ints to a new Signal type.
2026-05-04 11:30:11 -07:00
Danny Canter f7d00aad48 APIServer: Add support for filtering to list rpc (#1175)
This is not intended to be used to support `--filter` or similar on the
CLIs list yet, it's solely to clean up our rather awkward use of
`ContainerClient.list()` today in the CLI. The list RPC simply returns
all of the containers we have created. Because of this, for a LOT of our
commands we filter to what we need client side, which feels like a
waste.. This change introduces a filter struct that we can provide an
array of container IDs, labels, and the status of the containers to
filter the `list()` output from.

This additionally, because it was killing (pun not intended) me and I
was already having to change this area for the `list()` additions,
changes container kill slightly to return an error if you try and kill a
container that doesn't exist.
2026-02-11 15:09:21 -08:00
Danny Canter 6e9b8d724d CLI: Forego logging errors on multi-container operations (#1163)
Instead of logging errors, and then additionally throwing an error
stating what containers couldn't be stopped/killed/deleted, let's just
concatenate the errors and throw the single error.
2026-02-05 09:47:20 -08:00
Danny Canter 8fdfa29728 CLI: Rework ClientContainer (#1139)
ClientContainer was honestly extremely awkward. It could only be created
by passing either a ContainerConfiguration, or a Snapshot that had to be
obtained from calling a static method on the type itself. The type also
did not store a connection, so every single method got a new xpc
connection to the APIServer. This change aims to rework this type to be
just a generic client, that is *not* a client for one specific
container, but for any.

- Rename to ContainerClient
- Have list() return [ContainerSnapshot]
- Create a connection in the constructor
- Change all the callsites to use the new API
- Small, somewhat related, change to logs API in the APIServer. Now that
we don't need to call get() to grab a client anymore which was typically
what did "does this container exist" logic and gave a nice error
message, I added a small check in the APIServer to see if the container
exists and return mostly the same error message.
2026-02-04 09:52:09 -08:00
J Logan 2b18fc5870 Use StderrLogHandler for rich logging features. (#1066)
- Facilitates #507, #642.
- Plumb logger with logger option access into every command.
- StderrLogHandler allows logging to be enhanced for ANSI color mode for
log levels, JSONL log output, replacing `--debug` with `--level level`.
- Global logger is now just an Application.swift fileprivate only used
for initial args processing.
- Log with timestamp at debug and trace level.
- Metadata output is crude at present; we can refine this in a
follow-up.
2026-01-20 14:38:29 -08:00
J Logan 356c8d2f88 Reorganize client libraries. (#1020)
- Closes #461.
- Extract core types into ContainerResources target.
- Extract ContainerNetworkServiceClient from ContainerNetworkService.
- Relocate sandbox client from ContainerClient to
ContainerSandboxServiceClient.
- Relocate ContainerClient to ContainerAPIServiceClient.
- Common structure from services and clients under Source/Services.

Updated project hierarchy:

```
Sources/CAuditToken - audit token access wrapper
Sources/CLI - CLI executable
Sources/ContainerBuild - builder
Sources/ContainerCommands - CLI command implementations
Sources/ContainerLog - logging helpers
Sources/ContainerPersistence - persistent data and system property helpers
Sources/ContainerPlugin - plugin system
Sources/ContainerResource - resource (container, image, volume, network) types
Sources/ContainerVersion - version helpers
Sources/ContainerXPC - XPC helpers
Sources/CVersion - injected project version
Sources/DNSServer - container DNS resolver
Sources/Helpers - service executables
Sources/Services/*/Client - service clients
Sources/Services/*/Server - service implementations
Sources/SocketForwarder - port forwarding
Sources/TerminalProgress - progress bar
```

## Type of Change
- [ ] Bug fix
- [ ] New feature  
- [x] Breaking change
- [ ] Documentation update

## Motivation and Context
The ContainerClient library was a bit of a grab bag. This refactor
applies a more sensible project and library structure for resource data
types, services, and clients.

## Testing
- [x] Tested locally
- [x] Added/updated tests
- [ ] Added/updated docs
2026-01-06 08:27:14 -08:00
Kathryn Baldauf d6f052d206 Update license header on all files to include the current year (#1024)
## Motivation and Context
Now that we're in 2026, we need to update the license headers on all the
files. Unfortunately, Hawkeye doesn't have an attribute for the current
year to help us avoid this in the future. Instead, I had to work around
this by doing the following:

1. Update licenserc.toml with:
     ```
      [properties]
       ... (other properties)
       currentYear = "2026"
     ```
 
2. Update scripts/license-header.txt with
    ```
Copyright ©{{ " " }}{%- set created = attrs.git_file_created_year or
attrs.disk_file_created_year -%}{%- set modified = props["currentYear"]
-%}{%- if created != modified -%} {{created}}-{{modified}}{%- else
-%}{{created}}{%- endif -%}{{ " " }}{{ props["copyrightOwner"] }}.
    ```

Then I removed these two changes before committing. After this PR is
merged, all files will have recently had git updates, so the existing
code for setting the modified year should work as intended.

Signed-off-by: Kathryn Baldauf <k_baldauf@apple.com>
2026-01-05 13:09:34 -08:00
Raj 56f6d734f3 UX: fix typos, grammar and consistency issues (#845)
Fixes several typos, grammatical errors, and consistency issues to make
the UX smoother :)
2025-11-04 13:35:29 -08:00
J Logan bfc5ca9222 Removes "all rights reserved" from license header. (#711)
Closes #63.
2025-10-03 13:28:16 -07:00
J Logan f3b33ffc45 Cleans up option groups, container subcommand help. (#647)
- Part of #515.
- Add titles to option groups for container subcommands.
- Order option groups and container subcommand options alphabetically.
- Use `container-id` and `container-ids` consistently as argument names.
- Shorten long valueNames to avoid option column overflow in help output
where possible.
- Replace customShort and customLong with short, long, and shortAndLong
where possible.
- Always place global options and arguments after alphabetized
command-specific options.
- Rename RunCommand to ContainerRun and relocate it.
- Rename Executable to ContainerCLI.

## Type of Change
- [ ] Bug fix
- [ ] New feature  
- [x] Breaking change (if you're depending on `RunCommand`, renamed).
- [ ] Documentation update

## Motivation and Context
See #385.

## Testing
- [ ] Tested locally
- [ ] Added/updated tests
- [ ] Added/updated docs
2025-09-22 16:36:07 -07:00
Morris Richman 996a6819e3 Rename CLI and ExecutableCLI folders (#635)
## Motivation and Context
This is an extension of #603 to cleanup the folder structure and have it
match with the new library and target names.
2025-09-18 17:49:48 -07:00