New:Microsoft Teams Notifications Are Now Available in Socket.Learn more →
Get Started

@coralai/sps-cli

Package Overview
Dependencies
Maintainers
1
Versions
535
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@coralai/sps-cli

SPS CLI — AI-driven development pipeline orchestrator

latest
npmnpm
Version
0.90.13
Version published
Weekly downloads
577
16.8%
Maintainers
1
Weekly downloads
 
Created
Source

SPS CLI — AI Agent Harness & Development Pipeline

npm license

中文文档:README-CN.md

OpenAI daemon agent: configuration, security, recovery, and operations

v0.59.0

SPS (Smart Pipeline System) drives a Claude Code worker through task cards — code, commit, push, QA, merge, all automated. Three modes:

ModeCommandWhen
Harnesssps agentZero-config — one-shot or multi-turn chat with Claude. No project, no PM.
Pipelinesps tick <project>Automated card-driven workflow with YAML-configurable stages.
Consolesps consoleWeb UI — voice-first home, kanban, logs, projects, chat, memory, plugins, system (config / processes / doctor / audit).

The headline of v0.59 is a redesigned Console: a voice-first home (speak or type to a live agent, with an animated intro and a morphing voice-orb ↔ text-input), Doubao (Volcengine) large-model TTS for speech output (remote API, configured via SPS_DOUBAO_* in ~/.coral/env), a unified System page (config / processes / doctor / audit), and a consistent Pastel-Neubrutalism theme with light/dark switching. The Wiki Knowledge Base (opt-in per project, 5-layer retrieval auto-injected into worker prompts) remains — see doc-28 and ATTRIBUTION.md.

Table of contents

Install & setup

npm install -g @coralai/sps-cli      # latest 0.65.x
sps setup                            # interactive wizard (must run once)

sps setup:

  • Creates the ~/.coral/ directory tree (projects/, memory/, …).
  • Copies bundled skills → ~/.coral/skills/ (the single skills source; the global ~/.claude/skills dir is no longer used — setup also prunes legacy link pollution there).
  • Asks for GITLAB_URL / GITLAB_TOKEN / MATRIX_* (optional) → writes ~/.coral/env, with a commented reference of optional keys (memory / voice TTS / daemon sandbox & concurrency gate) at the end — the same file the Console System page edits visually.
  • Pins the workspaces root SPS_WORKSPACES_ROOT (default ~/coral-workspaces).

Re-run safe with sps setup --force (keeps existing values as defaults).

Prerequisites: Node ≥ 18 (≥ 22 recommended — code-graph & memory index use node:sqlite); for the claude backend a logged-in claude CLI (or API key / subscription); for the openai backend codex login (subscription) or endpoints registered in ~/.coral/agent-providers.json.

Installs that are many versions behind (especially pre-0.6x / ACP-era) accumulate retired config keys, old-schema state files, and legacy symlinks that cause hard-to-debug oddities. Prefer a full clean reinstall over an in-place upgrade:

# 1) Stop everything (apps first, then the engine)
pm2 delete all 2>/dev/null            # if you used pm2
sps console --kill 2>/dev/null
sps agent daemon stop 2>/dev/null
npm rm -g @coralai/sps-cli

# 2) Move the state root aside (backup + wipe in one step)
mv ~/.coral ~/.coral.bak-$(date +%m%d)
rm -rf ~/coral-workspaces              # auto-created session workspaces (move out anything you keep first)

# 3) In ~/.claude only remove what sps put there — never the whole dir
rm -rf ~/.claude/skills                # legacy full-link pollution from old versions

# 4) Reinstall
npm i -g @coralai/sps-cli && sps setup

Keep-list before wiping (copy back from the backup as needed): claude CLI credentials (~/.claude/, don't delete the dir), codex subscription auth (~/.codex/auth.json; re-run codex login if expired), your memory store (memory/ → ~/.coral/memory/), custom skills (bundled ones reinstall automatically), and any hand-filled secrets from the old env — transcribe valid keys into the new template rather than copying the whole file (old templates contain retired keys).

Version discipline after any upgrade: CLI / console / daemon must run the same version — upgrading the npm package does not restart running processes. Run sps agent daemon restart (check for in-flight work first), restart the console, and hard-refresh the browser. Platforms embedding sps (e.g. coral-platform) upgrade their own dependency and restart their own process.

Deployment (server / from source)

For running sps-cli as long-lived services (Console web UI + IM gateway + pipeline) on a server, deploy from source. An AI or operator can follow the steps below end to end.

After installing the npm package — required extras

npm install -g @coralai/sps-cli gives you the sps CLI only. To actually run it, also provide:

  • Node ≥ 22 (code-graph uses node:sqlite; the rest of the CLI runs on ≥ 18).
  • Claude Code CLI in PATH — the worker backend drives it (sps doctor checks which claude):
    npm install -g @anthropic-ai/claude-code
    
  • Claude auth (one of): log in with claude (Pro / Max → ~/.claude/.credentials.json), or set ANTHROPIC_API_KEY, or point workers at a third-party Anthropic endpoint.
  • Run sps setup once — scaffolds ~/.coral/, installs the ACP transport @agentclientprotocol/claude-agent-acp globally, writes ~/.coral/env.
  • git — pipelines run worktrees/branches inside the target repo.

Model / subscription config lives outside the package (secrets, per machine): the official subscription (claude login) works out of the box; third-party endpoints go in ~/.coral/game-platform/providers.json; the worker's default model in ~/.coral/agents/smartarrange.json (optional).

Verify the box is ready:

sps project init demo
sps doctor demo --fix     # checks Node, claude-in-PATH, dirs, config — reports what's missing

Per-feature extras (only if used): IM gateway → ~/.coral/im/config.json; remote Console → SPS_CONSOLE_TOKEN.

Dependencies

  • Node ≥ 22 and npm (the code-graph feature imports node:sqlite — DatabaseSync — which requires Node ≥ 22; the rest of the CLI runs on ≥ 18).
  • git.
  • Claude auth for workers: either ANTHROPIC_API_KEY in the environment, or a logged-in claude CLI (Pro / Max subscription). sps setup installs the worker transport @agentclientprotocol/claude-agent-acp globally.
  • No native/compiled dependencies — @colbymchenry/codegraph and the rest are pure JS; a plain npm install is enough.

1. Clone, install, build

git clone <repo-url> sps-cli && cd sps-cli
npm install            # root dependencies
npm run build          # THE build — see warning below
sps setup              # or: node dist/main.js setup — one-time ~/.coral scaffold + skills + claude-agent-acp

npm run build runs both halves and is the only correct build command:

  • build:cli → rm -rf dist && tsc (compiles src/ → dist/).
  • build:console → cd console && npm install && vite build, then copies console/dist → dist/console-assets. The console has its own node_modules; this step installs it for you — you do not run a separate install in console/.

⚠️ Never run npm run build:cli alone. Its rm -rf dist wipes dist/console-assets, so the Console web UI breaks with a 500 / missing index.html. Always use the full npm run build.

Expose the binary, or invoke dist/main.js directly:

npm link                       # puts `sps` on PATH → dist/main.js
# or, without linking:
node dist/main.js <command>

2. Run the services

Console (web UI):

sps console                                    # local: 127.0.0.1:4311
# server: bind all interfaces + REQUIRED auth token
SPS_CONSOLE_TOKEN=$(openssl rand -hex 24) sps console --host 0.0.0.0 --port 4321 --no-open
# then open  http://<host>:4321/?token=<the-token>

SPS_CONSOLE_TOKEN gates access. When binding to 0.0.0.0, always set it — without a token the UI is unauthenticated on the network. The startup banner prints the tokenized URL.

IM gateway (sps im) — inbound + outbound bots for Telegram / DingTalk (Stream) / Feishu-Lark / Slack / Discord / Matrix, with in-chat project switching:

sps im                         # foreground; reads ~/.coral/im/config.json

Configure channels the easy way in the Console → Plugins → Channel page (left = channel list, right = settings; it writes the file for you). Or edit ~/.coral/im/config.json directly:

{
  "console": { "url": "http://localhost:4321", "token": "<SPS_CONSOLE_TOKEN>", "agentKind": "claude" },
  "adapters": [
    { "kind": "telegram", "token": "<bot-token>", "allowedChatIds": [123456789] }
  ]
}

console.url + token bridge IM plain-text messages to project-agent chat. After changing the config, restart sps im for it to take effect. (Feishu is the only adapter needing a public callback; the rest work without inbound ports.)

Pipeline:

sps tick my-app                # foreground tick loop for one project

3. Keep the services alive

sps console, sps im, and sps tick are foreground processes. Use nohup or a systemd unit for persistence:

# nohup (simple)
SPS_CONSOLE_TOKEN=<hex> nohup node dist/main.js console --host 0.0.0.0 --port 4321 --no-open > ~/console.log 2>&1 &
nohup node dist/main.js im > ~/im.log 2>&1 &

For a systemd --user service, point ExecStart=node /abs/path/sps-cli/dist/main.js console --host 0.0.0.0 --port 4321 --no-open and set Environment=SPS_CONSOLE_TOKEN=....

4. Upgrading

git pull && npm install && npm run build
sps skill sync --force         # refresh skill SOPs after an upgrade
# then restart the console + im processes so new code/routes load

Newly added Console API routes (e.g. /api/channels) only take effect after the console process restarts — rebuild alone is not enough.

Harness mode (sps agent)

Direct one-shot or multi-turn chat with Claude. No project, no PM, no Git.

# One-shot
sps agent "Explain this repo"
sps agent --output summary.md "Summarize the architecture"

# Multi-turn (daemon-backed, persistent sessions)
sps agent --chat                              # interactive REPL
sps agent --chat --name reviewer              # named session, resume later
sps agent status                              # list active sessions
sps agent close --name reviewer

# Profile + context files
sps agent --profile reviewer "Review this module" --context src/auth.ts --context src/auth.test.ts
sps agent --system "You are a release engineer" "Plan the v0.52 cut"

# Verbose
sps agent --verbose "Why did this build fail?"

--profile <name>: looks up ~/.coral/skills/dev-worker/references/<name>.md, injects as system prompt. (Different from sps skill add — that's for project-level skill linking.)

Built-in agent: claude only (Codex / Gemini support removed in v0.38). Workers communicate via ACP JSON-RPC over stdio with claude-agent-acp.

Agent skills auto-loaded by Claude Code: ~/.claude/skills/ is scanned by claude itself — including sps-pipeline, sps-memory, wiki-update, and the 24 dev/persona skills. Skill descriptions trigger lazy load; no SPS prompt injection needed for harness mode.

Daemon cwd caveat: sps console and sps agent --chat start a session daemon (~/.coral/sessions/daemon.sock) that captures process.cwd() at startup and uses it as the default working directory for all chat workers. To switch the chat's working directory, restart the daemon: sps agent daemon stop && sps agent daemon start from the desired cwd.

Console mode (sps console)

Local web UI bundled into the binary. Single-instance guard via ~/.coral/console.lock.

sps console                          # opens http://127.0.0.1:4311
sps console --port 5000
sps console --no-open                # don't auto-open browser
sps console --kill                   # stop running console
sps console --dev                    # vite dev server (development)

Pages:

PathPurpose
/projectsList all projects with status
/projects/newCreate project (Wiki toggle + worker-model picker, v0.58.3+)
/projects/<n>Pipeline editor + conf editor + delete
/boardKanban (per-column scrolling, v0.51.1+)
/workersAggregate worker dashboard across projects
/logsLive SSE log viewer
/skillsUser-level skill management
/pluginsModel endpoints + IM channels + memory backend config (v0.58+)
/systemGlobal settings + daemon status
/chatAgent chat (multi-session; per-session model picker, v0.58.3+)

Tech: Hono server on 127.0.0.1:4311, chokidar watchers pushing SSE to React 19 + Vite + Tailwind v4 + shadcn/ui frontend. Design system: Pastel Neubrutalism, locked in console/DESIGN.md.

Model selection (v0.58.3+): the worker/chat model is chosen per project / per session at creation (dropdown of configured endpoints); leaving it unset uses the global default (~/.coral/agents/smartarrange.json). Project picks are written to the repo's .claude/settings.local.json; session picks are injected per-session. sps-cli does no global model env injection — the global config is only the fallback default.

Pipeline mode (sps tick)

Fully automated card-driven workflow. One worker, one card at a time, serial. Each card walks one or more YAML-defined stages (e.g. develop → review → Done); failure halts pipeline until you remove the NEEDS-FIX label.

Create a project

sps project init my-app
# or use Console /projects/new — has a Wiki toggle (v0.51+)

Asks for: project dir, merge branch, max workers, ACK timeout, optional GitLab remote, optional Matrix room.

Generates:

~/.coral/projects/my-app/
├── conf                              # mode 600 — your active config
├── conf.example                      # full reference (read-only docs)
├── pipelines/
│   ├── project.yaml                  # default 1-stage pipeline (develop → Done)
│   └── sample.yaml.example           # heavily-commented YAML reference
└── pipeline_order.json               # active pipeline pointer

In the target repo (PROJECT_DIR):

.claude/CLAUDE.md                     # worker rules (auto-installed)
.claude/skills/                       # symlinked from ~/.coral/skills/
.claude/settings.local.json           # Claude Code local config
wiki/                                 # if WIKI_ENABLED — see doc-28
ATTRIBUTION.md                        # if WIKI_ENABLED

Run

sps tick my-app                      # foreground tick loop
sps pipeline start my-app            # alias
sps pipeline stop my-app             # graceful stop (alias: sps stop my-app)
sps stop --all                       # stop all running ticks
sps status                           # all projects

Pipeline YAML

~/.coral/projects/<n>/pipelines/project.yaml — single source of truth for stages.

mode: project
git: true                            # false = non-code project, no git ops
stages:
  - name: develop
    profile: fullstack
    on_complete: "move_card Review"
    on_fail: { action: "label NEEDS-FIX", halt: true }
  - name: review
    profile: reviewer
    on_complete: "move_card Done"
    on_fail: { action: "label REVIEW-FAILED", halt: true }

Critical rules:

  • mode: project for state-machine pipelines; mode: steps for one-shot custom (use sps pipeline run <name>).
  • Each stage's on_complete must point to the next stage's target state.
  • Last stage's on_complete: "move_card Done".
  • Don't write agent: field — it's silently ignored (v0.38+ Claude is the only worker).
  • trigger and card_state are auto-derived per stage.

Field reference: see ~/.coral/projects/<n>/pipelines/sample.yaml.example (auto-generated, comment-rich) or doc-17.

Card lifecycle

Backlog → Todo → Inprogress → [QA / Review] → Done
   ↑↓                  ↓ fail
Planning           NEEDS-FIX (halt)
(manual park, v0.51.9+)

v0.51.10: caller-aware default state.

  • sps card add (CLI / agent / API default) → Backlog(自动跑)
  • Console "新卡片" 表单(人在 UI 操作) → Planning(暂存,等用户拖到 Backlog)

CLI 用户想暂存:sps card add ... --draft。Console 用户想立即跑:勾"立即派发执行"。 卡片严格按 seq 排序;不再有 pipeline_order.json。

Default states (configurable via YAML pm.card_states).

sps card add <p> "Title" "Description"
sps card add <p> "T" "D" --skills python,backend --labels feature

sps card dashboard <p>               # CLI table
                                     # console: /board?project=<n>

sps card mark-started <p> <seq>      # called by Claude Code UserPromptSubmit hook
sps card mark-complete <p> <seq>     # called by Claude Code Stop hook

sps reset <p>                        # reset all non-Done cards
sps reset <p> --card 5,6,7
sps reset <p> --all                  # full reset incl. Done + worktrees + branches

Card label vocabulary

LabelMeaningSet by
AI-PIPELINERequired to enter pipelineUser on creation
STARTED-<stage>ACK signal — Claude received the promptUserPromptSubmit hook
COMPLETED-<stage>Worker finished a stageStop hook
CLAIMEDStageEngine reserved a worker slotEngine
NEEDS-FIXWorker failed; pipeline haltedEngine
BLOCKEDExternal dep; pipeline skipsUser
WAITING-CONFIRMATIONWorker waiting on user inputEngine
STALE-RUNTIMEInprogress > timeoutMonitorEngine
ACK-TIMEOUTClaude never ACK'd within WORKER_ACK_TIMEOUT_SMonitorEngine
skill:<name>Force-load specific skillUser
conflict:<domain>Serial-with-others-in-same-domainUser

The active stage writes a per-slot marker file at ~/.coral/projects/<p>/runtime/worker-<slot>-current.json (v0.50.21+). Stop hook reads it to detect which card the worker just finished.

Memory + Wiki

Two complementary persistence systems, both auto-injected into worker prompts.

MemoryWiki (v0.51+)
Path~/.coral/memory/{user,agents,projects/<p>}/<repo>/wiki/ (per-project, in repo)
FormatFlat markdown + YAML frontmatter5 page types with zod-validated frontmatter
Cross-linkNone (flat index)[[type/Title]] wikilinks
Auto-injectknowledge section of promptwikiContext section (5-layer retrieval)
Opt-inAlways on (toggle via ENABLE_MEMORY=false)Per-project (WIKI_ENABLED=true)
Best forPersonal prefs, ad-hoc decisions, gotchasStructured project knowledge: modules, concepts, decisions, lessons

Memory CLI

⚠️ Under reconstruction (v2). The old sps memory list/add/search/context/ingest commands and read_memory/append_memory/recall MCP tools have been removed. The new local memory system (sps memory recall/save/read/...) is being rebuilt — see docs/design/memory-v2.md.

Wiki CLI (when WIKI_ENABLED=true)

sps wiki init <p>                              # scaffold wiki/ (auto on project init if toggled on)
sps wiki update <p>                            # show source diff
sps wiki update <p> --finalize                 # flush manifest after worker writes pages
sps wiki check <p>                             # lint: orphan / dead-link / fm-gap / stale
sps wiki list <p> --type lesson --tag pipeline
sps wiki get <p> lessons/Stop-Hook-Race
sps wiki status <p>                            # source ↔ manifest ↔ pages diff
sps wiki add <p> ~/notes.md --category transcripts
sps wiki read <p> "<query>"                    # preview the 5-layer retrieval

The 5-layer retrieval: hot.md / index summary / pinned / skill-tag / BM25F keyword. Type priority: lesson = 3, decision = 3, concept = 2, module = 1, source = 1. Token budget capped at ~2000.

Worker SOP: skills/wiki-update/SKILL.md (300 lines, single source of truth).

Skills

User-level skills live in ~/.coral/skills/ (28 bundled, copied from npm package on sps setup). Symlinked into ~/.claude/skills/ so Claude Code auto-loads them.

sps skill list                                 # what's available + project status
sps skill add <name> --project <p>             # symlink into <repo>/.claude/skills/
sps skill remove <name> --project <p>
sps skill freeze <name> --project <p>          # symlink → real copy (allow project edits)
sps skill unfreeze <name> --project <p>        # back to symlink
sps skill sync                                 # ① bundled (npm pkg) → ~/.coral/skills/
                                               # ② ~/.coral/skills/ → ~/.claude/skills/
sps skill sync --force                         # ⭐ overwrite existing user skills (after sps-cli upgrade)

Bundled skills (v0.51.3):

  • Dev (23): frontend, frontend-developer, backend, backend-architect, typescript, golang, rust, python, java, kotlin, swift, mobile, database, database-optimizer, qa-tester, security-engineer, architecture-decision-records, coding-standards, debugging-workflow, devops, devops-automator, git-workflow, code-reviewer
  • Worker profiles (3): dev-worker, tax-worker, reviewer (referenced via --profile)
  • SPS-specific (5): sps-pipeline, sps-memory, wiki-update

Agent persona & config (Output Style)

Each agent (chat / worker) gets its persona/role from an Output Style, injected per-agent — separate from the shared base, model, and execution rules. See the design doc.

  • Shared base → CLAUDE.md (root + .claude/: project identity/invariants + codegraph block). Thin, read by every agent.
  • Persona/role → the role segment in <repo>/.claude/agent-config.json (worker / chat), one outputStyle each, injected per-agent via _meta (both segments coexist → no cross-talk under concurrency):
    { "worker": { "outputStyle": "gf-worker" }, "chat": { "outputStyle": "sps-orchestrator" } }
    
    The Output Style file lives at <repo>/.claude/output-styles/<name>.md (frontmatter keep-coding-instructions). projectInit seeds the default sps-orchestrator (generic orchestrator) for new projects.
  • Model + endpoint + env → <repo>/.claude/settings.local.json (read natively by Claude, cross-platform). One model per project, not via process env (ANTHROPIC_BASE_URL via env doesn't reach claude on macOS).
  • Worker execution rules (scope / card lifecycle / git) → fixed by sps, delivered only to the worker via appendSystemPrompt.
  • Memory → a <memory> pointer injected at dispatch; the worker pulls with memory_recall on demand.

Platforms (e.g. gameforge) built on sps-cli follow these rules — they only fill agent-config.json with their own outputStyle after projects.create (and pass skipDefaultAgentConfig: true to skip the generic default).

Command reference

# Setup & projects
sps setup [--force]
sps project init <name>
sps project doctor <name> [--fix] [--json] [--reset-state] [--skip-remote]
sps doctor <name> --fix              # alias

# Pipeline
sps tick <project> [--json]
sps pipeline start|stop|status|reset|workers|board|card|logs|list|run|use [project] [args]
sps pipeline run <name> "<prompt>"   # for mode: steps pipelines
sps pipeline tick <project>          # one-off StageEngine pass
sps scheduler tick <project>         # dormant since v0.51.9 (kept for tick orchestrator)
sps qa tick <project>                # QA → Done finalization
sps monitor tick <project>           # health probe (ACK timeout, stale)
sps pm scan <project>                # rebuild card index from disk

# Cards
sps card add <p> "title" ["description"] [--skills a,b] [--labels x,y]
sps card dashboard <p>
sps card mark-started <p> [seq] [--stage <name>]
sps card mark-complete <p> <seq> [--stage <name>]

# Worker
sps worker ps <project>
sps worker dashboard <project>
sps worker kill <project> <seq>
sps worker launch <project> <seq>

# Status / logs
sps status [--json]
sps stop <project> [--all]
sps reset <project> [--all] [--card N,N,N]
sps logs [project] [--err] [--lines N] [--no-follow]

# Memory — under reconstruction (v2); old `sps memory` subcommands removed. See docs/design/memory-v2.md

# Wiki (v0.51+)
sps wiki init <p>
sps wiki update <p> [--finalize] [--json]
sps wiki read <p> "<query>" [--skills a,b] [--pinned id1,id2] [--budget N]
sps wiki check <p> [--json] [--fix]
sps wiki add <p> <file> [--category <name>] [--no-ingest]
sps wiki list <p> [--type T] [--tag T] [--json]
sps wiki get <p> <pageId> [--json]
sps wiki status <p> [--json]

# Skill
sps skill list [--project <p>]
sps skill add <name> [--project <p>]
sps skill remove <name> [--project <p>]
sps skill freeze <name> [--project <p>]
sps skill unfreeze <name> [--project <p>]
sps skill sync [--force]

# Console
sps console [--port N] [--host H] [--no-open] [--dev] [--kill]

# Agent
sps agent "<prompt>" [--profile <p>] [--system "..."] [--context file] [--output file] [--verbose]
sps agent --chat [--name <session>]
sps agent status|close [args]
sps agent daemon start|stop|status

# Hooks (called by Claude Code, not by users)
sps hook stop
sps hook user-prompt-submit

# ACP control (for advanced debugging)
sps acp <ensure|run|prompt|status|stop|pending|respond> <project> [args]

Add --help after any command to see its specific usage. Add --json for structured output where supported.

Project config (conf)

Live at ~/.coral/projects/<name>/conf (shell export VAR="value" syntax, mode 600). Full field reference (with comments) auto-generated at ~/.coral/projects/<name>/conf.example.

FieldDefaultNotes
PROJECT_NAME(required)Internal id
PROJECT_DIR(required)Absolute path to repo
GITLAB_PROJECT—user/repo (optional, for GitLab API)
GITLAB_PROJECT_ID—Numeric ID (GitLab only; auto-resolved from path on first MR)
GITLAB_MERGE_BRANCHmainWorker pushes here
PM_TOOLmarkdownOnly markdown supported as of v0.42. Cards live in ~/.coral/projects/<n>/cards/<state>/<seq>.md
PIPELINE_LABELAI-PIPELINERequired label on cards to enter pipeline
MR_MODEnonenone (push direct) / create (open MR; needs GITLAB_PROJECT_ID)
WORKER_TRANSPORTacp-sdkFixed; do not change
MAX_CONCURRENT_WORKERS1Slot count; cards still serial within a project
MAX_ACTIONS_PER_TICK3New tasks claimable per tick
INPROGRESS_TIMEOUT_HOURS2After this, MonitorEngine flags STALE-RUNTIME
WORKER_ACK_TIMEOUT_S300Wait for STARTED- label after dispatch (5min, raised in v0.50.24)
WORKER_ACK_MAX_RETRIES1ACK timeout retry count
MONITOR_AUTO_QAtrueAuto-advance to QA on stale runtime
CONFLICT_DEFAULTserialFallback for cards without conflict: label
MATRIX_ROOM_ID—Project-level Matrix override
WORKTREE_DIR~/.coral/worktrees/<p>Worker scratch space
DEFAULT_WORKER_SKILLS—Comma-separated; fallback when no profile: and no card.skills
ENABLE_MEMORYtruefalse skips memory write instructions in prompt
WIKI_ENABLEDunset (off)v0.51+: true enables wiki context injection + reminder
COMPLETION_SIGNALdoneWord the Stop hook listens for

Global credentials at ~/.coral/env: GITLAB_URL, GITLAB_TOKEN, GITLAB_SSH_HOST, GITLAB_SSH_PORT, MATRIX_HOMESERVER, MATRIX_ACCESS_TOKEN, MATRIX_ROOM_ID. Set via sps setup or vim.

Speech output (TTS) — Doubao (Volcengine)

The Console voice home speaks via Doubao (Volcengine) large-model TTS (remote API, zero client dependencies: the browser only hits the Console domain; the backend proxies Volcengine and the key never leaves the server). Configure it in ~/.coral/env on the machine running sps console:

VariableRequiredNotes
SPS_DOUBAO_API_KEY✅Volcengine Speech API key (new console single-header X-Api-Key auth, ark-… form)
SPS_DOUBAO_SPEAKER✅A 2.0 voice id (suffix _uranus_bigtts), e.g. zh_female_vv_uranus_bigtts (female), zh_male_yangguangqingnian_uranus_bigtts (male)
SPS_DOUBAO_RESOURCE_IDnodefaults to seed-tts-2.0
SPS_DOUBAO_ENDPOINTnodefaults to https://openspeech.bytedance.com/api/v3/plan/tts/unidirectional
# ~/.coral/env (mode 600, keep out of git)
SPS_DOUBAO_API_KEY=ark-xxxxxxxx-...
SPS_DOUBAO_SPEAKER=zh_female_vv_uranus_bigtts

If unset, speech falls back to the browser Web Speech API. Restart with sps console --stop then start again to apply. Deploying on another machine only needs this block repeated there — no local model to install.

Project layout

~/.coral/                              # User-global state
├── env                                # Global credentials (mode 600)
├── skills/                            # User-level skills (synced from npm)
├── memory/{user,agents,projects}/     # 3-layer memory store
├── projects/<name>/                   # Per-project state
│   ├── conf                           # Project config (mode 600)
│   ├── conf.example                   # Field reference (auto-generated)
│   ├── pipelines/{project,*}.yaml     # Pipeline definitions
│   ├── pipeline_order.json            # Active pipeline pointer
│   ├── runtime/state.json             # Worker slot + active card state
│   ├── runtime/worker-<slot>-current.json   # Per-slot card marker (v0.50.21+)
│   ├── runtime/tick.lock              # Tick lock
│   ├── runtime/acp-state.json         # ACP session state
│   ├── cards/<state>/<seq>.md         # Card files (markdown PM backend)
│   ├── cards/seq.txt                  # Sequence counter
│   ├── logs/                          # Per-tick logs
│   └── pm_meta/                       # Card index
├── sessions/                          # Agent daemon (chat sessions)
│   ├── daemon.sock daemon.pid
│   └── chat-sessions/<id>.json        # Persisted chat sessions
├── console.lock                       # Single-instance guard for console
└── worktrees/<project>/<seq>/         # Worker worktree per active card

In the target repo (PROJECT_DIR):

.claude/
├── CLAUDE.md                          # Worker rules (project-specific + SPS-injected)
├── settings.local.json                # Claude Code local config
├── skills/                            # Symlinked from ~/.coral/skills/
└── hooks/{start,stop}.sh              # Lifecycle hooks (call into sps)
wiki/                                  # If WIKI_ENABLED — see docs/design/28-wiki-system.md
ATTRIBUTION.md                         # If WIKI_ENABLED

Architecture

4-layer service architecture (v0.50+):

Delivery (commands/, console/routes/)        Thin parameter parsing + I/O orchestration
  ↓
Service (services/)                          ProjectService / ChatService / PipelineService /
                                             SkillService / WikiService — Result<T> + DomainEvent
  ↓
Domain (engines/)                            SchedulerEngine / StageEngine / MonitorEngine /
                                             CloseoutEngine / EventHandler — pipeline logic
  ↓
Infrastructure                               WorkerManager (single worker), ACPWorkerRuntime,
  (manager/, providers/, daemon/)            sessionDaemon, TaskBackend, RepoBackend

Engines:

  • SchedulerEngine — dormant since v0.51.9 (cards go directly to Backlog on add; Planning is a manual park). Class kept as a no-op for the tick orchestrator's stable interface.
  • StageEngine — drives card through stages; builds prompt (skill + projectRules + memory + wikiContext + task description + wikiUpdateReminder); kicks worker via ACP.
  • MonitorEngine — ACK timeout detection, stale runtime, auto-QA promotion.
  • CloseoutEngine + EventHandler — finalize completed cards.

Single-worker is intentional: v0.37.2 deleted multi-worker concurrency code. Don't propose "add a parallel mode" — the architecture relies on serial execution for state coherence. For higher throughput, run multiple projects in parallel.

For deep dives:

Troubleshooting

sps doctor <project> --fix           # ★ first thing to try
sps logs <project> --err             # stderr / errors only
sps reset <project> --card <seq>     # nuke a stuck card
sps reset <project> --all            # full project reset

# Worker / daemon issues
sps worker ps <project>
sps agent daemon status              # is the chat daemon up?
sps agent daemon stop && sps agent daemon start    # restart (clears stale cwd)

# Wiki issues
sps wiki check <project>
sps wiki status <project>

Common issues:

SymptomCause / fix
Pipeline halted with NEEDS-FIXOpen the failed card, fix the issue, remove the label. Console makes this 2 clicks.
Worker not startingsps worker ps, then sps logs --err. Often Claude API key missing or claude-agent-acp adapter not installed (sps setup reinstalls).
Cards stuck in PlanningNeed AI-PIPELINE label. sps card add applies it automatically; if added externally, add manually.
ACK timeout on every cardClaude cold-start is slow with many skill / memory files. Raise WORKER_ACK_TIMEOUT_S (default 300s as of v0.50.24).
Console shows stale dataSSE may have dropped; reload page; if persistent, sps console --kill && sps console.
Wiki context not injectingVerify WIKI_ENABLED=true in conf and wiki/WIKI.md exists. StageEngine logs a warning if conf says yes but scaffold is missing.
New skill SOP not pulling after upgradesps skill sync --force (default sync skips existing skills).
Daemon chat using wrong cwdDaemon captures cwd at startup. sps agent daemon stop && cd <repo> && sps agent daemon start.

License & attribution

MIT, see LICENSE.

The Wiki system (v0.51+) borrows ~70% from claude-obsidian (MIT) — three-layer architecture, manifest delta tracking, hot cache, ingest workflow, contradiction callouts, wikilinks. SPS-specific 30%: 5 page types, sources={card,commit,path}, 5-layer reader, sps wiki check exit gate. Mental model from Karpathy's "LLM Wiki" gist.

Full attribution: ATTRIBUTION.md.

Keywords

cli

FAQs

Package last updated on 04 Sep 2026

Related posts