npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@coralai/sps-cli

v0.90.1

Published

SPS CLI — AI-driven development pipeline orchestrator

Readme

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:

| Mode | Command | When | |---|---|---| | Harness | sps agent | Zero-config — one-shot or multi-turn chat with Claude. No project, no PM. | | Pipeline | sps tick <project> | Automated card-driven workflow with YAML-configurable stages. | | Console | sps console | Web 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:

  1. Creates the ~/.coral/ directory tree (projects/, memory/, …).
  2. 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).
  3. 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.
  4. 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.

Upgrading a stale install: clean reinstall recommended

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:

  1. Node ≥ 22 (code-graph uses node:sqlite; the rest of the CLI runs on ≥ 18).
  2. Claude Code CLI in PATH — the worker backend drives it (sps doctor checks which claude):
    npm install -g @anthropic-ai/claude-code
  3. 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.
  4. Run sps setup once — scaffolds ~/.coral/, installs the ACP transport @agentclientprotocol/claude-agent-acp globally, writes ~/.coral/env.
  5. 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:sqliteDatabaseSync — 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:clirm -rf dist && tsc (compiles src/dist/).
  • build:consolecd console && npm install && vite build, then copies console/distdist/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:

| Path | Purpose | |---|---| | /projects | List all projects with status | | /projects/new | Create project (Wiki toggle + worker-model picker, v0.58.3+) | | /projects/<n> | Pipeline editor + conf editor + delete | | /board | Kanban (per-column scrolling, v0.51.1+) | | /workers | Aggregate worker dashboard across projects | | /logs | Live SSE log viewer | | /skills | User-level skill management | | /plugins | Model endpoints + IM channels + memory backend config (v0.58+) | | /system | Global settings + daemon status | | /chat | Agent 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:

  1. mode: project for state-machine pipelines; mode: steps for one-shot custom (use sps pipeline run <name>).
  2. Each stage's on_complete must point to the next stage's target state.
  3. Last stage's on_complete: "move_card Done".
  4. Don't write agent: field — it's silently ignored (v0.38+ Claude is the only worker).
  5. 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

| Label | Meaning | Set by | |---|---|---| | AI-PIPELINE | Required to enter pipeline | User on creation | | STARTED-<stage> | ACK signal — Claude received the prompt | UserPromptSubmit hook | | COMPLETED-<stage> | Worker finished a stage | Stop hook | | CLAIMED | StageEngine reserved a worker slot | Engine | | NEEDS-FIX | Worker failed; pipeline halted | Engine | | BLOCKED | External dep; pipeline skips | User | | WAITING-CONFIRMATION | Worker waiting on user input | Engine | | STALE-RUNTIME | Inprogress > timeout | MonitorEngine | | ACK-TIMEOUT | Claude never ACK'd within WORKER_ACK_TIMEOUT_S | MonitorEngine | | skill:<name> | Force-load specific skill | User | | conflict:<domain> | Serial-with-others-in-same-domain | User |

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.

| | Memory | Wiki (v0.51+) | |---|---|---| | Path | ~/.coral/memory/{user,agents,projects/<p>}/ | <repo>/wiki/ (per-project, in repo) | | Format | Flat markdown + YAML frontmatter | 5 page types with zod-validated frontmatter | | Cross-link | None (flat index) | [[type/Title]] wikilinks | | Auto-inject | knowledge section of prompt | wikiContext section (5-layer retrieval) | | Opt-in | Always on (toggle via ENABLE_MEMORY=false) | Per-project (WIKI_ENABLED=true) | | Best for | Personal prefs, ad-hoc decisions, gotchas | Structured 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 baseCLAUDE.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.

| Field | Default | Notes | |---|---|---| | 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_BRANCH | main | Worker pushes here | | PM_TOOL | markdown | Only markdown supported as of v0.42. Cards live in ~/.coral/projects/<n>/cards/<state>/<seq>.md | | PIPELINE_LABEL | AI-PIPELINE | Required label on cards to enter pipeline | | MR_MODE | none | none (push direct) / create (open MR; needs GITLAB_PROJECT_ID) | | WORKER_TRANSPORT | acp-sdk | Fixed; do not change | | MAX_CONCURRENT_WORKERS | 1 | Slot count; cards still serial within a project | | MAX_ACTIONS_PER_TICK | 3 | New tasks claimable per tick | | INPROGRESS_TIMEOUT_HOURS | 2 | After this, MonitorEngine flags STALE-RUNTIME | | WORKER_ACK_TIMEOUT_S | 300 | Wait for STARTED- label after dispatch (5min, raised in v0.50.24) | | WORKER_ACK_MAX_RETRIES | 1 | ACK timeout retry count | | MONITOR_AUTO_QA | true | Auto-advance to QA on stale runtime | | CONFLICT_DEFAULT | serial | Fallback 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_MEMORY | true | false skips memory write instructions in prompt | | WIKI_ENABLED | unset (off) | v0.51+: true enables wiki context injection + reminder | | COMPLETION_SIGNAL | done | Word 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:

| Variable | Required | Notes | | --- | --- | --- | | 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_ID | no | defaults to seed-tts-2.0 | | SPS_DOUBAO_ENDPOINT | no | defaults 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:

| Symptom | Cause / fix | |---|---| | Pipeline halted with NEEDS-FIX | Open the failed card, fix the issue, remove the label. Console makes this 2 clicks. | | Worker not starting | sps worker ps, then sps logs --err. Often Claude API key missing or claude-agent-acp adapter not installed (sps setup reinstalls). | | Cards stuck in Planning | Need AI-PIPELINE label. sps card add applies it automatically; if added externally, add manually. | | ACK timeout on every card | Claude cold-start is slow with many skill / memory files. Raise WORKER_ACK_TIMEOUT_S (default 300s as of v0.50.24). | | Console shows stale data | SSE may have dropped; reload page; if persistent, sps console --kill && sps console. | | Wiki context not injecting | Verify 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 upgrade | sps skill sync --force (default sync skips existing skills). | | Daemon chat using wrong cwd | Daemon 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.