Write your CLAUDE.md, skills, hooks, and MCP servers once. Use them in Claude Code, Codex, Cursor, OpenCode, and 8 more agents — on this machine and every other one. No daemon, no sign-in, no server. Just git + local files.
Built solo-first, for a team of one.
curl -fsSL https://raw.githubusercontent.com/ojspace/soloteam-cli/main/install.sh | bash
# standalone binary → ~/.local/bin. No Node, no Bun, no registry needed.
# macOS (arm64/x64) and Linux (x64/arm64) supported.Other ways in:
npm install -g soloteam-cli # once published to npm
npm install -g github:ojspace/soloteam-cli # straight from git (needs Bun to build)Needs Node 18+ (or Bun) only for the npm/git routes — the binary runs on its own.
# 1. Start here — no remote, no VPS, no theory
soloteam init --local
# 2. Check the wiring
soloteam doctor[OK ] config file exists
[OK ] root is a git repo
[OK ] config valid
[OK ] remote — local-only (no remote configured)
[OK ] agent targets — claude, codex
[OK ] mcp.yaml valid — 0 server(s)
[OK ] recall guidance — enabled
[OK ] claude hooks installed — /Users/you/.claude/settings.json
# 3. Add your first MCP server — no YAML editing
soloteam mcp add --name context7 --command npx --args "-y,@upstash/context7-mcp"
soloteam mcp list
# 4. Save + find your first lesson
soloteam learn "Port fix" --body "Stale dev server was holding :3000. Kill it, retry."
soloteam recall "port conflict"
soloteam timelineDone. Your CLAUDE.md is already fanning out to every installed agent on each soloteam pull (automatic on session start via hooks).
Local-first works. When you want a second machine in sync, point soloteam at a git repo you control:
# Option A: private GitHub repo (easiest)
gh repo create claude-config --private
soloteam init git@github.com:you/claude-config.git
# Option B: your own server
ssh you@your-server "git init --bare -b main /path/to/claude-config.git"
soloteam init you@your-server:/path/to/claude-config.git
# On the second machine:
soloteam init git@github.com:you/claude-config.git
# (pulls your CLAUDE.md, skills, hooks, MCP, learnings on first session start)How sync works: soloteam push commits tracked files and pushes to main. soloteam pull fast-forwards and delivers to every agent. Uncommitted edits → pull backs off silently instead of merging over your work. No reviewer, no merge request — you're the only reviewer.
Already on --local? Add a remote later: edit remote: in soloteam.yaml, then soloteam push.
Edit CLAUDE.md in your sync root (~/.claude by default). On next pull it lands as AGENTS.md in Codex, Cursor, OpenCode, Gemini, Copilot, and the rest — skills/, rules/, commands/, context/ come along.
soloteam agents # what pull targets on this machine
soloteam agents --all # all 12 known agents
soloteam pull # fan out now# Local (stdio) server
soloteam mcp add --name my-tools --command npx --args "-y,my-mcp" --env "TOKEN=${MY_TOKEN}"
# Remote (HTTP/SSE) server — ${VAR} secrets pass through untouched
soloteam mcp add --name my-api --url https://example.com/mcp --header "Authorization=Bearer ${MY_TOKEN}"
# Already configured in Claude/Cursor/OpenCode? Pull it in, don't retype it
soloteam mcp import --from claude,cursor,opencode
# Write to agents now (pull does this automatically too)
soloteam mcp inject
soloteam mcp inject --agent codex
# Remove one server everywhere
soloteam mcp remove my-toolsOr edit mcp.yaml directly if you prefer — same result on next pull:
servers:
- name: context7
command: npx
args: ["-y", "@upstash/context7-mcp"]
- name: my-api
transport: http
url: https://example.com/mcp
headers:
Authorization: Bearer ${MY_TOKEN}Writes ~/.claude.json (Claude), ~/.cursor/mcp.json (Cursor), ~/.config/opencode/opencode.json (OpenCode), and a managed # soloteam:begin/end block in ~/.codex/config.toml (Codex). Your hand-written entries are never touched.
soloteam learn "Stripe webhook fix" --body "Test clock needed advancing 2h. Prod was fine."
echo "..." | soloteam learn "Title" # pipe a note
soloteam learn "Title" --file ./note.md # or from a file
soloteam recall "stripe webhook" # search learnings + rules + skills
soloteam timeline # newest learnings + sessions
soloteam session save --note "fixed webhooks" --push
soloteam digest # last 7 days
soloteam digest --since 2026-09-01After a rough session (interruptions, errors, corrections), the Stop hook nudges you with the exact commands to save it. Agents auto-search before tasks once soloteam recall enable is on (default for new inits; disable opts out). Everything is local markdown under learnings/ + sessions/ — searched with plain TF-IDF, no index daemon, synced like everything else.
Coming from claude-mem? Bring your notes, keep the local model:
soloteam memory import --from-claude-mem
soloteam memory import --from ~/my-notesTwo hooks, no background process:
- SessionStart →
soloteam pull: fast-forward git pull, then copy to mirrors, fan out to agents, install hooks, inject MCP. - Stop →
soloteam push+ friction check: commit + push only if something tracked changed; separately count interruptions / tool errors / corrections and nudge once per session if the score passes your threshold.
Config lives in soloteam.yaml at the sync root:
remote: git@github.com:you/claude-config.git # or "local"
branch: main
track: [CLAUDE.md, rules/, context/, commands/, skills/, agents/, hooks/, learnings/, sessions/, mcp.yaml]
mirrors: [] # extra dirs getting a verbatim copy after each pull
agents: [] # [] = every installed agent; e.g. [codex, cursor] to pin
exclude: [] # tracked prefixes that sync but never fan out
friction: { threshold: 5, weights: { interruption: 3, error: 1, correction: 2 } }--dir <path> overrides the root ($SOLOTEAM_DIR, else ~/.claude). SOLOTEAM_HOME overrides home for agent detection. pull/push take --strict to exit non-zero instead of hook-safe silence.
| Agent | Detected via | Memory | Skills | Hooks | MCP |
|---|---|---|---|---|---|
| Claude Code | ~/.claude |
CLAUDE.md |
skills/ |
settings.json | ~/.claude.json |
| Codex CLI | ~/.codex |
AGENTS.md |
skills/ |
— | config.toml |
| Cursor | ~/.cursor |
AGENTS.md |
skills/ |
— | mcp.json |
| OpenCode | ~/.config/opencode |
AGENTS.md |
skills/ |
plugin | opencode.json |
| OpenClaw | ~/.openclaw |
AGENTS.md |
skills/ |
— | — |
| Gemini, Copilot, Aider, Windsurf, Kiro, Qoder, CodeBuddy | ~/.<id> |
AGENTS.md |
skills/ |
— | — |
Detection = home dir exists. soloteam exclude add sessions/private keeps a path synced but out of agents. mirrors: covers anything exotic.
| What | Commands |
|---|---|
| Start | init [--local | <git-url>], doctor, uninstall [--purge] |
| Sync | pull, push, status |
| Agents / hooks / MCP | agents [--all], hooks [install|list|remove], mcp [list|add|import|inject|remove [<name>]], exclude [list|add|remove] |
| Memory | learn, recall [query|enable|disable|status], timeline, memory import, session save, digest, friction-check |
| teamai-cli | soloteam-cli | claude-mem | |
|---|---|---|---|
| Built for | A team | One dev, N machines, M agents | Any agent, deep session memory |
| Sync | push → review → pull | push → pull, direct to main | Cloud sync / local worker |
| Agents | 10, team-administered | 12, auto-detected | Claude, Codex, Cursor, OpenCode… via plugin |
| Memory | Shared team KB (BM25 + graph) | Local learnings/ (TF-IDF, offline) |
Auto-captured observations (SQLite + vectors) |
| Setup | Team repo + roles | init --local, add remote later |
npx claude-mem install + sign-in |
| Runtime | Hooks + git | Hooks + git, no daemon | Hooks + local worker service |
Use teamai-cli for a real team. Use claude-mem when you want everything auto-captured and searchable. Use soloteam-cli when you want one config + memory in git, working offline, in every agent, with zero services running.
- Start here:
soloteam doctor— it names the broken piece. - Remote FAIL:
git ls-remote <url from soloteam.yaml>— SSH key/agent issues show up first. Local-only? That's fine,remote: localis valid. - Pull does nothing: by design it backs off on uncommitted edits.
soloteam pushfirst, thensoloteam status. - Hooks not firing: confirm the agent reads the
settings.jsonsoloteam wrote to, andsoloteamis onPATHin non-interactive shells. - Nudge never shows: once per
session_id. Delete the marker under.soloteam-state/friction/to re-test. - Agent not detected: launch the agent once (creates
~/.<id>), thensoloteam agents. - MCP not landing:
soloteam mcp list→soloteam mcp inject→ check the agent's native file. Hand-written entries stay; declared ones merge in. - Upgrading from 0.1.x: new tracked paths only seed on fresh
init. Add them totrack:manually; runrecall enable+mcp listto adopt.
bun install
bun run typecheck
bun test # bun:test, no extra deps
bun run build # node-compatible dist/soloteam.js for npm
bun run build:binary # standalone binary via bun compileSmall files under src/ — agents.ts, fanout.ts, hooks.ts + teamhooks.ts, mcp.ts, opencode.ts, recall.ts, timeline.ts, sessions.ts, friction.ts, one file per command under src/commands/, colocated *.test.ts.
MIT — see LICENSE.
Issues and PRs welcome. Scope rule: solo leverage only. If a feature needs a second person (reviews, roles, per-member analytics), it belongs in a team-scoped tool, not here.