AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
ccteam은 기존 코딩 에이전트들을 하나의 팀으로 묶어 세션별로 작업을 생성·배포·수집할 수 있게 한다
ccteam turns the coding agents you already run (Claude Code, Codex, Grok, DeepSeek Harness, Kimi, Pi) into one team — any session can spawn, dispatch, and collect work from any vendor on any machine,
개발 도구Rust · TypeScriptGitHub @firstintent직접 설치운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
ccteam turns the coding agents you already run (Claude Code, Codex, Grok, DeepSeek Harness, Kimi, Pi) into one team — any session can spawn, dispatch, and collect work from any vendor on any machine, while you steer it all from Telegram, Lark, or a browser tab. 把你在用的编程 agent 编成一支团队,跨厂商跨机器派活,Telegram/飞书/网页统一指挥。
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
ccteam
ccteam turns the coding agents you already run (Claude Code, Codex, Grok, Kimi, Deepseek Harness) into one team — any session can spawn, dispatch, and collect work from any vendor on any machine, while you steer it all from Telegram, Lark, or a browser tab.
Each coding CLI is brilliant alone but works in isolation — one terminal, one context, no colleagues:README 전문 보기 ↗Each coding CLI is brilliant alone but works in isolation — one terminal, one context, no colleagues:
anthropic/…, openai/…), on your own machineccteam is the connective tissue they lack — identity, routing, delivery guarantees, guardrails, a cost ledger — and leaves how the team organizes itself to prompts you version.
1 · Remote control from Telegram / Lark / Slack
Paste a bot token once (Settings → Access) and the chat becomes a full console — completion notifications, HITL [approve] [deny] buttons, and shipped files all land in the same thread. Dispatch at midnight, close the laptop, find the result at breakfast. In a group or channel the bot answers every message from allowed members — or, with one switch per IM, only when @-mentioned. On Slack every session gets its own thread: a top-level message starts a session, a reply in its thread talks only to it, so parallel sessions never interleave (commands start with ! there — !status, !model — since Slack keeps / for itself; Settings → Access creates the Slack app for you in one click):
/cd demo # pick a project; your next message talks to it
/new codex effort=high # more sessions: /new [vendor] [role] [model=…] [effort=…]
@s2 run the test suite # address any session directly
/status /sessions /stop s3 # health · fleet · cost · stop
/inbox +30m remind me … # schedule a one-shot user turn; /inbox lists · cancel dN
2 · Remote control from the web console
The installer runs the daemon; ccteam status reprints your link (http://<lan-ip>:7331/?token=…) — open it from any device on your LAN. It's a chat shell, not a dashboard:
routing.md agents read via status) edited in place, and a Runs tab listing every ccteam Flow run with the sessions it hiredEverything the console does is also /api/v1 (OpenAPI at /api/docs).
3 · Orchestrate a team from inside a claude session
Any registered session can hire the others — say it in plain language and agent / agent_read run under the hood (with an honest working / idle signal, so nobody guesses from silence):
Spawn a codex session, have it implement RFC-12 and run the tests; report back when green.
Plan this refactor, then delegate: codex implements, grok profiles the hot path in
parallel, kimi sweeps the rename across the repo. Collect everything into one summary.
Spawn a claude reviewer on s2's diff — I'm not merging until it signs off.
4 · Many machines, one console
Register a satellite with a join token (Settings → Access) — it dials out to your daemon, so a laptop behind NAT works fine. Projects are bound to a host and run where they live: spawn into the GPU-box project and its tests run on the GPU box, while transcripts, cost, and the team view stay in one console. Switching machines is just switching projects.
Satellite execution currently runs Claude sessions; the other vendors run on the daemon's machine.
5 · Orchestrate in code, not in a prompt
When the shape of the work is known, write it down instead of asking for it. A flow is a plain JS script the ccteam runner executes — agent() / parallel() / pipeline() / phase() over real cross-harness hires, every leaf its own session on the ledger:
ccteam flow new branch-review # scaffold a script + the API it can call
ccteam flow run branch-review.flow.js --args '{"base":"main"}' --budget 5
ccteam flow eval <run-id> # grade a finished run with a flow of your own
Runs are journaled, so a run survives a daemon restart and --resume picks it back up — the workers outlive the runner. --parallel / --max-agents / --max-cost are the brakes, and the Team page's Runs tab shows every run with the sessions it hired.
Independently, a policy hook — <project>/.ccteam/hooks/pre-agent, any executable, re-read on every call — gates every delegation, whether a human, an agent or a flow made it. It is handed the caller, the request and the live per-harness quota map on stdin; exit 0 allows, exit 2 denies with your stderr relayed verbatim to the calling agent, and a broken script refuses distinguishably rather than silently opening.
Under all five modes are the same six MCP tools, available to every session, to your plain hand-started CLIs once registered, and to any external agent that presents an enrollment credential over POST /mcp — one credential per vendor config or per copy-button, and the daemon issues each process its own identity when it connects, so two agents sharing a config are still two callers with their own ledger rows and their own children:
agent · agent_read · agent_stop
status (+ its discovery alias grok_claude_codex_kimi) · chat_send_file
The daemon routes and records — at-least-once notifications across restarts, idempotency keys, a child's turn written to disk before its parent is told, guardrails that refuse runaway fan-out with a reason. When a web-driven session finishes autonomous work while nobody is watching the console, the final answer is mirrored to your IM; the IM /status card shows your session's working children at a glance. It never schedules; when to delegate lives in prompts you version.
ccteam also lives natively inside DeepSeek Harness's own web UI, as one DSH client plugin — @ccteam/ccteam-ui, not a port of the console above, built with DSH's own slots, primitives and locale. Installing it once gives you three faces and an engine supervisor:
| Face | For | What it gives you |
|---|---|---|
| Workbench | People using DSH Web | A full-page ccteam workbench opened from a button at the bottom of DSH's sidebar: the cross-harness team tree (search, per-project fold/unfold, hover ⋯ menu), a native-grade conversation (streaming Markdown, tool steps, choice prompts, attachments, mid-turn model/effort switch, interrupt), and a details column — docks beside DSH's own panes or expands full-page. |
| Tools | DSH agents (the LLM) | The same six MCP tools described above, callable from inside a DSH session. |
| Transport | ccteam | The channel that lets ccteam hire a DSH session the way it hires any other harness. |
| Engine | You | The ccteam daemon itself, shipped with the plugin as a platform package (@ccteam/engine-<os>-<cpu>): installed, started and supervised from the Engine section of the plugin's settings card — state, version, Start / Stop / Restart / Update engine, a Start the engine when the plugin loads switch, the engine log. |
Install it with dsh plugin --profile web add @ccteam/ccteam-ui and restart dsh web: the plugin brings the engine, starts the daemon, and picks up your console token from ~/.ccteam on the same machine — nothing to paste. If your DSH is already running through ccteam (/new dsh, the ccteam DSH page, or agent with vendor:"dsh"), the plugin and its credentials are materialized for you. Either way it is one daemon shared with the CLI and ccteam web: the plugin attaches to a running one, never starts a second one against another ~/.ccteam, and never stops it when DSH restarts. The full setup (both install paths, coexistence rules, troubleshooting) is in the DSH plugin guide (中文).
Runs on macOS, Linux, and Windows (via WSL).
[!IMPORTANT] Bring your own coding CLI — install and authenticate at least one before you start. ccteam is the bridge, not the agent: it spawns the vendor CLIs already on the machine a project is bound to, so a vendor that is missing (or installed but not authenticated) cannot host a session.
- Claude Code — install Claude Code, then
claude auth login- Codex — install Codex CLI, then
codex login- Grok Build — install Grok CLI, then
grok login- OpenCode — install OpenCode, then
opencode auth login- Kimi Code — install Kimi Code, then
kimi login- DSH — install DeepSeek Harness with
npm i -g @deepseek-ai/dsh. DSH sessions and DSH Web useDEEPSEEK_API_KEYwhen set, otherwise the identity's DSH Settings → Models config.- Pi — install Pi, then set your provider key and check it with
pi auth check --provider <provider>Any one of them is enough to start. Afterwards
ccteam statusand Settings → Hosts report, per machine, which vendors are installed, their versions, and whether each is actually authenticated — sitting onPATHnever counts as logged in.
1 · One-click script
curl -sSL https://raw.githubusercontent.com/firstintent/ccteam/main/install.sh | sh
One static binary into ~/.local/bin, no sudo. Every install mode — the script, make install, ccteam update, and the DSH plugin — resolves the destination through the same ladder (CCTEAM_INSTALL_DIR → wherever ccteam already lives → ~/.local/bin), so an upgrade replaces the copy you are actually running instead of leaving a second one to shadow it.
2 · From DeepSeek Harness — one command, engine included:
dsh plugin --profile web add @ccteam/ccteam-ui
Restart dsh web and the plugin installs the ccteam engine from its platform package through the same ladder, starts the daemon, and shows an Engine section in its settings card. It is one shared daemon: the ccteam CLI, ccteam web and the plugin all use the same ~/.ccteam — whoever starts first wins and the others attach (details).
3 · Let an agent do it — paste into any agent you already have:
Install https://github.com/firstintent/ccteam — follow
INSTALL.mdin the repo.
4 · From source (Rust + Node):
git clone https://github.com/firstintent/ccteam && cd ccteam && make install
Start it — ccteam start runs ccteam in the background and keeps it running after you close the terminal (make install and the DSH plugin already did this for you). It is the only way to start the daemon, and it is idempotent: a second ccteam start — from a shell, a script, or the DSH plugin — reports the one already running instead of starting another. Manage it any time:
ccteam start # start in the background; prints your web console link
ccteam daemon status # is it running, and on which version?
ccteam daemon restart # restart it
ccteam stop # stop it (your sessions come back next time you start)
ccteam daemon logs -f # watch the logs live
After you reboot your computer, run ccteam start again to bring ccteam back.
Configure in the browser — open the printed link (also shown by ccteam status), create a project, and just type; the session is born on your first message. Then:
~/.dsh web profile instead (a DSH session of yours can also orchestrate after pasting an Access credential); Pi gets the team tools through a ccteam-owned bridge loaded into the sessions ccteam spawns, so a pi you start by hand in a shell is left completely untouched~/.ccteam/skills; the skills tab comes first) and personas (into the project), checksum-verified; attach library skills to any message from the composer~/.dsh space (ccteam attaches to a DSH Web already on 127.0.0.1:3080 when present); each regular user gets an isolated $CCTEAM_HOME/runtime/dsh/web/<user>/ space with the ccteam client plugin preloaded. It works out of the box by following this machine's DSH login until the user changes DSH Settings → Models; the whole identity — menu sessions and hires alike — runs on that one config. User-installed DSH plugins are preserved.The console binds to
0.0.0.0:7331with token auth, no TLS — keep it on a trusted LAN. DSH Web uses a companion listener on the web port + 1 by default; override it with--dsh-web-bind <addr:port>or disable it with--dsh-web-bind off. If you put HTTPS in front of ccteam, proxy the companion listener too (usually a second HTTPS port or subdomain). Proxying only:7331makes the DSH iframe mixed-content fail, and DSH Web cannot be safely mounted under a path prefix.
DSH Web honesty: native DSH turns run inside DSH, not as ccteam sessions, so they do not appear in the ccteam cost ledger — including turns you type into a hired session from the DSH side (ccteam records only the turns it routed; the DSH home keeps the full conversation). Work delegated through the ccteam DSH plugin is ledgered normally. Tenant DSH Web is same-OS-user isolation: DSH agents can run shell commands, and self-installed DSH plugins are arbitrary npm code with the same trust level as that user account.
Delegation is explicit — an agent (or you) says who does what, and the bridge handles identity, routing, delivery, and the ledger:
agent{vendor:"codex", title:"impl", task:"implement RFC-12, run tests, report"}
agent{vendor:"grok", title:"probe", task:"profile the hot path", wait:120}
agent{vendor:"kimi", title:"chore", task:"apply the rename across every module"}
Async by default: the completion notification lands in the parent's chat like a colleague reporting back. wait is for sub-minute answers you need inline.
Common workflows:
Who gets what starts from facts, not guesses: one status call is the roster — vendors installed, authenticated, and in-budget on the project's host, each one's models and reasoning-effort levels as it last declared them, and your routing notes (<project>/.ccteam/routing.md over the global fallback).
Every spawn surface takes model and effort for every vendor and forwards both verbatim — the vendor owns the verdict on its own values, so a level it refuses comes back as a real error instead of a session quietly running at the default. Omit them and the vendor's own defaults hold. The ladders differ (claude low…max, codex low…xhigh, grok low|medium|high, kimi low|high|max, and pi's is per model — it declares which levels the chosen model actually supports), so ask rather than guess: status for agents, GET /api/v1/models for programs, and the web composer's menus render from the same source.
ccteam adds a team to your repo without taking it over:
CLAUDE.md / AGENTS.md through the vendor's own mechanism; ccteam never rewrites project knowledge..ccteam/ (state), .claude/agents/ (personas you install), and in .claude/settings.local.json only the keys you ask for (a hub plugin you enable, an /effort you pin) — never your settings.json, and no hooks (unless you pick the frozen terminal protocol, which installs its own).s1, s2, …) survive daemon restarts and cold-resume from disk; state is plain files in your repo. A session you are not talking to releases its harness process after an idle window (default one hour, matching the prompt-cache TTL) and comes straight back on your next message, on the same id and the same conversation — so a fleet of thirty sessions costs thirty transcripts, not thirty resident processes. One session, one process: a restart never kills an agent mid-turn and never starts a second one beside it — the daemon lets the process finish, queues what you send it meanwhile, recovers the answer it gave from the vendor's own record, and resumes the session by id..claude/agents/; skills install into the user-level global library ~/.ccteam/skills (nested ids, whole-repo sources via ccteam skill source add), then attach to sessions per message — the library never links or copies into a project, while project-own skills live in .agents/skills/ as normal git-visible files (ccteam skill ensure-project). Everything is fetched from pinned upstreams, sha256-verified, copied verbatim, never executed. Vendor-native Claude Code plugins are delegated to Claude Code itself (ccteam only flips the two settings keys).[approve] [deny] buttons, through the vendor's native gate; deny blocks the tool call without killing the turn.Seven excellent coding CLIs shipped in two years, and each assumes it's alone. The result: you, alt-tabbing between vendors, re-pasting context, playing message bus. The fix isn't a framework on top — the vendors' harnesses are already great. It's the connective tissue they lack: identity, routing, delivery, cost, observability, across vendors and machines. That's ccteam — cc for the Claude Code it grew out of, team for what your agents become.
It stays deliberately underneath:
0%.~/.ccteam and your repos; no cloud in the loop.ccteam update # update in place; restarts the daemon onto the new binary
ccteam status shows your version and flags a newer release. From DSH, the plugin's Engine section does the same with Update engine (the engine from its platform package, through the same drain + restart + verify); dsh plugin --profile web update @ccteam/ccteam-ui updates the plugin itself. (Details: usage.)
curl -sSL https://raw.githubusercontent.com/firstintent/ccteam/main/install.sh | sh -s -- --uninstall
rm -rf ~/.ccteam # state, secrets, hub cache — keep it if you may return
Per project, delete .ccteam/ — or, before uninstalling, run ccteam project rm --purge <slug>, which also strips any hook entries or plugin pin an older ccteam left in .claude/settings.local.json.
MIT — see LICENSE. Built on Claude Code, driving Codex, Grok, OpenCode, Kimi, DSH and Pi.