Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 25 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,16 @@ layer for reusing installs across sessions is planned but not yet wired up. See
**[packages/cli/README.md#skill-staging](./packages/cli/README.md#skill-staging)**
for the full mechanics.

### Clean mode (`--clean`)
### Sandbox mount (default for claude / opencode)

For interactive `claude` sessions, `--clean` launches the harness inside a
Interactive `claude` and `opencode` sessions launch inside a
[`@relayfile/local-mount`](https://www.npmjs.com/package/@relayfile/local-mount)
sandbox that hides repo-level Claude Code configuration from the model:
sandbox by default. The mount hides repo-level harness configuration
(claude) and routes skill-install writes into the sandbox (opencode), so
the model sees persona context + user-level context — and nothing the
repo itself declares. Codex sessions never mount.

| Hidden in `--clean` mode | Still visible |
| Hidden in the mount (claude) | Still visible |
| --- | --- |
| `CLAUDE.md` (at any depth) | `~/.claude/CLAUDE.md` (user-level) |
| `CLAUDE.local.md` | `~/.claude/skills/` (user-level skills) |
Expand All @@ -162,23 +165,26 @@ sandbox that hides repo-level Claude Code configuration from the model:
| | your keychain auth (unchanged) |

```bash
agent-workforce agent --clean posthog@best
agent-workforce agent posthog@best
```

The repo tree is mirrored into
`~/.agent-workforce/sessions/<id>/mount/` via symlinks; claude sees the
mount as its cwd. Writes inside the mount sync back to the real repo on
exit. Ignore semantics follow gitignore — `.claude` hides nested variants
like `packages/foo/.claude/` too.

**Scope:** interactive claude only. Pass it to codex/opencode and the flag
is ignored with a note. `--clean` and `--install-in-repo` are mutually
exclusive — they ask for opposite things.

**Caveat:** user-level Claude Code config in `~/.claude/` still loads
inside the session. `--clean` hides the *repo's* context, not the user's.
If you need to hide user-level config too, launch under a scratch
`$HOME`. See **[packages/cli/README.md#clean-mode](./packages/cli/README.md#clean-mode)**
The repo tree is mirrored into `~/.agent-workforce/sessions/<id>/mount/`
via symlinks; the harness sees the mount as its cwd. Writes inside the
mount sync back to the real repo on exit. Ignore semantics follow
gitignore — `.claude` hides nested variants like `packages/foo/.claude/`
too. `.git` is included in the mount (one-way project→mount sync) so git
commands work inside the sandbox; mount-side commits are discarded on
cleanup, so push to persist work.

**Opt out:** `--install-in-repo` runs against the real cwd and stages
skills into the repo's harness-conventional dirs. Useful when you want to
inspect installed skills on disk or when the mount conflicts with
something else (network filesystem, etc.).

**Caveat:** user-level harness config in `~/.claude/` etc. still loads
inside the session — the mount hides the *repo's* context, not the
user's. If you need to hide user-level config too, launch under a scratch
`$HOME`. See **[packages/cli/README.md#sandbox-mount](./packages/cli/README.md#sandbox-mount)**
for the full mount layout and semantics.

## Packages
Expand Down
65 changes: 37 additions & 28 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -392,11 +392,11 @@ persona session, add it to the persona's `mcpServers` block.
## Interactive

```sh
agent-workforce agent [--install-in-repo] [--clean] <persona>[@<tier>]
agent-workforce agent [--install-in-repo] <persona>[@<tier>]
```

`--install-in-repo` and `--clean` are mutually exclusive — see
[**Clean mode**](#clean-mode) below.
By default, claude and opencode sessions run inside a sandbox mount — see
[**Sandbox mount**](#sandbox-mount) below. `--install-in-repo` opts out.

1. Resolves the persona, walks the cascade, resolves `$VAR` refs.
2. **Stages skills outside the repo by default** (claude interactive only —
Expand Down Expand Up @@ -483,39 +483,57 @@ stage dir conflicts with something else (network filesystem, read-only
into a new stage dir. A `~/.agent-workforce/cache/` content-addressed cache
is planned but not wired up.

## Clean mode
## Sandbox mount

`--clean` launches an interactive claude session inside a
By default, claude and opencode interactive sessions run inside a
[`@relayfile/local-mount`](https://www.npmjs.com/package/@relayfile/local-mount)
symlink mount that hides the repo's Claude Code configuration from the
session — so the model sees persona context + user-level context, and
nothing the repo itself declares.
symlink mount that hides repo-level harness configuration from the session
and routes skill-install writes into the sandbox — so the model sees
persona context + user-level context, and nothing the repo itself declares.
Codex sessions never mount (no harness-side support).

```sh
agent-workforce agent --clean <persona>[@<tier>]
```
`--install-in-repo` opts out and runs against the real cwd.

**What's hidden (gitignore semantics, at any depth):**

For claude:

| Pattern | Rationale |
| --- | --- |
| `CLAUDE.md` | Repo-level project memory |
| `CLAUDE.local.md` | Developer-local project memory |
| `.claude` | Repo Claude Code config dir (settings, agents, skills, commands) |
| `.mcp.json` | Repo-declared MCP servers |

For opencode (skill-install pollution that would otherwise leak back to
the repo):

| Pattern | Rationale |
| --- | --- |
| `.agents`, `.claude/skills`, `.factory/skills`, `.kiro/skills`, `skills` | skill.sh universal install root + per-harness symlink farms |
| `.opencode`, `.skills` | prpm `--as <harness>` output roots |
| `prpm.lock`, `skills-lock.json` | provider lockfiles |

**What's preserved:**

- **User-level context** under `~/.claude/` — `CLAUDE.md`, skills, etc.
still load. `--clean` scrubs the *project*, not the user. To exclude
still load. The mount scrubs the *project*, not the user. To exclude
user-level context too, launch under a scratch `$HOME`.
- **Persona skills.** The `--plugin-dir` passed to claude resolves to an
absolute path *outside* the mount, so staged skills from
`~/.agent-workforce/sessions/<id>/claude/plugin/` load normally.
- **Keychain auth.** `--clean` does NOT pass `--bare`; it only hides
files via the mount. Claude Code's macOS keychain login stays active.
- **Persona skills.** For claude, the `--plugin-dir` passed to the harness
resolves to an absolute path *outside* the mount, so staged skills from
`~/.agent-workforce/sessions/<id>/claude/plugin/` load normally. For
opencode, the install runs inside the mount so the writes land in the
sandbox.
- **Keychain auth.** The mount does not pass `--bare`; it only hides
files. Claude Code's macOS keychain login stays active.
- **Persona `mcpServers`.** Still passed via `--mcp-config` — unaffected
by the mount. The repo's `.mcp.json` is hidden regardless.
- **Git.** `.git` is included in the mount (one-way project→mount sync per
`@relayfile/local-mount` 0.6+'s `includeGit`). Tracked paths matching
the hidden patterns are flagged `skip-worktree` so `git status` doesn't
report them as deleted, and the patterns are added to `.git/info/exclude`
to suppress untracked-and-hidden files. Mount-side commits/refs are
sandboxed and discarded on cleanup — `git push` to persist work.

### Session layout

Expand All @@ -531,31 +549,22 @@ is generated once and both paths are derived from it:
│ ├── .claude-plugin/plugin.json
│ ├── skills → .claude/skills
│ └── .claude/skills/<name>/SKILL.md
└── mount/ ← --clean: claude's cwd
└── mount/ ← session cwd
└── <mirrored project tree, minus the hidden patterns>
```

`@relayfile/local-mount` handles mount creation, process spawn,
SIGINT/SIGTERM forwarding, write syncback, and cleanup on exit. The
agent-workforce CLI just wires the paths and passes the persona's argv.

### Interactions with other flags

- **`--clean` + `--install-in-repo` is rejected** — they ask for
incompatible things. `--install-in-repo` stages skills into the real
repo's `.claude/skills/`; `--clean` hides the real repo. Pick one.
- **`--clean` on codex/opencode is a warning no-op.** Only the claude
harness gets the mount (it's the only one whose native surface includes
the hidden patterns).

### Example

```sh
# Interactive PostHog session with the repo's CLAUDE.md, .claude/, and
# .mcp.json hidden — session sees the persona's staged skills plus your
# user-level ~/.claude/CLAUDE.md, nothing else from this repo.
export POSTHOG_API_KEY=phx_…
agent-workforce agent --clean posthog@best
agent-workforce agent posthog@best
```

On exit: mount is synced back to the real repo, then torn down; skill
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"dependencies": {
"@agentworkforce/harness-kit": "workspace:*",
"@agentworkforce/workload-router": "workspace:*",
"@relayfile/local-mount": "^0.5.0",
"@relayfile/local-mount": "^0.6.0",
"ora": "^9.4.0"
},
"repository": {
Expand Down
Loading
Loading