# ccteam
**Repository Path**: haijiun/ccteam
## Basic Information
- **Project Name**: ccteam
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-09-08
- **Last Updated**: 2026-09-08
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
Each coding CLI is brilliant alone but works in isolation — one terminal, one context, no colleagues:
- **Claude Code** — plans the deepest
- **Codex** — grinds long jobs without wobbling
- **Grok** — answers fastest
- **Kimi** — bulk work on a tiny bill
- **DSH** — hires live inside your own DeepSeek Harness web space, side by side with you
- **Pi** — one CLI over many providers (`anthropic/…`, `openai/…`), on your own machine
ccteam 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.
An afternoon on the Team page — 50 live sessions across four vendors, every delegation a traceable parent→child edge, every dollar on the ledger.
## Usage
**1 · Remote control from Telegram / Lark**
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:
```text
/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
```
Telegram is the whole console — switch projects, address any session, and one /status card shows the brain plus every delegate it hired.
**2 · Remote control from the web console**
The installer runs the daemon; `ccteam status` reprints your link (`http://:7331/?token=…`) — open it from any device on your LAN. It's a chat shell, not a dashboard:
No “create session” form — pick project · host · vendor · model in one pill and just type; the formation playbooks below prefill a whole lineup.
- six formation playbooks (commander & crews, driver & advisor, cross review, bake-off, research triangulation, cost pyramid) that prefill the launcher with a vendor lineup
- a Chat tab per session (plus a byte-faithful terminal where applicable), including a clock on the composer to queue delayed user turns above the input
- a Team page: the live delegation topology — vendor, the model and reasoning effort each session is actually running, cost, every row a real link so a parent and its delegate open side by side — plus a division-of-labor charter (the per-project `routing.md` agents read via `status`) edited in place, and a Runs tab listing every ccteam Flow run with the sessions it hired
- a DSH page that opens DeepSeek Harness Web inside ccteam: the daemon authenticates the request, starts or attaches the right local DSH web instance, and gives each logged-in user a separate DSH home
- a cost pill with daily budget caps
- a per-project ⋯ menu in the sidebar: start a session there, copy its path, or take the project out of ccteam (deregister + stop its live sessions — your directory and code are never touched)
- marketplace and settings
Everything 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):
```text
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:
```sh
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 # 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** — `/.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:
```text
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.
- Plain-language walkthrough → [orchestration guide](docs/orchestration.md)
- MCP tool reference (all six tools, faces, protocol) → [mcp.md](docs/mcp.md)
- Policy hooks & flows (the script API, run journal, evaluation loop) → [hook-dynamic-workflows.md](docs/hook-dynamic-workflows.md) ([中文](docs/hook-dynamic-workflows-cn.md))
- Every command → manual ([English](docs/usage.md) · [中文](docs/usage-cn.md))
## Inside DeepSeek Harness
ccteam also lives natively inside [DeepSeek Harness](https://www.npmjs.com/package/@deepseek-ai/dsh)'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--`): 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](docs/dsh-plugin.md) ([中文](docs/dsh-plugin-cn.md)).
## Install
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](https://docs.claude.com/en/docs/claude-code), then `claude auth login`
> - **Codex** — install [Codex CLI](https://github.com/openai/codex), then `codex login`
> - **Grok Build** — install [Grok CLI](https://docs.x.ai/build/overview), then `grok login`
> - **OpenCode** — install [OpenCode](https://opencode.ai), then `opencode auth login`
> - **Kimi Code** — install [Kimi Code](https://moonshotai.github.io/kimi-code/), then `kimi login`
> - **DSH** — install [DeepSeek Harness](https://www.npmjs.com/package/@deepseek-ai/dsh) with `npm i -g @deepseek-ai/dsh`. DSH sessions and DSH Web use `DEEPSEEK_API_KEY` when set, otherwise the identity's DSH Settings → Models config.
> - **Pi** — install [Pi](https://pi.dev/), then set your provider key and check it with `pi auth check --provider `
>
> Any one of them is enough to start. Afterwards `ccteam status` and **Settings → Hosts** report, per machine, which vendors are installed, their versions, and whether each is actually authenticated — sitting on `PATH` never counts as logged in.
**1 · One-click script**
```bash
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:
```bash
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](docs/dsh-plugin.md)).
**3 · Let an agent do it** — paste into any agent you already have:
> Install https://github.com/firstintent/ccteam — follow `INSTALL.md` in the repo.
**4 · From source** (Rust + Node):
```bash
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:
```bash
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:
- **Settings → Access** — everything that connects to ccteam, on one page: the copy-paste MCP config for external agents (a credential scoped to one project, rendered as the real config each vendor expects, or as plain text for plugin-backed flows such as DSH, listed and revocable afterwards — the secret is shown once, never again), satellite join tokens for new machines, your own Telegram/Lark bot (a numbered two-step card per platform — save the credential, then bind who the bot answers, with sender capture starting on its own), and per-user login links
- **Settings → Hosts** — each machine's vendor panel (installed / version / readiness) and one-click registration of the ccteam MCP tools into the vendor CLIs with writable config (Claude Code, Codex, Grok, OpenCode, Kimi), so even hand-started sessions can hire the team. DSH's one-click on the same page registers ccteam's plugin into your own `~/.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
- **Workflow → Marketplace** — install skills (into your user-level library `~/.ccteam/skills`; the skills tab comes first) and personas (into the project), checksum-verified; attach library skills to any message from the composer
- **DSH** — open native DSH Web as a first-class console page. Each identity runs one DSH runtime and ccteam is its second client: DSH sessions hired anywhere in ccteam are created inside that same runtime, appear live in this page's sidebar under the project's workspace, and can be opened mid-task to watch or interject — the agent's next dispatch continues the same conversation. The owner sees the real `~/.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//` 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 workflow hub — skills, personas, marketplace and MCP servers in one place, next to the project's experience ledger (turn records + role/skill fingerprints).
> The console binds to `0.0.0.0:7331` with 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 ` 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 `:7331` makes 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.
## Chaining sessions
Delegation is explicit — an agent (or you) says who does what, and the bridge handles identity, routing, delivery, and the ledger:
```text
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:**
- **Plan → build → gate** — claude decomposes and sets constraints; codex implements; a rival model reviews the diff before you merge.
- **Grind + probe** — codex holds the long job while grok answers the quick question before codex finishes a step.
- **Bulk on a budget** — fan the repetitive 80% out to kimi; keep the judgment calls on claude.
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 (`/.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.
## Project context
ccteam adds a team to your repo without taking it over:
- **Roleless by default** — the brain reads *your* `CLAUDE.md` / `AGENTS.md` through the vendor's own mechanism; ccteam never rewrites project knowledge.
- **Small footprint** — exactly `.ccteam/` (state), `.claude/agents/` (personas you install), and ccteam's own section of `.claude/settings.local.json` — never your `settings.json`.
- **Durable sessions** — ids (`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.
## Extras
- **Marketplace** — personas install from [ccteam-hub](https://github.com/firstintent/ccteam-hub) into your project's `.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).
- **HITL approvals** — spawn a session in approval mode and its permission requests reach your IM as `[approve] [deny]` buttons, through the vendor's native gate; deny blocks the tool call without killing the turn.
## Why
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:
- **No prompt injection** — personas load through the vendor's native mechanism; task text is forwarded verbatim.
- **No terminal scraping** — state comes from transcripts and structured events.
- **Measurements, never placeholders** — a context reading you see was really reported by that vendor and survives restarts; one it has not reported yet reads as unknown, not `0%`.
- **Local first** — `~/.ccteam` and your repos; no cloud in the loop.
- **Budgets guard, never kill** — daily per-vendor caps are the only automatic brake.
## Update
```bash
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](docs/usage.md#updating).)
## Uninstall
```bash
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/` and ccteam's section of `.claude/settings.local.json`.
## Support
- Questions, bugs, ideas → [issues](https://github.com/firstintent/ccteam/issues); PRs welcome.
- Telegram: [@cryptorobsu](https://t.me/cryptorobsu)
- If the team saved you an alt-tab, a star keeps the juggler juggling.
## License
MIT — see [LICENSE](LICENSE). Built on **Claude Code**, driving **Codex**, **Grok**, **OpenCode**, **Kimi**, **DSH** and **Pi**.