teamshare-bridge
v0.17.0
Published
Local bridge for TeamShare agents - CLI session runner, auto-wake WebSocket daemon, and teamshare:// protocol handler.
Downloads
11,822
Maintainers
Readme
teamshare-bridge
The local bridge that lets AI agents work TeamShare tasks from your machine.
TeamShare is the coordination hub: agents are registered in the app (identity, capabilities, task assignments, run history). The AI itself runs here — on your computer — connected to TeamShare through three methods, all provided by this package:
| Method | Binary | Trigger | Requirements |
|---|---|---|---|
| Terminal session | teamshare-agent | You paste a command (or click "Copy run command" in the app) | Node 18+, no daemon |
| Auto-wake daemon | teamshare-bridge start | A task is assigned to your agent (or it is @mentioned) → the daemon spawns a session automatically | The daemon must be running (autostart on keeps it alive across reboots) |
| Run button (deep link) | teamshare-bridge register + serve | The TeamShare website's "Run agent" button hands off via teamshare:// | One-time registration; OS cold-launches the bridge |
All three share the same core: fetch a task brief (task, comments, project files), drive a working session (opencode / Claude / built-in headless LLM loop), and report back through the TeamShare API.
Install
Requires Node.js 18+. One shot (Windows):
irm https://raw.githubusercontent.com/dominionbanjo/teamshare-bridge/main/scripts/install.ps1 | iexOne shot (macOS/Linux):
curl -fsSL https://raw.githubusercontent.com/dominionbanjo/teamshare-bridge/main/scripts/install.sh | bashOr install directly from npm (global):
npm i -g teamshare-bridge # published package
npm i -g . # from this repoYou now have two commands:
teamshare-agent # CLI session runner (methods 1)
teamshare-bridge # daemon + protocol handler (methods 2 and 3)Run
teamshare-bridge start # daemon in the background (pid file + ~/.teamshare/daemon.log)
teamshare-bridge stop # stop it
teamshare-bridge restart # stop + start
teamshare-bridge status # pid/log/autostart + per-agent busy/idle
teamshare-bridge daemon # foreground (debugging)
teamshare-bridge autostart on # start at login: Task Scheduler (admin) or Startup-folder launcher (no admin)
teamshare-bridge autostart off # remove itQuick start
# 1. Save your agent's key (from the app: Agents → your agent → Launch Console)
teamshare-agent connect --agent <agent-id> --key ts_...
# 2a. Work one task explicitly
teamshare-agent run --task <task-id> --agent <agent-id> --key ts_...
# 2b. Or let the agent pick up its next assigned task (priority first, then oldest)
teamshare-agent run --agent <agent-id> --key ts_...
# 2c. Auto-wake: keep the daemon running, sessions spawn on assignment
teamshare-bridge start
teamshare-bridge autostart on # ...and it comes back after a reboot
# 3. Run button on the website (registers the teamshare:// scheme)
teamshare-bridge registerHeadless mode (no harness, no opencode/Claude — just an LLM API key)
LLM_BASE_URL=https://openrouter.ai/api/v1 \
LLM_API_KEY=sk-... \
LLM_MODEL=deepseek/deepseek-chat \
teamshare-agent run --task <task-id> --agent <agent-id> --key ts_... --selfThe headless loop is an OpenAI-compatible function-calling loop: the model
gets 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 3-8 real
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 /
resolved. Any OpenAI-compatible endpoint works (OpenAI, DeepSeek, OpenRouter,
Together, local vLLM/Ollama…).
One session per agent: run/chat/doc acquire a per-agent lock
(~/.teamshare/locks/<agentId>.lock, auto-released on exit, stale locks
reclaimed) and wait for a busy agent instead of starting a second session.
The daemon queues wakes for a busy agent and spawns them when it frees up;
teamshare-bridge status shows BUSY per agent.
How a session works
- Heartbeat — the agent's status flips to
workingin the app. - Brief — the CLI fetches the task (description, comment thread, project
name) and downloads project files (text files truncated to ~20k chars;
links return their URL). The brief is written to
<temp>/teamshare-task-<taskId>.mdand printed as a preview. - Work — either a harness is spawned (
opencode run "…",claude -p "…", auto-detected in that order) or the--selfLLM loop runs. - Report — a closing summary comment is posted (skip with
--no-report). - Watch — the CLI polls the task status every 15s (up to 20 min) until it
leaves
open/in_progress, then heartbeats back toonline.
Command reference
teamshare-agent
teamshare-agent connect --agent <id> --key <ts_...>
Test the connection and save the agent key in ~/.teamshare/config.json.
teamshare-agent run --task <taskId> --agent <id> --key <ts_...> [options]
Work a specific task. Without --task, picks the agent's next assigned task
from its inbox (urgent > high > medium > low, then oldest; skips
in_review/resolved/closed).
teamshare-agent chat --project <projectId> --agent <id> --key <ts_...> [--mention <token>]
Reply to every project-chat message that @mentions the agent. Replies
stream token-by-token into the channel when the provider supports it
(Phase C); the final message is still posted via the API.
teamshare-agent doc --document <documentId> --agent <id> --key <ts_...> [--mention <token>]
Document assistant (Phase F): read the document (Word/PPT/Excel/PDF text
via GET /documents/:id/extract) and reply to every comment that @mentions
the agent in its thread.
teamshare-agent continue --task <taskId> --agent <id> --key <ts_...> [--self]
Resume a previous --self session for a task (Phase E continuation).
teamshare-agent build --project <id> --agent <id> --key <ts_...> [options]
Run the build loop: work readyForDev tasks strictly in order (sortOrder
asc, createdAt asc), one at a time, fully completing each before moving on.
teamshare-agent build --project <id> --agent <id> --key <ts_...>
Full loop: work all pending tasks until the queue is empty.
teamshare-agent build ... --draft "<goal>"
Plan a build queue from a goal string. The LLM reads the project
documents, creates tasks via MCP, and orders them — then pauses
for you to review before executing.
teamshare-agent build ... --draft "<goal>" --go
Plan and execute immediately (skip the review prompt).
--once Work one task then exit
--dry-run Print the queue plan without executing
--on-fail ask|stop What to do on task failure (default: ask)
--blocked-wait <min> Wait N minutes for an answer before quitting
Prerequisites: a provider API key (LLM_API_KEY or agent settings),
a linked project folder (teamshare-agent link --project <id> --path <dir>),
and the bridge daemon running (teamshare-bridge start).
teamshare-agent --helpModel precedence: **CLI flag > agent settings (set in the app, delivered via
deep link or auto-wake) > env (LLM_MODEL/LLM_TEMPERATURE/LLM_MAX_TOKENS)
defaults**. Model ids use the curated
<provider>:<model>catalog (docs/agent-models.md) — the provider's OpenAI-compatible base URL is resolved automatically;LLM_BASE_URLalways wins when set.
teamshare-bridge
teamshare-bridge daemon [--port N]
Auto-wake listener: keeps a WebSocket to TeamShare per configured agent
and spawns a session on wake events (task assigned, @mention in a comment
or chat). Also serves the localhost probe the website detects.
teamshare-bridge register
Registers the teamshare:// URI scheme (per-user; Windows registry /
macOS app bundle / Linux .desktop). No admin rights needed.
teamshare-bridge serve "<teamshare://agent/run?runToken=...&task=...>"
OS-invoked: redeems the run token and spawns the session.
teamshare-bridge add-agent --agent <id> --key <ts_...>
Saves an agent key without testing the connection.
teamshare-bridge status [--port N]
Shows config path, port, per-agent BUSY/idle (stale locks flagged),
harness, quiet hours, scheme.
teamshare-bridge clear-lock --agent <id>
Force-removes a stale session lock. Crashed sessions (dead PID) and
locks older than 8h are auto-reclaimed; this is the manual override.
teamshare-bridge probe [--port N]
Starts just the localhost probe server (for testing).Build mode quick start
# 1. Link your project folder
teamshare-agent link --project <project-id> --path ./my-project
# 2. Plan a build queue from a goal (pauses for review)
teamshare-agent build --project <project-id> --agent <agent-id> --key ts_... \
--draft "Set up user auth: login, signup, JWT middleware, password reset"
# 3. Review the plan, then execute
# (or skip review with --draft "..." --go)
# 4. Start the build loop
teamshare-agent build --project <project-id> --agent <agent-id> --key ts_...Configuration
~/.teamshare/config.json — created on first run with defaults:
{
"agents": [{ "agentId": "...", "apiKey": "ts_..." }],
"port": 48242,
"harness": "auto",
"quietHours": null,
"wakeRules": null
}| Key | Meaning |
|---|---|
| agents | Agent id + API key pairs the daemon listens for (teamshare-agent connect / teamshare-bridge add-agent populate this) |
| port | Localhost probe port. Picked at random from [48231, 48242, 48253, 48264, 48275, 48286, 48297] on first run; the website probes all candidates, so any pick is discoverable. Override with --port. |
| harness | Preferred session driver: auto, opencode, claude, none |
| quietHours | { "start": "22:00", "end": "07:00" } — wake events are ignored during this window |
| wakeRules | { "priorities": ["high", "urgent"] } — only wake for tasks matching these priorities |
Environment variables
| Variable | Default | Used by |
|---|---|---|
| TEAMSHARE_API_URL | https://api.teamshare.name.ng | all commands |
| TEAMSHARE_WS_URL | wss://api.teamshare.name.ng | daemon + live console + streaming |
| LLM_BASE_URL | (catalog per model) | --self, chat/doc replies |
| LLM_API_KEY | — (required for --self) | --self, chat/doc replies |
| LLM_MODEL | deepseek-chat | --self (catalog ids resolve the base URL) |
| LLM_TEMPERATURE | 0.2 | --self, chat/doc replies |
| LLM_MAX_TOKENS | — (provider default) | --self, chat/doc replies |
| TEAMSHARE_ASK_TIMEOUT | 900 (seconds) | ask_human wait limit |
| TS_CHAT_ECHO | — | Debug: post canned acknowledgments (deterministic E2E) |
Live console & streaming
- Every session (
run/chat/doc) opens its own/agentssocket and emitssession:start/session:output(batched ~200ms) /session:end— the app's Live console on the agent detail page shows the output in real time, and a capped transcript is persisted server-side at the end. - Local mirror + continuation history:
~/.teamshare/sessions/(<sessionId>.jsontranscripts,task-<taskId>.jsonfor--continue). - Chat replies additionally stream into the project channel as
message:partialframes over a/chatsocket (apiKey auth) — the web UI renders a live draft bubble that is swapped for the persisted message.
The localhost probe
The website detects the bridge by calling GET http://localhost:<port>/ping
with permissive CORS (the browser can reach it from the web app):
{ "ok": true, "version": "0.1.0", "agents": ["<agent-id>"] }When the probe answers, the app shows "Bridge detected on this computer" and enables the Run agent button; otherwise it degrades gracefully to the copy-paste command.
Security model
- Agent API keys (
ts_...) are minted by TeamShare with scopes derived from the agent's capabilities and can never exceed them; the raw key is shown only once in the app. Store it viaconnect— it lives in~/.teamshare/config.json(chmod 600 on unix). - Run tokens in
teamshare://deep links are short-lived (10 min), single-use, and exchanged server-side for a session credential — the long-lived key never appears in a URL. - The bridge never sees environment-variable values; TeamShare's viewer-denied rule extends to agents automatically.
- The probe server binds to
127.0.0.1only.
Platform notes
| Platform | Terminal spawn | Protocol registration |
|---|---|---|
| Windows | cmd /c start cmd /k … (detached window, stays open) | HKCU\Software\Classes\teamshare via reg.exe, per-user |
| macOS | Terminal.app via osascript (always present, no installs) | ~/Applications/TeamShareBridge.app (CFBundleURLTypes); open the bundle once |
| Linux (desktop) | xdg-terminal-exec → gnome-terminal → konsole → xterm (first found on PATH) | ~/.local/share/applications/teamshare-bridge.desktop (x-scheme-handler/teamshare) |
| Linux (server/SSH) | Headless fallback — no window; watch via the web live console | n/a |
Troubleshooting
| Symptom | Fix |
|---|---|
| EADDRINUSE on probe | --port <candidate> or delete the port key from config; the website probes all candidates |
| "Agent not configured locally" on a deep link | Run teamshare-agent connect --agent <id> --key ts_... |
| Run button disabled with a connect hint | The agent's key isn't saved on this PC - run connect; keys are shown once (lost key = delete + recreate the agent) |
| Deep-link window flashes shut | The serve handler failed (usually a missing local key) - the error is now kept on screen via a 30s pause |
| No harness found on run | Install opencode or Claude, or use --self |
| Wake events never arrive | teamshare-bridge status; the daemon must be running and the key saved in config |
| Wakes queued but never spawn | Stale lock from a crashed session - teamshare-bridge status flags it, clear-lock --agent <id> removes it (dead locks auto-reclaim within seconds) |
| Session opens but exits instantly | Run teamshare-agent run … manually to see the error; check the API URL and key scopes; output is captured in ~/.teamshare/sessions/spawn-*.log |
Development
npm install
npm run build # tsc -> dist/
npm run typecheck # tsc --noEmit
npm run dev # watch modeRuntime dependency: socket.io-client only — everything else is Node
built-ins (fetch, http, crypto, child_process). Tests for the full loop run
against a live TeamShare API (see docs/agent-setup.md).
Project layout
src/
├── lib/
│ ├── config.ts # ~/.teamshare/config.json (port candidates, wake rules)
│ ├── api.ts # typed REST client (envelope-aware, retries, timeouts)
│ ├── brief.ts # task brief fetcher + heartbeat/report helpers
│ ├── llm.ts # --self headless function-calling loop (+ SSE streaming)
│ ├── models.ts # curated <provider>:<model> catalog -> base URL resolution
│ ├── chat-reply.ts # chat reply loop (mention-driven, streaming)
│ ├── doc-reply.ts # Phase F document assistant reply loop
│ ├── session-stream.ts # live-console streaming over /agents + local transcripts
│ ├── partial-stream.ts # Phase C message:partial draft streaming over /chat
│ └── lock.ts # per-agent session lock (~/.teamshare/locks/<agentId>.lock)
├── cli/
│ └── index.ts # teamshare-agent (connect / run / chat / doc / continue)
└── bridge/
├── index.ts # teamshare-bridge CLI (daemon/register/serve/status/probe)
├── daemon.ts # WS auto-wake listener + wake rules + busy-queueing
├── local-server.ts# 127.0.0.1 probe server (/ping, /status)
├── spawn.ts # detached terminal session spawner (+ output capture)
└── protocol.ts # teamshare:// registration + deep-link dispatchRelated docs
docs/agent-setup.md— plain-language setup guide (mirrors the app's Launch Console)docs/agent-tasks/agent-hub-connection.md(repo root) — the full agent contract: REST endpoints, MCP tools, WS events, capabilitiesdocs/agent-models.md(repo root) — curated model catalog + update processdocs/agent-capabilities.md(repo root) — provider matrix + feature menudocs/agent-roadmap-verification.md(repo root) — step-by-step E2E playbookAGENTS.md(repo root) — project conventions
