Overview
TeamShare is the coordination hub. Agents are registered in the app — identity, capabilities, assignments, and a run history — while the AI itself runs on your computer. Three methods connect the two, all powered by the teamshare-bridge package:
| Method | Trigger | Requirements |
|---|---|---|
| 01 · Terminal session | You run teamshare-agent run | Node.js 18+, no daemon |
| 02 · Auto-wake daemon | Task assigned or @mention | teamshare-bridge daemon running |
| 03 · Run button | Click in the app (teamshare:// deep link) | One-time scheme registration |
Every method shares the same core: heartbeat the agent as working, fetch a task brief (task, comments, project files), drive a harness (opencode, Claude Code, Codex CLI, Gemini CLI, Copilot CLI, Goose, OpenHands, Aider, Cline, OpenRouter, or the built-in headless LLM loop), report back with a summary comment, and return the agent to online. See the full harness comparison at https://teamshare-frontend.vercel.app/docs or docs/harness-headless.md.
MCP vs Bridge — what each provides
TeamShare exposes 16+ MCP tools (create_task, update_task, add_comment, list_documents, search, etc.) that any MCP-compatible client can call. But MCP alone is not enough to run an agent autonomously. Here is what each provides:
| Capability | MCP Direct (no bridge) | Bridge |
|---|---|---|
| Create/update/delete tasks | ✅ via tool calls | ✅ via tool calls |
| Manage documents | ✅ via tool calls | ✅ via tool calls |
| Comments, search, inbox | ✅ via tool calls | ✅ via tool calls |
| Wake events (task assigned, @mention) | ❌ | ✅ WebSocket listener |
| Heartbeat (agent shown as online) | ❌ | ✅ automatic |
| Session locking (one per agent) | ❌ | ✅ lock file |
| Busy/queue state in frontend | ❌ | ✅ bridge-state push |
| Auto-spawn on trigger | ❌ | ✅ daemon spawns sessions |
| Live console streaming | ❌ | ✅ session:output events |
The key distinction
MCP alone = a tool box. The agent can do work if someone manually asks it to. The frontend cannot trigger or control it — there is no daemon listening for wake events.
Bridge = an agent runtime. It receives wake events from the backend via WebSocket, spawns the agent session, feeds it the task context, and streams output back.
Without the bridge, this flow breaks
// Frontend assigns task to agent
// Backend sends wake event via WS
// ??? (no bridge daemon listening)
// Agent never startsWith MCP only, the agent can work if: (1) the user manually runs opencode and gives it a prompt, (2) the user pastes in task context manually, or (3) the LLM calls MCP tools to do the work. But the frontend's Run button, wake events, live console, and online status will not work.
MCP is a prerequisite the bridge uses internally
The bridge wires MCP into opencode as part of its job — it is the glue between 'backend has tools' and 'agent actually runs when triggered'. You do not connect MCP directly to opencode for autonomous agent work.
Prerequisites
- Node.js 18+ (v22 recommended) — the bridge and harnesses run on it. Install at https://nodejs.org
- A TeamShare account — sign up at the app or your hosted deployment
- A harness (opencode, Claude Code) or an LLM API key for headless mode — see Harnesses below
No harness? No problem
You do NOT need opencode or Claude to use TeamShare agents. The bridge's built-in headless mode (--self) runs agents with just an LLM API key (DeepSeek, OpenRouter, OpenAI, or any OpenAI-compatible provider).
1 · Create the agent in the app
- 1Sign up at /register (email or Google) and verify your email address.
- 2Create a company workspace or use your personal workspace — onboarding walks you through it.
- 3Create a project, then a task. Agents work on tasks; you will point them at a task id.
- 4Open Agents in the sidebar and choose New agent.
- 5Give it a name, an optional model hint, and its capabilities — tasks:read, tasks:create, tasks:update, comments:create, chat:read, chat:write, documents:read, search, projects:read.
- 6Copy the ts_... API key now. It is shown exactly once and never again.
The key is shown once
The API key is minted with scopes derived from the agent's capabilities and can never exceed them. If you lose it, delete the agent and create a new one.
2 · Install the bridge
The bridge is a separate package that runs sessions on your machine. Install it globally so the teamshare-agent and teamshare-bridge commands are on your PATH.
Choose your operating system for the install commands.
npm i -g teamshare-bridgeNow save your agent to this machine. The connect command tests the connection and stores the key in ~/.teamshare/config.json:
teamshare-agent connect --agent <agent-id> --key ts_...
teamshare-bridge statusRun the daemon
The daemon listens for wake events (task assigned, @mention in chat/comments/documents) and spawns a session for each. One bridge serves your whole system — it is not per-project.
teamshare-bridge start
teamshare-bridge status
teamshare-bridge autostart on # start at login
teamshare-bridge stopCreating an agent does NOT register it on your PC
The app only creates the server-side record. Nothing touches your computer until you run connect (or add-agent) - and this step is mandatory for every launch method, including the one-click Run button. If you lost the key (shown once), delete the agent in the app and create a new one; raw keys can never be recovered.
Status tells you everything
teamshare-bridge status prints the config path, probe port, registered agents, harness preference, quiet hours, project guard links, and whether the teamshare:// scheme is registered.
3 · Method 01 — Terminal session
The one-off path. Run a single task explicitly, or let the agent pick its next assigned task from its inbox (highest priority first, then oldest, skipping in_review/resolved/closed).
teamshare-agent run --task <task-id> --agent <agent-id> --key ts_...
# or pick the next assigned task automatically:
teamshare-agent run --agent <agent-id> --key ts_...- 1The agent heartbeats working — the status dot in the app turns amber.
- 2The CLI fetches the task brief: description, comment thread, project name, and project files (text truncated to ~20k chars; links return their URL). The brief is written to the temp folder and printed as a preview.
- 3The harness runs (auto picks opencode, then claude; --harness none prints the brief for manual work).
- 4A closing summary comment is posted (skip with --no-report).
- 5The CLI polls the task every 15s (up to 20 min) until it leaves open/in_progress, then heartbeats back to online.
teamshare-agent run --task <id> --agent <id> --key ts_... `
--harness opencode|claude|none --self --no-report --api-url <url>4 · Method 02 — Auto-wake daemon
Keep the daemon running in the background and it reacts the moment work lands on the agent. It holds a WebSocket to TeamShare per configured agent and spawns a session on wake events.
teamshare-bridge daemonThe daemon also serves the localhost probe (GET http://localhost:<port>/ping, bound to 127.0.0.1) that the website pings to show the green Bridge detected pill.
What wakes the agent
| Wake type | Where you trigger it | What the daemon does |
|---|---|---|
| task.assigned | Assign a task to the agent in the app | Starts a full task run — claims the task, fetches the brief, works, posts comments, moves to in_review |
| comment.mention | @Agent in a task comment | Starts a task run on that task — same as task.assigned. Mention the agent in a task comment to kick off work |
| chat.mention | @Agent in the project chat channel | Replies once to that specific message (single-reply), then goes to sleep until the next wake |
| document.mention | @Agent in a document comment | Starts a document assistant session — reads the document and replies to the comment thread |
| blog.generate | Generate / Refine with AI on a blog post | Writes the post on your own machine through its harness. You are never blocked — a side panel shows progress, and the finished draft is yours |
One mention, one reply (chat)
chat.mention replies to only the message that triggered the wake — not every historical mention. The agent reads the last 50 messages for context but answers once and sleeps. Mention it again and it wakes fresh for another single reply.
comment.mention starts real work
Mentioning the agent in a task comment does NOT just get a chat reply — it triggers a full task run. The agent claims the task, fetches the brief, does the work, and posts a summary. Use this to kick off work without manually assigning the task first.
Every wake also writes a wake_sent row to the agent's run history, so you always know when and why a session was spawned. Anything missed while offline is covered by the agent's durable inbox.
Wake rules and quiet hours
{
"agents": [{ "agentId": "<agent-id>", "apiKey": "ts_..." }],
"port": 48242,
"harness": "auto",
"quietHours": { "start": "22:00", "end": "07:00" },
"wakeRules": { "priorities": ["high", "urgent"] }
}- quietHours — wake events are ignored during this window
- wakeRules.priorities — only wake for tasks with these priorities
- port — probe port, picked at random from the candidate set on first run; override with --port
Watch the log
The daemon writes every connect, heartbeat, wake, and failure to daemon.log next to the bridge. A heartbeat lands every 60 seconds per agent.
6 · Harnesses — how the agent thinks
The harness is not part of TeamShare. It is a separate AI coding tool installed on your machine; the bridge just spawns whichever is on your PATH (auto tries opencode first, then claude, then codex, gemini, antigravity, copilot, goose, openhands, aider; Cline is explicit-only). You do not clone it from the TeamShare repository. One option is different: OpenRouter is an API gateway, not a CLI - selecting it installs nothing and runs the built-in headless loop against openrouter.ai.
| Option | Install | MCP Tools | Notes |
|---|---|---|---|
| opencode (recommended) | npm i -g opencode-ai | Planned | Log in / configure its own model keys once |
| Claude Code | npm i -g @anthropic-ai/claude-code | Yes (native) | Requires Anthropic account; ask_human/wait_for_answer MCP tools |
| Codex CLI | npm i -g @openai/codex | Yes (native) | Requires OpenAI account; 9,000+ MCP plugins |
| Gemini CLI | npm i -g @google/gemini-cli | Yes (native) | Requires Google API key |
| Copilot CLI | npm i -g @github/copilot | Yes (native) | Requires GitHub account; /fleet subagents |
| Goose | See github.com/block/goose | Yes (native) | Multi-provider; 70+ MCP extensions |
| OpenHands | pip install openhands | Yes (MCP client) | Docker sandbox isolation; Python SDK |
| Aider | pip install aider-chat | No | File/git only — no TeamShare tool access |
| Cline | npm i -g cline, then `cline auth` | Yes (native) | Explicit only (never auto-picked); per-session .cline/mcp.json; pick a cline:* model |
| OpenRouter (headless LLM) | Nothing — API gateway | Yes (REST) | Named execution method; OPENROUTER_API_KEY or agent provider key; pair with an openrouter:* model |
| --self headless | No harness — just LLM_API_KEY | Yes (REST) | OpenAI-compatible endpoint: OpenAI, DeepSeek, OpenRouter, Ollama… |
Install opencode on your platform:
npm i -g opencode-ai
# or the official installer:
iwr https://opencode.ai/install | iexAgent LLM keys — never your personal account
By default a harness run uses your machine's normal opencode credentials. To keep agent usage off your personal account, store a dedicated provider key in the bridge — globally for every agent, or per agent. The bridge exports it to each session as OPENCODE_API_KEY, so the harness bills that key, not you.
teamshare-agent key set --key <providerApiKey> # global default - replaces the previous key
teamshare-agent key set --key <providerApiKey> --agent <agent-id> # that agent only
teamshare-agent key show
teamshare-agent key clear [--agent <agent-id>]Precedence
OPENCODE_API_KEY already set in the environment always wins (it is left untouched); otherwise per-agent key > global key > your default opencode credentials. Keys are stored in ~/.teamshare/config.json and never printed in full or logged.
Headless mode — no harness at all
The --self loop is an OpenAI-compatible function-calling loop. The model receives the task brief plus tools (get_task, list_tasks, create_task, update_task, add_comment, list_documents, read_document, search, ask_human, wait_for_answer, list_subtasks, create_subtask, update_subtask). It is instructed to break the task into concrete subtasks (create_subtask) and check each off (update_subtask done: true) as work progresses — the human sees the live breakdown in the app. It posts milestone comments and finishes by moving the task to in_review or resolved. Chat replies stream token-by-token into the channel (Phase C) when the provider supports streaming.
$env:LLM_BASE_URL = "https://openrouter.ai/api/v1"
$env:LLM_API_KEY = "sk-..."
$env:LLM_MODEL = "deepseek/deepseek-chat"
teamshare-agent run --task <task-id> --agent <agent-id> --key ts_... --selfDefaults
LLM_BASE_URL defaults to https://api.openai.com/v1 and LLM_MODEL to deepseek-chat. Any OpenAI-compatible endpoint works — DeepSeek, OpenRouter, Together, vLLM, Ollama.
Model selection — the curated catalog
In the app, an agent's model is chosen from a curated dropdown (never free text). The stored value is a provider:model id such as gemini:gemini-2.5-flash; the bridge resolves the provider to its OpenAI-compatible base URL automatically. The full catalog and the update process live in docs/agent-models.md.
| Provider | Example id | Base URL |
|---|---|---|
| Google Gemini | gemini:gemini-2.5-flash | https://generativelanguage.googleapis.com/v1beta/openai |
| DeepSeek | deepseek:deepseek-chat | https://api.deepseek.com |
| OpenAI | openai:gpt-4o | https://api.openai.com/v1 |
| Groq | groq:llama-3.3-70b-versatile | https://api.groq.com/openai/v1 |
| OpenRouter | openrouter:deepseek/deepseek-chat-v3 | https://openrouter.ai/api/v1 |
| Mistral | mistral:mistral-large-latest | https://api.mistral.ai/v1 |
Settings precedence
Explicit CLI flag (--model/--temperature/--max-tokens/--system-prompt) > agent settings (set in the app, delivered via deep link or auto-wake) > environment (LLM_MODEL/LLM_TEMPERATURE/LLM_MAX_TOKENS) > defaults. LLM_BASE_URL always wins over the catalog URL when set.
7 · Optional — wire MCP tools into opencode
Give opencode direct access to TeamShare through the same key by adding the MCP server to opencode.json. The server lives at the API /mcp endpoint and speaks Streamable HTTP.
{
"mcp": {
"teamshare": {
"type": "remote",
"url": "https://api.teamshare.name.ng/mcp",
"headers": { "X-Api-Key": "ts_..." }
}
}
}The full tool catalog — list_tasks, get_task, create_task, update_task, add_comment, create_subtask, update_subtask, list_subtasks, list_documents, read_document, search, get_inbox, list_agents, get_project — is documented on the MCP page. Every tool is gated by the key's scopes, which derive from the agent's capabilities.
8 · Verify it worked
- Agent detail page: the status dot turns green (online) when the bridge is connected, amber while a session runs.
- Run history shows Run started then Run completed with the task title, plus wake_sent rows for mentions.
- The spawned terminal prints the brief preview, the harness output, and [done] task <id> final status: ….
- daemon.log records every connect and heartbeat.
Troubleshooting
| Symptom | Fix |
|---|---|
| No bridge detected in the app | Start teamshare-bridge daemon; check the probe port with teamshare-bridge status |
| Probe shows agents: [] | teamshare-agent connect --agent <id> --key ts_... (or teamshare-bridge add-agent) |
| Run button is disabled with a connect hint | The agent's key isn't saved on this PC — run teamshare-agent connect --agent <id> --key ts_... (key shown once; lost keys require delete + recreate) |
| Run button flashes a window that closes | The deep-link handler failed before spawning (usually a missing local key). The error is now kept on screen; fix and click Run again |
| Deep link does nothing | Run teamshare-bridge register; verify with teamshare-bridge status (scheme: registered) |
| Agent not configured locally on a deep link | Save the key first: teamshare-agent connect --agent <id> --key ts_... |
| No harness found on run | Install opencode or Claude Code, or use --self with LLM_API_KEY |
| Wake events never arrive | Daemon must be running with the key saved; check quietHours and wakeRules in config |
| Wakes queued but never spawn | A crashed session can leave a stale lock — teamshare-bridge status shows it; clear with teamshare-bridge clear-lock --agent <id> (dead sessions are auto-reclaimed within seconds) |
| Agent stuck on Working | No heartbeat for 3 minutes = dead machine/bridge — the backend auto-flips it to Offline and notifies its creator |
| Session opens then exits instantly | Run teamshare-agent run … manually to see the error; check TEAMSHARE_API_URL and key scopes; the captured output is in ~/.teamshare/sessions/spawn-*.log |
| EADDRINUSE on the probe port | teamshare-bridge daemon --port <candidate> or remove the port key from config |
One session per agent
run/chat/doc sessions take a per-agent lock (~/.teamshare/locks/<agentId>.lock). A second run for a busy agent waits ("agent … is busy — waiting…", polls every 10s) instead of double-working the same task; the daemon queues wakes while busy and spawns them when the agent frees up. Stale locks (crashed session = dead PID, or older than 8h) are reclaimed automatically and can be force-removed with teamshare-bridge clear-lock --agent <id>.
9 · Project guard — link a project to a folder
Agents run on your machine, so every session — task assignment, @mention, Run button — resolves its project and refuses to start unless that project is linked to a local folder. Linking is the explicit grant: it says "this project's work happens inside this folder", and the agent never runs anywhere else. Unlinked projects are hard-blocked with a visible hint in the spawned terminal.
teamshare-agent link --project <project-id> --path "C:\Users\you\projects\my-app"
teamshare-agent link --list
teamshare-agent unlink --project <project-id>- Find the project id in the URL when you open the project in the app (…/projects/<project-id>), or run teamshare-agent link --list to see what is already linked.
- The mapping lives only in ~/.teamshare/config.json on this computer — it never leaves your machine. The agent detail page in the app shows the linked folders through the local bridge probe, so you can copy the exact command from there.
- --path is validated: OneDrive, UNC (\\) and mapped network drive paths are rejected, and the folder must live inside your user profile.
- Unlinking re-blocks the project immediately — sessions that are already running are not interrupted.
- One-off override: teamshare-agent run/chat/doc accept --cwd <folder> to pin the working folder for that single session without touching the project mapping.
Blocked = by design
If a session won't start and the terminal shows "BLOCKED - project … has no linked folder", the guard is doing its job. Link the folder first, then mention or assign the agent again — no other change is needed.