Skip to content

getting started

Mike Crowe edited this page Sep 17, 2026 · 1 revision

Getting started

Five steps. Host mode first (no podman), the container boundary last. Each step says what it writes and where, so nothing lands on your machine that you didn't expect.

If you only read one thing: harnessed never touches ~/.claude. Every stack gets its own config dir, and the host harness reads that dir and nothing else.

1. Install the CLI

harnessed is a host Python CLI (Python 3.12 or newer). The installer checks for uv and podman. It installs uv on request and never installs podman (that is privileged and distro-specific).

git clone https://github.com/drmikecrowe/harnessed.git
cd harnessed && ./install.sh          # --install-uv to also install uv; --uninstall to remove

By hand, the same thing is uv tool install ./harnessed (or pipx install ./harnessed). The binary lands in ~/.local/bin; uv tool update-shell puts that on your PATH if it isn't.

Writes: ~/.local/bin/harnessed, and on first run the overlay catalog at ~/.config/harnessed/catalog/ with the shipped default recipe seeded into it.

2. Run the baseline

cd /path/to/project
harnessed host-run claude

With no --stack and no --recipe, that is the shipped default stack: one recipe, carrying the skill that helps you author more recipes. Claude starts with CLAUDE_CONFIG_DIR pointed at a directory holding exactly that profile.

Writes: $XDG_DATA_HOME/harnessed/profiles/default/claude/ (the assembled profile) and $XDG_DATA_HOME/harnessed/home/default/claude/ (the config dir the harness reads).

Host mode isolates configuration, not the filesystem. Claude runs on your real machine, in your real project, with your real credentials. That is the point at this step: you can see the composition work without building an image.

3. Add a recipe for this session

harnessed host-run claude --recipe superpowers

--recipe composes on top of default. The superpowers skills are loaded for this launch. Exit, run step 2 again, and they are gone. Nothing was installed into your host config.

Behind the flag, harnessed writes a generated stack named after the recipe set (default.superpowers) under $XDG_DATA_HOME/harnessed/catalog/stacks/. It is regenerated on every launch, so don't edit it. The same recipe set from another repo resolves to the same generated stack and shares its profile.

This is the "just for now" form. I use it for pulumi: the Pulumi CLI, its egress hosts, and my ~/.pulumi login have no business in a session that isn't doing deployments, so they are a flag, not a stack.

4. Save it as a stack

Author the manifest in your overlay catalog. Three lines is a complete stack.

# ~/.config/harnessed/catalog/stacks/mine/stack.yaml
name: mine
recipes: [default, superpowers, rtk]
harnessed host-run claude --stack mine

The overlay wins on a name clash with the repo catalog, so a default stack here replaces the shipped one wholesale. That is how you turn your own baseline into what --recipe extends.

harnessed new <stack> scaffolds a manifest, but it writes into the repo catalog, which for a uv tool install is the installed package. Author the overlay file by hand until that changes.

The full stack.yaml schema (harnesses:, services:, permissions:, credential forwarding) is in the stacks guide.

5. Add the container boundary

This is where podman comes in. Build the stack's image once, then launch the same stack as a pod: the harness container, the MCP hub, and any declared services, with the egress firewall on.

harnessed build mine claude
harnessed container-run claude --stack mine

The first build is slow because it builds the shared base toolchain image. Later builds are cache hits unless a recipe changed. What gets built and in what order is in build and images.

Then make the launch one word:

harnessed install mine       # writes ~/.local/bin/mine
mine claude                  # same as: harnessed container-run claude --stack mine

And prove it built what you declared:

harnessed test mine claude

That launches the stack headless, asserts every skill and MCP server the manifest declares is actually exposed, and writes a per-capability report to $XDG_DATA_HOME/harnessed/profiles/mine/claude/capability-report.md.

Where to next

Clone this wiki locally