Your agent gets a sandbox. You get a branch to read.
omh runs Claude Code in a container with your rules, skills and MCP servers already inside it, on a git worktree of its own. Your checkout is never mounted. When the agent is done you are on the host, looking at a diff.
brew install mindsers/tap/omh
$ omh s s01 omh/s01 stopped 2 uncommitted s02 omh/s02 stopped 2 uncommitted s01 and s02 both change shared.rs
Your checkout is never mounted
A session is a container, a git worktree and a branch. The agent works on its side of that line and cannot reach across it. Nothing arrives in your working tree until you put it there.
On your host, while it works
$ git status On branch main nothing to commit, working tree clean $ git stash list (nothing — yours is where you left it)
omh s01 commit
Inside the session, meanwhile
$ omh s01 log a4f21c8 add the parser, and its guard 7e0b3d1 reset --hard, second attempt c19f4a2 wire it into the CLI its own repo, one commit deep
What running omh buys you
-
Several sessions, and the collision before you hit it
omh s is every session with its state, how far it has drifted from trunk, and the files two of them are both about to change — the merge conflict you would otherwise meet on Friday.
-
Your setup, declared once
Rules, skills, MCP servers, commands, subagents and hooks live in one place. omh renders them into the shape the harness reads, and omh eject hands the raw config back whenever you want out.
-
A code graph the agent actually uses
Indexed per session and refreshed after every turn in about a seventh of a second, with hooks that point the agent at it when it is about to grep or read a whole file.
-
Your editor, inside the sandbox
omh s01 attach opens VS Code, Zed, Cursor or Neovim over SSH into the container — one dependency tree, shared with the agent, instead of a second one on your host that quietly drifts.
-
The agent gets git too
Its own repository, holding one commit and none of your history, so stash and reset --hard are its to use. Bring its commits over with the messages it wrote, all of them or the ones you name.
Getting the work back
Three commands, in the order you would guess. Nothing here touches
your checkout — the work sits on omh/s01 until you merge
it, and one command throws the whole session away.
- Read it.
omh s01 diff, or-pfor the patch. - Land it.
omh s01 commit— one commit, or replant the agent's own. - Share it.
omh s01 push, named for a reviewer.
$ omh s01 diff README.md | 2 +- src/main.rs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) $ omh s01 commit -m "Add a greeting" committed to omh/s01 (1 commit on the branch) $ omh s s01 omh/s01 up 1 to push
It decides, and tells you what it decided
omh init asks nothing. Your manifests name the stack,
git log names what you work on, the README names the project — so it
reads those, picks, and prints the result. Every entry it adds can
be traced with omh why: what it costs, and what was
considered instead.
$ omh init omh init — decided, asked nothing harness claude (found on your host) stack rust (from Cargo.toml) hooks 2 selected (4 more in your catalogue) provision rust/toolchain memory 2 notes written graph indexing in background omh why <name> what it costs, what was considered instead, how to remove it
Install
Homebrew
brew install mindsers/tap/omh
brew upgrade keeps it current, which is the part the
script cannot do.
Without Homebrew
curl -fsSL https://ohmyharness.sh/install.sh | sh
Redirects to the script in the repo, so there is one copy of it.
It picks the build for your machine, checks it against the
published SHA256SUMS, and runs it once before
installing. A failed install never replaces a working omh.
Requires Docker and git. Also builds from source with Rust 1.85+.