Run agent CLIs locally on macOS, powered by Ollama
This repository packages a practical local setup for running agent CLIs on Apple
Silicon Macs with Apple’s container tool.
The main entry point is agentctl, which manages:
- curated images such as
agent-plain,agent-python, andagent-swift - runtime selection (
codex,claude, and more over time) - local vs online launch modes
- runtime auth sync through the in-container
agent.shcontract - feature packs and bootstrap flows
You need:
- a Mac with Apple Silicon
- Ollama installed
- Apple’s
containerCLI installed
Recommended memory:
- for local-model workflows, plan for at least 32 GB RAM
- online-only workflows may work with less memory, but that is not yet verified in the current docs/test matrix
Official releases:
container: https://github.com/apple/container/releases- Ollama: https://ollama.com/download
After installing Ollama and container, clone this repository and open a
Terminal in the repository root.
Then make agentctl available on your PATH. The easiest option on macOS is
usually a symlink into /usr/local/bin:
sudo ln -sf "$PWD/agentctl" /usr/local/bin/agentctlIf you prefer a user-local install instead:
mkdir -p "$HOME/bin"
ln -sf "$PWD/agentctl" "$HOME/bin/agentctl"
export PATH="$HOME/bin:$PATH"After that, run:
# Pull the default local model used by current Codex and Claude local flows
ollama pull gpt-oss:20b
# Optional Codex profile models
ollama pull gemma4:26b-a4b-it-q4_K_M
ollama pull qwen3.5:35b-a3b-coding-nvfp4
# Optional smaller model for direct `--model` testing
ollama pull qwen3.5:9b-nvfp4
# Start the Apple container API service
container system startBefore your first local run, make sure containers can reach Ollama. The short version is:
- many setups use
192.168.64.1:11434as the host-visible Ollama address - default Ollama only listens on
localhost - you may need to expose or proxy Ollama onto the container-visible host address
Details and options are in docs/networking.md.
agentctl run starts an agent inside a container, but it mounts a host
directory into that container at /workdir.
In the normal case:
- the directory you run
agentctl runfrom becomes the mounted work directory - everything under that directory is visible to the agent
- the agent can read and write files in that mounted directory tree
- the agent does not get unrestricted access to the rest of your host
filesystem through
agentctl
So the normal workflow is:
cdinto the project or document folder you want the agent to work on- run
agentctl run - let the agent work inside that mounted directory tree
If you want a different directory than the current one, use:
agentctl run --workdir /path/to/projectBuild the curated images once:
agentctl buildThen start the agent against the current directory, which will be mounted into
the container as /workdir:
agentctl runCommon first-run workflows:
# Run Codex with a specific local profile
agentctl run -c profile=gemma
# Test a specific model directly
agentctl run --model qwen3.5:9b-nvfp4
# Pass a runtime-specific Claude launch flag
agentctl run --runtime claude -c dangerously-skip-permissions=true
# Use the runtime's online/provider-backed mode after logging in once
agentctl auth --runtime codex
agentctl run --runtime codex --online
# Start a shell instead of the runtime
agentctl run --shell
# Create a new container and auto-install Claude on first launch
agentctl run --runtime claude
# Override the launch model for the selected runtime
agentctl run --runtime claude --model qwen3:14b
# Refresh an existing container in place after pulling a newer agentctl checkout
agentctl refreshChoose a toolchain image when needed:
agentctl run --image agent-python
agentctl run --image agent-swiftInspect or manage runtimes:
agentctl runtime list
agentctl runtime info codex
agentctl runtime install claude
agentctl runtime use claudeUse the office feature on an agent-python container:
agentctl run --image agent-python --cmd true
agentctl feature info office
agentctl feature install officeBootstrap onto a compatible non-agentctl container:
agentctl bootstrap --name existing-devbox
agentctl bootstrap --name my-alpine-devbox --image docker.io/library/alpine:latestUse these curated images for most workflows:
agent-plain: general shell, Git, and runtime workagent-python: Python-heavy tasks and librariesagent-swift: Swift toolchain and SwiftPM workflows
agent-office remains only as a legacy compatibility image. For new work, use
agent-python plus the office feature pack.
If you started with one curated image and later need another one for the same
container, recreate it with agentctl upgrade --image .... For example:
agentctl upgrade --name <container> --image agent-pythonIf you already have a compatible base container and want to bring the managed
control surface onto it, use agentctl bootstrap instead of starting from a
curated image. More on that in docs/bootstrap.md.
Host integration and shell unit tests are documented in TESTING.md.
Fast checks:
bash tests/run-unit-tests.sh
bash tests/run-tests.shDeeper documentation now lives under docs/: