mcpField
S
squad

squad

github.com/steloitProductivity052 installsUpdated 14w ago
Repository

About squad

squad is a skill for managing project tasks and context. Its commands cover board views, task lifecycle changes, project records, and session handoffs.

Key features

  1. 01View board and task progress
  2. 02Create, edit, and move tasks
  3. 03Complete, cancel, and reopen tasks
  4. 04View statistics and project context
  5. 05Manage project briefs and links
  6. 06Upload image attachments to tasks

Use cases

  1. 01Review task progress at session start
  2. 02Advance or adjust task statuses
  3. 03Maintain project briefs and relationships
  4. 04Attach task images and inspect statistics

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/steloit/squad-skills --skill squad

After installing, type/squadin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

models.json
principles.md
schema.md
shared.md
scripts/
api_smoke.py
api.md
api.py
coach_smoke.py
observe_smoke.py
observe.md
observe.py
refine_ledger_smoke.py
refine_ledger.md
refine_ledger.py
render_agent_prompt.py
templates/
coach.md
reviewer.md
worker.md

Details

From the project README

Shared context: read shared.md for project config & auth, pipeline levels, status transitions, API endpoints, error handling, and agent context flow. Safety principles: read principles.md — mandatory, not optional.

Commands

/squad or /squad list — View Board
BOARD=$(api GET /board?summary=true)

Output: markdown table with ID, Status, Priority, Title.

Epics: the board response carries an epics aggregate (each with children_progress and a derived epic_status). Group children under their epic from this aggregate + the embedded parent/children edges — never from tag parsing (see shared.md → Task Relationships & Epics). Show each epic's children_progress (e.g. 2/5 done).

/squad context — Session Handoff

Run first when starting a new session. Fetch board and output pipeline state: Implementing / Plan Review / Impl Review / Testing / Recently Done / Next Todo.

BOARD=$(api GET /board?summary=true)
/squad add <title> — Add Task
  1. Ask user for priority, level (L1/L2/L3), description, tags (use AskUserQuestion)
  2. Build JSON safely with jq (see shared.md → JSON Safety), POST to API, capture the new task ID. tags MUST be a JSON array — the canonical stored format the board renders. Split the user's comma-separated input into an array, e.g. --arg tags "$TAGS" then tags: ($tags | split(",") | map(gsub("^ +| +$";""))) in the jq body (no tags → omit the field or pass [], never "").
  3. Images: if the user gave image file path(s) (e.g. /squad add "Login bug" --image ./bug.png, or "attach ./shot.png"), upload each to the new task via the attachment API (see shared.md → "Upload an image attachment"). Output the task ID + the returned attachment url(s). A pasted image with no path → ask the user to save it to a file first (the upload reads a local file).
/squad move <ID> <status> — Move Task

Always follow shared.md → Move Protocol in order. Step 1 (check current status + level) → Step 2 (consult the matrix) → Step 3 (execute the move). On 400: self-correct once via the response's .allowed[0]; notify the user after 2 failures.

/squad edit <ID> — Edit Task

Ask user which fields to modify, then PATCH via API. To attach an image to an existing task, upload a local image file via the attachment API (shared.md → "Upload an image attachment").

/squad complete <ID> [note] — Complete Task (administrative completion)

Mark a task done from any non-terminal status. This is non-interactive — no AskUserQuestion, no confirmation prompt; completing is history-preserving and reversible, so just do it.

NOTE="$*"   # everything after the ID; may be empty
# omit/empty note → send {} ; otherwise send {"completion_note": "<note>"}
if [ -n "$NOTE" ]; then
  api POST /task/$ID/complete --json "$(jq -n --arg n "$NOTE" '{completion_note:$n}')"
else
  api POST /task/$ID/complete --json '{}'
fi
# → {"success":true,"status":"done","version":<int>}

Complete is the paired twin of /squad cancel: complete = finished, cancel = won't-do. Both are history-preserving (plan, notes, comments, counts, results are kept) and reversible via /squad reopen, unlike the irreversible /squad remove (a hard DELETE). Re-completing an already-done task is a safe no-op; a cancelled target returns 409 — reopen it first. The card records completed_via:"admin" (vs "pipeline" for a gated pipeline finalize) plus the optional completion_note.

/squad cancel <ID> [reason] — Cancel Task (preferred abandon verb)

Cancel a task from any status. This is non-interactive — no AskUserQuestion, no confirmation prompt; cancelling is history-preserving and reversible, so just do it.

REASON="$*"   # everything after the ID; may be empty
# omit/empty reason → send {} ; otherwise send {"cancel_reason": "<reason>"}
if [ -n "$REASON" ]; then
  api POST /task/$ID/cancel --json "$(jq -n --arg r "$REASON" '{cancel_reason:$r}')"
else
  api POST /task/$ID/cancel --json '{}'
fi
# → {"success":true,"status":"cancelled","version":<int>}

Cancel is the preferred way to abandon work: it is history-preserving (plan, notes, comments, counts, results are kept) and reversible via /squad reopen. Re-cancelling an already-cancelled task is a safe no-op. Use it for won't-do / superseded / deprioritized work instead of /squad remove.

/squad reopen <ID> — Reopen Task (the un-cancel / un-complete path)

Restore a terminal task (cancelled OR done) back to todo. This is the un-cancel and un-complete path — reopening clears lifecycle timestamps, current_agent, cancel_reason, completion_note, and completed_via, and preserves prior work.

api POST /task/$ID/reopen --json '{"reason": "<why reopening>"}'
# → {"success":true,"status":"todo","version":<int>}

Reopening a non-terminal task (anything other than cancelled/done) returns 409 and changes nothing.

/squad remove <ID> — Delete Task
api DELETE /task/$ID

remove is a hard DELETE — irreversible (the card and its attachments are gone). Reserve it for never-started mistakes / duplicates. For won't-do or superseded work, prefer /squad cancel (history-preserving and reversible).

/squad stats — Statistics

Column counts come from the board summary; per-actor token/event totals come from a single GET /api/activity/stats call (server-side GROUP BY actor — no per-task loop, no board fetch for tokens).

export BOARD=$(api GET /board?summary=true)
export STATS=$(api GET /activity/stats)
python3 << 'PY'
import json, os

board = json.loads(os.environ['BOARD'])
stats = json.loads(os.environ['STATS'])
columns = ['todo', 'plan', 'plan_review', 'impl', 'impl_review', 'test', 'done', 'cancelled']

# Column counts (summary is keyed by status, each an array of cards)
counts = {col: len(board.get(col, [])) for col in columns}
counts['total'] = sum(counts.values())
print("## Column Counts\n")
print("| Status | Count |")
print("|--------|-------|")
for col in columns:
    print(f"| {col} | {counts[col]} |")
print(f"| **total** | **{counts['total']}** |")

# Per-actor token/event stats — tolerant reader: pull only the fields we use,
# treat a null/missing per-actor `tokens` as unknown (render —, never coerce to 0,
# never do arithmetic over a null), and ignore any unknown/extra fields the server adds.
rows = stats.get('stats', [])
totals = stats.get('totals', {})
print("\n## Agent Token Usage\n")
if not rows:
    print("No token data")
else:
    print("| Actor | Events | Tokens | Coverage |")
    print("|-------|--------|--------|----------|")
    for r in sorted(rows, key=lambda r: r.get('actor', '')):
        events = r.get('events', 0)
        tok = r.get('tokens')
        reported = r.get('reported')
        tok_cell = "—" if tok is None else f"{tok:,}"
        if reported is None:
            cov_cell = "—"
        elif reported < events:
            cov_cell = f"{reported}/{events} (partial)"
        else:
            cov_cell = f"{reported}/{events}"
        print(f"| {r.get('actor', 'unknown')} | {events} | {tok_cell} | {cov_cell} |")
    tot_tok = totals.get('tokens')
    tot_tok_cell = "—" if tot_tok is None else f"{tot_tok:,}"
    print(f"| **Total** | **{totals.get('events', 0)}** | **{tot_tok_cell}** | |")
PY
/squad project — Current Project Context (AI Context Docking)

Fetch the current project's context from the projects table. Use this at the start of a session to load project purpose, stack, brief, relationships, and task counts in one call.

PROJECT_DATA=$(api GET /projects/$PROJECT)

Output: formatted project context including:

  • Purpose (WHY this project exists)
  • Stack (technologies used)
  • Brief (compressed current state + direction + recent decisions)
  • Category and status
  • Task counts by status
  • Links to related projects

If the project is not registered, suggest running /squad-init to register it.

/squad project all — Full Project Map

Fetch all projects grouped by category. Useful for understanding the full project landscape.

ALL_PROJECTS=$(api GET /projects)

Output: projects grouped by category (e.g. personal, tools, skills) with names and purposes.

/squad project brief — View/Update Project Brief

The brief is a compressed context summary (200–500 chars) that agents consume at low token cost.

View current brief:

api GET /projects/$PROJECT | jq -r '.brief // "No brief set"'

Set brief directly:

api PATCH /projects/$PROJECT --json '{"brief": "..."}'

AI-assisted update (/squad project brief update):

  1. Fetch current project info + recent done tasks (GET /api/board?project=$PROJECT&summary=true)
  2. Analyze: current state, recent completions, active direction
  3. Draft a concise brief (200–500 chars) covering: what exists now, where we're heading, recent key decisions
  4. Present to user for confirmation → PATCH to save
/squad project update <field> <value> — Edit Project Metadata

Update any project field via PATCH:

# Update purpose
api PATCH /projects/$PROJECT --json '{"purpose": "new purpose"}'

# Archive project
api PATCH /projects/$PROJECT --json '{"status": "archived"}'

Supported fields: name, purpose, stack, brief, status, category, repo_url.

/squad project link — Manage Project Relationships
# Add relationship
api POST /projects/$PROJECT/links --json '{"target_id": "other-project", "relation": "depends_on"}'

# Remove relationship
api DELETE /projects/$PROJECT/links --json '{"target_id": "other-project", "relation": "depends_on"}'

Relations: extends, serves, depends_on, shares_data.

/squad observe status|dry-run — Observation Consent (read-only)

Inspect the observation-consent gate. Read-only — the opt-in/opt-out act lives in the web app (Settings → Observation & Consent); the skill never grants or withdraws. See shared.md → Observation & Consent.

observe() { python3 ../squad/scripts/observe.py "$@"; }

# status — effective on/off, the source that decided it (env override / server
# consent / default), the policy_version on record, and the web-app manage pointer.
observe status            # human-readable;  add --json for the decision object

# dry-run — print the ABSTRACTED user_steering payload that WOULD be recorded to
# stdout (pipeable to jq) + a `# DRY RUN` banner to stderr. Writes/sends NOTHING,
# in any consent state — inspect before opting in.
observe dry-run | jq .

There is no grant/withdraw here — opt in or out in the web app.

Setup & Web Board

Run /squad-init first to register this project — it writes .squadrc (SQUAD_PROJECT=…, plus an optional SQUAD_ORG=<label> org selector) at the repo root, committed so your whole team's agents target the same board project. The token never goes in a project file — it's a Personal Access Token resolved as SQUAD_AUTH_TOKEN env > bare SQUAD_AUTH_TOKEN= from ~/.squad/auth (see shared.md).

Open the deployed board at https://squad.steloit.com/?project=<PROJECT> (or via the configured SQUAD_BASE_URL). Features: 7-column pipeline, drag-and-drop (valid transitions only), card lifecycle modal, agent log viewer, 10s auto-refresh.

Comments

Markdown supported