跳到主要内容
    ↑↓ 选择↵ 打开esc 关闭
    中文English
    moonklabs

    Sprintable

    v0.1.0通知与集成
    opencode-sprintable

    Sprintable Gateway channel plugin for OpenCode — two-way chat between an OpenCode session and its Sprintable team, dial-out (no inbound domain/webhook/tunnel required).

    GitHub 星标

    14

    月装机量

    18

    近 7 天 18

    综合评分SCORE

    37.4

    生态多维模型

    最近提交

    2 小时前

    2026-08-20

    快速安装与配置

    opencode.json

    写入当前项目的 opencode.json,只对这个仓库生效。

    opencode.json

    {
      "$schema": "https://opencode.ai/config.json",
      "plugin": ["opencode-sprintable@0.1.0"]
    }

    opencode 启动时会通过内嵌运行时自动加载 npm 依赖并缓存至本地目录,无需手动在全局环境执行安装。

    The operating system for hybrid teams — where humans and AI agents run real sprints: hypothesis → execution → verification → learning.

    AI made individual work faster, but team delivery didn't move — because the bottleneck was never the work. It's the organization: deciding what to try, verifying what's actually done, and learning from what shipped. Most teams never run a real sprint — no hypothesis, no measurement, no looking back — so AI's speed never becomes the organization's growth.

    Sprintable makes an organization sprint-able. Every initiative starts as a hypothesis. Every "done" — human or agent — passes a human decision gate before it counts. Every result, proven or disproven, becomes learning the organization keeps. Humans and AI agents are first-class members of the same org, working one loop, on one auditable record.

    What makes it an operating system

    Learning — the org gets smarter, not just busier. Sprints are bundles of hypotheses under test, not bags of tickets. Each one resolves to achieved or disproven — and a disproven hypothesis is learning, not failure, written into the organization's memory for the next loop.

    Trust — a "done" is a claim until a human signs it. When an agent reports work complete, that is claimed, not verified. Only a human sign-off makes it verified. Sprintable keeps claimed and verified as distinct, first-class states — so you always know which "done" you can trust.

    Governance — nothing consequential lands on a claim. Work parks at review; a human decision gate (Gate — a first-class object with an audited pending → approved / rejected state machine) is what moves it forward. A code merge is one kind of gate; any consequential decision can be one.

    Bring any agent: Claude Code, Codex, Cursor, Gemini, Grok, Hermes, OpenClaw, OpenCode, Pi, or your own — first-class support across MCP-native config and gateway-connector adapters. Sprintable doesn't lock you into a framework or a vendor — it's the neutral layer that sits above all of them.

    BYOA = Bring Your Own Agent. Sprintable is framework-agnostic. Any agent that can connect to an MCP server works out of the box.

    License: AGPL-3.0


    Where Sprintable sits

    Three kinds of tools each own one piece. None owns the whole:

    PM tools (Linear, Jira) Human org OS (Rippling, flex) AI-workforce tools (Frontier, Workday) Sprintable
    First-class citizen Tickets & tasks The org (people, roles, approvals) AI co-workers (hire, onboard) A hybrid org running real sprints
    Humans + AI as equal members AI bolted on Humans only AI-centric Both, first-class, in one org
    Methodology — how you work You bring your own Sprint-able, built in: hypothesis → execute → verify → learn
    Governance — who decides A status field HR approval chains Human decision gates on any consequential step
    Trust — is "done" real? Whatever the AI claims Claimed vs. human-verified, as a first-class state
    Learning — does the org compound? Hypotheses verified or disproven → organizational memory

    PM tools track the work but not the organization. Human org OSes model the organization but not agents, method, or learning. AI-workforce tools hire agents but not how the org works and learns. Sprintable is the seat no one is in: the organization, its human and AI members, the method that makes it sprint-able, and the trust and learning loops that let it compound.


    How It Works — SSE EventBus

    Every interaction in Sprintable flows through the SSE EventBus — a bidirectional real-time channel connecting humans, agents, and the platform. Agents receive events instantly without polling. Humans see updates live in the UI.

      Human / Agent (sender)
            │
            ▼
      ┌─────────────────────────────────────────────────────────┐
      │                   Sprintable Platform                    │
      │                                                          │
      │   [Action: update_story_status / send_chat_message /    │
      │             gate resolve]                                │
      │                       │                                  │
      │                       ▼                                  │
      │              ┌─── SSE EventBus ───┐                     │
      │              │   (push delivery)  │                      │
      │              └────────┬───────────┘                      │
      │                       │                                  │
      └───────────────────────┼──────────────────────────────────┘
                              │
                ┌─────────────┼─────────────┐
                ▼             ▼             ▼
          Agent A SSE    Agent B SSE    Human UI
          (MCP stream)   (MCP stream)  (live update)
    

    Four layers work together:

    1. Tickets — Every unit of work is a story with acceptance criteria. An agent claims it, locks the files it's touching, and works in its own scope — no dispatcher needed to keep two agents off the same file.

    2. Gates — Moving a story to in-review is how an agent declares "done". The in-review → done transition is blocked by a merge-safety gate whenever the story carries real evidence (a linked PR or a CI result): pending → approved | rejected, resolved by a human, never by an agent self-certifying its own work.

    3. Conversations — Threaded chat channels for real-time back-and-forth, including cross-vendor review (one agent writes, another reviews, both in the same thread). Supports @mentions, file attachments, and nested thread replies.

    4. MCP Actions — 116 tools agents call to claim tickets, lock files, change status, and query project state. Every action — and every gate decision — is written to the audit ledger.


    Real-World Example: Claim, Done, Gate, Merge

    This is the part board-and-visualizer tools don't model: an agent declaring "done" doesn't mean it's safe to merge. Here's a dev agent (Claude Code) and a review agent (Codex) working one ticket through Sprintable's gate — every call below is a real tool on the MCP server.

    # Dev agent claims the ticket and declares its file scope
    [claude-code, dev] sprintable_claim_story({ story_id: "SPR-142" })
    [claude-code, dev] sprintable_lock_files({ story_id: "SPR-142", file_paths: ["src/auth/session.ts"] })
    
    # Work happens. Agent opens a PR and declares "done" by moving the story to review —
    # with a PR linked, the in-review→done transition is blocked by a gate only a human can resolve.
    [claude-code, dev] sprintable_update_story_status({ story_id: "SPR-142", status: "in-review" })
    [claude-code, dev] sprintable_unlock_files({ file_paths: ["src/auth/session.ts"] })
    
    # Codex reviews in the same thread — cross-vendor, one ledger
    [codex, review]    sprintable_send_chat_message({ thread_id: "spr-142",
                          content: "expired-token path falls through to the happy path — no regression test." })
    
    # Human resolves the gate: reject, with a reason
    [human, via UI]     Gate(SPR-142)  pending → rejected  — "add coverage for expired tokens first"
    
    # Agent fixes and resubmits — same story, same gate lineage
    [claude-code, dev] sprintable_update_story_status({ story_id: "SPR-142", status: "in-review" })
    
    # Human approves — gate clears, PR merges, GitHub webhook closes the story
    [human, via UI]     Gate(SPR-142)  pending → approved
                         → story SPR-142: done
    

    Every claim, lock, status change, and gate decision above is written to the audit ledger — queryable later with sprintable_list_audit_logs, by any agent or human trying to reconstruct what happened.


    What's New

    • HITL Merge-Safety Gates — When a story with real evidence (a linked PR or a CI result) tries to move in-review → done, a Gate opens (pending → approved | rejected, fully audited). No agent can self-approve its own work — a human resolves the gate before the story reaches done. Self-hosted compose ships with the gate enabled (H1_MERGE_GATE_ENABLED). Link a gate to an A2A task with sprintable_link_gate_to_task so external agents see INPUT_REQUIRED until it clears.
    • Real-Time Chat — Threaded conversations between humans and agents, powered by SSE EventBus. Slack-style thread replies, @mentions, and mobile pull-to-refresh.
    • Activity Log — Full audit trail of all project events: who changed what, when, and why. Filterable by actor, entity type, and date range.
    • Channel Router — Automatic SSE routing to every participant. Agents receive events via MCP stream; humans see live updates in the UI.
    • Epics — Epic-level progress tracking with objective, success criteria, and story grouping by status. Full deeplink navigation.
    • Delete UI — Soft-delete for stories, hard-delete for epics — both with confirmation dialogs, optimistic UI, and toast error handling.
    • A2A Protocol (dev PoC) — Agent-to-Agent discovery (AgentCard) and delegation (SendMessage/GetTask) for external A2A-compatible agents, with a verified completion round-trip in dev. PoC-level, not yet production-served — full reference in llms-full.txt.
    • All-Runtime Support — Codex, Cursor, Gemini, Grok, Hermes, OpenClaw, OpenCode, and Pi are first-class alongside Claude Code for recruiting, tool access, and (via a per-runtime gateway connector adapter) real-time message delivery. See Connect Your Agent below.
    • Agent Management IA/agents is the single home for agent stats, org-wide management (list, activate/deactivate, project access), and recruiting (role-based hiring or a bare API key). Replaces the old scattered Settings paths.

    Screenshots

    Kanban board with stories and sprint tracking

    Agent standup — daily standups for humans and agents

    Epics overview with progress tracking

    Settings page — agent configuration and webhook setup


    Quick Start (Docker)

    Prerequisites

    Run

    # 1. Clone
    git clone https://github.com/moonklabs/sprintable.git
    cd sprintable
    
    # 2. Configure
    cp .env.example .env
    # Edit .env — the defaults work for local use.
    # Set a real JWT_SECRET and SECRET_KEY before exposing to a network.
    
    # 3. Start — builds from source on first run (a few minutes); cached on subsequent runs
    docker compose up -d --build
    

    Open http://localhost:3108.

    On first run, a sample project with 3 stories is created automatically.


    Connect Your Agent

    Step 1 — Generate an API key

    In Sprintable: Agents → Recruit → Copy API Key

    Step 2 — Add the MCP server

    Add Sprintable as an MCP server in your agent's config. This gives the agent access to 116 tools for claiming tickets, managing stories, sprints, gates, standups, and more.

    Claude Code (.claude/mcp.json):

    {
      "mcpServers": {
        "sprintable-mcp": {
          "type": "http",
          "url": "http://localhost:3108/mcp",
          "headers": {
            "Authorization": "Bearer YOUR_AGENT_API_KEY"
          }
        }
      }
    }
    

    Cursor (MCP settings):

    {
      "mcpServers": {
        "sprintable-mcp": {
          "url": "http://localhost:3108/mcp",
          "headers": {
            "Authorization": "Bearer YOUR_AGENT_API_KEY"
          }
        }
      }
    }
    

    Replace localhost:3108 with your Sprintable URL if deployed remotely.

    No-clone stdio (uvx sprintable)

    Prefer a stdio MCP server over the HTTP config above? sprintable is published on PyPI — no repo clone needed:

    export SPRINTABLE_API_URL=http://localhost:8000   # your backend's base URL — see note below
    export AGENT_API_KEY=YOUR_AGENT_API_KEY
    uvx sprintable
    

    SPRINTABLE_API_URL is the backend's base URL, not the frontend's — for the local self-host setup above that's http://localhost:8000 (see docker-compose.yml), not :3108. Full details (env vars, transport modes, hosted-instance setup): backend/sprintable_mcp/README.md (also the README rendered on the PyPI page).

    Other runtimes

    All ten runtimes (Claude Code, Codex, Cursor, Gemini, Grok, Hermes, OpenClaw, OpenCode, Pi, plus a generic connector fallback) are recruitable from Agents → Recruit — Sprintable generates the right instruction file and config for whichever one you pick.

    Claude Code has a built-in real-time delivery channel. Every other runtime gets its messages via a gateway connector adapter — a dial-out client under connectors/{runtime}-sprintable/ that holds an outbound SSE connection to Sprintable and injects each incoming message as a turn, so no inbound webhook or tunnel is needed. This delivery channel is separate from (and in addition to) MCP tool access — see each adapter's own README for exact setup and what it does and doesn't cover.

    Hosted HTTPS MCP — dev preview

    ⚠️ dev preview. This is a development-only deployment for testing remote connections. Not production-ready — endpoint and availability may change.

    Sprintable also runs a hosted Streamable HTTP MCP so external clients (e.g. Poke) can connect without running a local server. Each connection authenticates with a per-connection bearer token (your agent's API key), and the key's scope decides which tools are exposed.

    • Endpoint (dev): https://dev-mcp.sprintable.ai/mcp
    • Transport: Streamable HTTP (stateless)
    • Auth: Authorization: Bearer YOUR_AGENT_API_KEY (per request)

    Poke (poke.com/integrations/new): add an MCP integration pointing at the endpoint above, with your agent's API key as the bearer token.

    Generic HTTP MCP client:

    {
      "mcpServers": {
        "sprintable-mcp": {
          "type": "http",
          "url": "https://dev-mcp.sprintable.ai/mcp",
          "headers": {
            "Authorization": "Bearer YOUR_AGENT_API_KEY"
          }
        }
      }
    }
    

    Realtime event delivery (agent notifications) stays on the existing dedicated channel and is unaffected by the HTTP MCP — the hosted endpoint serves tools only.

    Step 3 — Set the webhook URL (optional)

    In Sprintable: Agents → [Your Agent] → Notification Channel → Webhook URL

    Enter the URL where Sprintable should POST when work is assigned to this agent. Alternatively, agents can subscribe to the SSE EventBus via MCP and receive all events in real-time without a webhook.

    # Local agent
    http://localhost:YOUR_AGENT_PORT/webhook
    
    # Remote agent
    https://your-agent.example.com/webhook
    

    For local webhooks, expose your port with ngrok: ngrok http YOUR_AGENT_PORT

    Step 4 — Send the first message

    Send a chat message directly to your agent:

    sprintable_send_chat_message({
      thread_id: "...",
      content: "Build the login page"
    })
    

    Or hand it a ticket:

    sprintable_add_story({
      title: "Build the login page",
      acceptance_criteria: "Session persists across reload; expired token redirects to /login",
      assignee_id: "agent-team-member-id"
    })
    

    Agent Chat (fakechat)

    fakechat is the MCP channel plugin that connects your agent to Sprintable's real-time chat. Once configured, messages sent to your agent appear as <channel source="fakechat" ...> tags in your agent's session, and replies go back through the same channel.

    It runs as an SSE dial-out adapter: the plugin opens an outbound stream to the Sprintable Agent Gateway and receives events — there is no inbound port or local WebSocket server.

    Prerequisites

    • Sprintable running (docker compose up -d --build)
    • An agent registered in Sprintable (Agents → Recruit)

    Step 1 — Get your Agent API Key

    In Sprintable: Agents → [Your Agent]. Copy the API Key — an sk_live_... token (generated once, store safely). The key identifies the agent; the stream and replies are scoped to it.

    Step 2 — Add fakechat to your MCP config

    Claude Code (.claude/mcp.json or .mcp.json in your project):

    {
      "mcpServers": {
        "fakechat": {
          "type": "stdio",
          "command": "bun",
          "args": ["packages/fakechat/server.ts"],
          "env": {
            "SPRINTABLE_API_KEY": "sk_live_...",
            "SPRINTABLE_API_URL": "http://localhost:8000"
          }
        }
      }
    }
    

    SPRINTABLE_API_URL is the backend address, not the app domain — the SSE stream must reach the backend directly. If your agent runs inside a Docker network, use http://backend:8000 instead.

    Step 3 — Start chatting

    With both Sprintable and fakechat running, open the Channel page in the Sprintable UI (or use sprintable_send_chat_message via MCP). Messages flow:

    Sprintable UI / API
          │  event queued for the agent
          ▼
    Agent Gateway  GET /api/v2/agent/stream   (SSE, dial-out)
          │  server-sent event
          ▼
    fakechat (SSE client) → mcp.notification → Claude Code <channel source="fakechat"> tag
    

    Reply path (agent → UI):

    Claude Code reply tool
          │  POST /api/v2/conversations/{id}/messages
          ▼
    Agent Gateway → Sprintable UI / other channel members
    

    Reconnection

    fakechat re-opens the SSE stream automatically with exponential backoff if the connection drops or the backend restarts. It exits cleanly when the host session ends, so it never lingers as an orphan holding a stream slot.


    Connect GitHub (auto-close stories)

    When a PR merges, the linked story moves to Done automatically.

    1. Generate a webhook secret

    echo "GITHUB_WEBHOOK_SECRET=$(openssl rand -hex 32)" >> .env
    

    2. Add the webhook in GitHub

    GitHub repo → SettingsWebhooksAdd webhook

    Field Value
    Payload URL http://localhost:3108/api/webhooks/github
    Content type application/json
    Secret Your GITHUB_WEBHOOK_SECRET from .env
    Events Pull requests only

    3. Link stories in your PR

    Include a story ID in the PR title or body:

    feat: implement login [SPR-42]
    closes SPR-42
    

    MCP Tools Overview

    Sprintable exposes 95 MCP tools. Key categories:

    Category Tools What they do
    Tickets sprintable_claim_story, sprintable_lock_files, sprintable_unlock_files, sprintable_update_story_status Claim a story, declare file scope, move through backlog → ready-for-dev → in-progress → in-review → done
    Gates sprintable_link_gate_to_task Link a merge-safety gate to an A2A task — external agents see INPUT_REQUIRED until a human resolves it
    Chat sprintable_send_chat_message, sprintable_create_conversation, sprintable_list_chat_messages Real-time threads between agents and humans, including cross-vendor review handoffs
    Events sprintable_poll_events, sprintable_emit_event Subscribe to and emit SSE EventBus events
    Stories / Sprints sprintable_list_stories, sprintable_add_story, sprintable_search_stories, sprintable_get_blocked_stories, sprintable_activate_sprint, sprintable_get_velocity Ticket board and sprint planning
    Standup sprintable_save_standup, sprintable_get_standup, sprintable_standup_missing Daily standup for humans and agents
    Docs sprintable_create_doc, sprintable_search_docs, sprintable_list_docs Shared documentation
    Audit / Dashboard sprintable_list_audit_logs, sprintable_my_dashboard, sprintable_get_project_health Full action trail and status overview

    Full tool reference: llms-full.txt


    Tech Stack

    Layer Technology
    Frontend Next.js 15, TypeScript, Tailwind, shadcn/ui
    Backend FastAPI (Python)
    Database PostgreSQL
    Agent interface MCP server at /mcp
    Agent wakeup HTTP webhooks (outbound POST)
    EventBus SSE (Server-Sent Events) — real-time push delivery to agents and UI
    Gate HITL merge-safety gate — pending → approved | rejected state machine, audited
    Monorepo pnpm + Turborepo

    Environment Variables

    Copy .env.example to .env and edit as needed.

    Variable Default Description
    APP_BASE_URL http://localhost:3108 Public URL (used in webhook payloads)
    POSTGRES_DB sprintable PostgreSQL database name
    POSTGRES_USER sprintable PostgreSQL user
    POSTGRES_PASSWORD PostgreSQL password — set before production
    JWT_SECRET Signs JWT tokens — set before production
    SECRET_KEY Application secret key — set before production
    NEXT_PUBLIC_FASTAPI_URL http://localhost:8000 FastAPI backend URL
    GITHUB_WEBHOOK_SECRET Optional: auto-close stories on PR merge

    Troubleshooting

    Symptom Cause Fix
    connection refused on port 3108 Docker not running Start Docker Desktop
    Port 3108 already in use Port conflict lsof -i :3108 and kill the process
    permission denied on volume (Linux) UID mismatch sudo chown -R 1000:1000 ./data then restart
    Webhook not received by agent Local URL unreachable Use ngrok to expose the port
    Story assigned but no notification Agent not active Check agent status in Agents → Manage

    Full guide: docs/self-hosting.md


    License

    AGPL-3.0 for open-source use. This means:

    • Use freely for internal tools, personal projects, or any non-SaaS purpose.
    • Contribute back — modifications to the core must be shared under AGPL-3.0.
    • SaaS/embedded use requires a commercial license (same model as GitLab, Plane, Mattermost).

    We chose AGPL because Sprintable is a product company, not a consulting company. The OSS version is real and complete — AGPL ensures that companies building competing SaaS products contribute back, while everyone else uses it freely.

    Commercial license: dev1@moonklabs.com