tackroom · git:20261002.a92fcfa · 2026-10-02 · sha256 952323d29f44dfe8
tackroom git:20261002.a92fcfaA
Immutable. This exact content never changes and is served at /api/v1/blob/952323d29f44dfe8.
---
name: tackroom
description: Set up, inspect, and sync a private user-owned agent configuration across Claude Code, Codex, Hermes, Droid, OpenCode, Qwen Code, Pi, and OMP. Use for tackroom setup, status, sync, doctor, skill, MCP, hook, role, memory-tier, or config-root workflows.
---
# tackroom
`tackroom` is a public Go CLI. The user's canonical configuration is a separate private directory or repository.
Config precedence:
1. `--config /path/to/tackroom.yaml`
2. `$TACKROOM_HOME/tackroom.yaml`
3. `~/.agents/tackroom.yaml`
Never infer configuration from the current project. Never replace a user's config root with a public checkout.
## Commands
```bash
tackroom setup [--memory off|basic|memsearch] [--agents ...] [--yes] [--dry-run] [--json]
tackroom status [--verbose] [--agents ...]
tackroom sync [--pull] [--agents ...]
tackroom doctor [--e2e] [--agents ...]
tackroom config
tackroom config validate
tackroom config print
tackroom view [--addr 127.0.0.1:8765] [--no-open] [--secure-cookie] [--ssh-host user@host]
tackroom inspect [--no-open] [--ssh-host user@host] [--port N] [--host ADDR]
tackroom sessions [--no-open] [--ssh-host user@host] [--port N] [--host ADDR]
tackroom skill new <name> [--description ...]
tackroom skill list [--agents ...]
tackroom skill info <name>
tackroom skill update [name ...]
tackroom skill promote <name-or-path> [--dry-run]
tackroom publish [--target NAME] [--skills a,b] [--dry-run] [--json] [--yes]
tackroom mcp <list|add|import|remove> [options]
```
`config` (terminal TUI) and `view` (browser web UI) are the canonical authoring
surfaces. Both edit shared YAML or the machine-local overlay; effective
configuration is read-only. In `view`, each toggle applies immediately; neither
surface runs `sync` implicitly. `view` binds only to loopback and uses a session
cookie plus CSRF and origin protection. `inspect` is a separate read-mostly
HarnessKit launcher. `sessions` is a separate AgentsView launcher for transcript
search, replay, telemetry, and usage. Both integrations are optional external
tools, not tackroom dependencies.
Run `tackroom help --all` for maintenance commands and compatibility aliases. Do not use hidden aliases in new scripts or documentation.
## setup
First-run setup:
1. Creates the canonical config root when absent.
2. Extracts missing public starter assets without overwriting user files.
3. Detects supported harness binaries.
4. Scans native skill, role, and MCP locations.
5. Shows an interactive review screen: share, keep harness-specific, or skip per item; items identical across harnesses are shared automatically. Imports are copy or conversion only; originals remain untouched.
6. In non-interactive runs it falls back to sequential prompts; `--yes` imports everything without prompting, `--dry-run` prints candidates and exits without changes, `--json` emits the detection result and exits.
7. Registers the chosen memory tier.
8. Patches only the required native harness settings.
9. Runs the first sync.
The public starter contains `tackroom`, the pinned `grilling` example, six generic roles (`architect` `builder` `general` `researcher` `reviewer` `tester`), and reusable memory scripts. Personal skills, hooks, MCP servers, secrets, and memory data belong only in the private config repository.
Memory tiers:
- `off`: no managed memory hooks.
- `basic` (default): Python-3-only bounded Markdown digests under `$KNOWLEDGE_DIR/sessions/` plus recent context at session start.
- `memsearch`: the indexed SessionStart, Stop, and SessionEnd pipeline; requires `memsearch` on `PATH`.
For Hermes, the `memsearch` tier also keeps the built-in memory files and the
knowledge vault in sync: `sync-vault-to-memory.sh` runs at session start,
`session-end.sh` captures the session digest at finalize, and
`sync-memory-to-vault.sh` exports durable memory at finalize. The generic
`session-start.sh` is not registered for Hermes because its Claude-style
context response is not consumed by Hermes; Hermes injects the synchronized
built-in memory natively instead.
Verify the complete setup with `tackroom doctor --e2e`, then run
`hermes hooks doctor`. Hermes hook approval is host-local and may require one
interactive approval after setup.
## status
Reports each configured harness as detected or not detected and compares the four managed surfaces with native state:
- skills
- MCP servers
- hooks
- agent roles
Missing, drifted, conflicting, stale managed, and unrelated external entries are reported separately.
## sync
Reconciles only configured managed entries. Unrelated native content remains untouched.
For symlink-based harnesses, skills point to canonical directories under `~/.agents/skills`. Hermes uses `skills.external_dirs: ["~/.agents/skills"]`; Qwen Code uses `skills.directories: ["~/.agents/skills"]`. Both consume the canonical tree without creating a duplicate mirror.
Agent roles are canonical Markdown files under `~/.agents/agents/` and render to:
- Claude Code: `~/.claude/agents/<name>.md`
- Codex: `~/.codex/agents/<name>.toml`
- Factory Droid: `~/.factory/droids/<name>.md`
- OpenCode: `~/.config/opencode/agents/<name>.md`
- Pi with `pi-subagents`: `~/.pi/agent/agents/<name>.md`
- OMP: `~/.omp/agent/agents/<name>.md`
- Qwen Code: `~/.qwen/agents/<name>.md`
Pi always has managed skills. With `pi-subagents` installed, tackroom renders canonical roles into Pi's user agent directory. With `pi-mcp-adapter` installed, it patches canonical and Agent Plugin MCP entries into `~/.pi/agent/mcp.json`. Put pinned package sources under the Pi target's `packages` list to make `sync` reconcile `~/.pi/agent/settings.json`; Pi installs missing declared packages at startup. Tackroom does not install the Pi executable. The role and MCP files remain inert when their packages are absent. OMP is a separate target.
For MCP servers, sync patches only named canonical entries and preserves unrelated native servers. Import redacts literal environment values to `${KEY}` references; list output never prints values.
For hooks, sync registers only declared entries on harnesses with verified hook support. Host-local review and approval state remains outside tackroom; Hermes keys first-use consent by the exact event and command and reports script mtime drift through `hermes hooks doctor`.
`sync --pull` runs `git pull --ff-only` in the private canonical repository before reconciliation.
## External skills
Declare external Git sources in the private `tackroom.yaml`:
```yaml
external_skills:
- url: https://github.com/example/shared-skills
branch: main
skill_dirs: [engineering/alpha, productivity/beta]
materialize: true
```
`tackroom.lock` records exact commits and materialized ownership. `sync` repairs drift to the pin; `skill update` explicitly advances it. `doctor` audits external source content and fails on materialization drift.
## publish
`publish` is the outward analogue of external skills: it pushes canonical skills to a remote skill registry (OpenAI `/v1/skills`) and pins the returned id/version in `tackroom.lock` under `published_skills`. Declare opt-in targets with an explicit skill allowlist in `tackroom.yaml`:
```yaml
publish_targets:
- name: openai
kind: openai-skills
enabled: true
skills: [jobs, tech-search]
api_key_env: OPENAI_API_KEY # key is read from this env var, never inlined
```
`tackroom publish` uploads only allowlisted skills whose bundle content changed since the last run (content-hash idempotency: create, skip if unchanged, new version if changed). It is inert until a target sets `enabled: true`. Use `--dry-run` to preview, `--target`/`--skills` to narrow, `--json` for machine output, `--yes`/`-y` to skip the confirmation prompt. A real upload always prints a US-only / no-Zero-Data-Retention warning first; do not publish skills carrying secrets or private vault content.
## MCP management
```bash
tackroom mcp list
tackroom mcp add local --command uvx --arg pkg@1.2.3 --env KEY=value
tackroom mcp import claude-code local --agents=codex,hermes,droid,pi,omp
tackroom sync
tackroom mcp remove local
```
Use versions verified against the package registry. Keep secrets in environment variables or host-local native config, never canonical YAML.
## doctor --e2e
Runs sync, status, and doctor as one health check. It fails on drift, conflicts, invalid external pins, unsupported managed claims, or other doctor errors.
```bash
tackroom doctor --e2e
```
## view
Opens the canonical config UI in your browser: the same review-first authoring surface as `tackroom config`, served over a loopback-only HTTP listener embedded in the `tackroom` binary (no HarnessKit, Node, or separate daemon). It authors the shared YAML and the machine-local overlay, shows a read-only effective merge, guards saves by revision, and keeps sync as a separate preview/confirm step. Loopback-only bind, tokenized startup URL bootstrapped into an `HttpOnly`, `SameSite=Strict` session cookie, plus CSRF and origin checks on mutations.
It prints the tokenized URL on its own line and, when running locally, opens it in your default browser. `--no-open` suppresses the browser launch. `--addr` sets the loopback bind (default `127.0.0.1:8765`). `--secure-cookie` marks the session cookie `Secure` for HTTPS loopback access (e.g. behind a Tailscale HTTPS proxy). On a remote host, pass `--ssh-host user@host` (or run inside an SSH session, where it derives the host from `SSH_CONNECTION`) to print a ready `ssh -L` tunnel command instead of auto-opening.
```bash
tackroom view # open the config UI locally
tackroom view --no-open --addr 127.0.0.1:8765 # print the URL, do not open a browser
tackroom view --ssh-host me@box # remote: print an ssh -L tunnel command
```
Legacy HarnessKit flags on `view` (`--port`, `--host`, `--no-token`) are rejected with a one-line pointer to `tackroom inspect`; they do not launch HarnessKit.
## inspect
Launches [HarnessKit](https://github.com/RealZST/HarnessKit) (`hk serve`) as a read-mostly inspection web UI over every detected harness — skills, MCP, hooks, and configs in one place, with a security audit. `inspect` writes nothing, but HarnessKit's own enable/disable/deploy actions bypass tackroom; treat `inspect` as look/audit and reconcile any HarnessKit changes with `tackroom sync`. Requires `hk` on `PATH` (install HarnessKit separately). This launcher was `tackroom view` before v0.9.0, when `view` became the config UI.
It prints the tokenized URL on its own line and, when running locally, opens it in your default browser. `--no-open` suppresses the browser launch. On a remote host, pass `--ssh-host user@host` (or run inside an SSH session, where it derives the host from `SSH_CONNECTION`) to print a ready `ssh -L` tunnel command instead of auto-opening. Any other flags (`--port`, `--host`, `--no-token`, `--name`) are forwarded to `hk serve`.
```bash
tackroom inspect # open the inspector locally
tackroom inspect --no-open --port 7070 # print the URL, do not open a browser
tackroom inspect --ssh-host me@box --host 0.0.0.0 # remote: print an ssh -L tunnel command
```
## sessions
Launches [AgentsView](https://github.com/kenn-io/agentsview) (`agentsview serve`) as an optional local session search, replay, telemetry, and usage dashboard. AgentsView owns its index and configuration; tackroom does not sync or mutate either. Requires `agentsview` on `PATH`, installed separately.
`--no-open` maps to AgentsView's `--no-browser`. On a remote host, pass `--ssh-host user@host` (or run inside an SSH session) to suppress remote browser launch and print a loopback `ssh -L` tunnel command. Other flags are forwarded to `agentsview serve`.
```bash
tackroom sessions # open AgentsView locally
tackroom sessions --no-open --port 8080 # serve without opening a browser
tackroom sessions --ssh-host me@box --port 8080 # remote: print a tunnel command
```
## Capability matrix
| Harness | Skills | Roles | MCP | Hooks |
|---|---|---|---|---|
| Claude Code | yes | yes | yes | yes |
| Codex | yes | yes | yes | yes |
| Factory Droid | yes | yes | yes | yes |
| Hermes | yes, config-driven | no | yes | yes |
| OpenCode | yes | yes | yes | no |
| Pi | yes | yes, via `pi-subagents` | yes, via `pi-mcp-adapter` | no |
| OMP | yes | yes | yes | no |
| Qwen Code | yes, config-driven | yes | yes | yes |
Do not add a surface without a verified native adapter and focused tests.