squadrant 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +268 -0
  3. package/dist/index.js +9154 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/squadrantd.js +3928 -0
  6. package/dist/squadrantd.js.map +1 -0
  7. package/package.json +68 -0
  8. package/plugin/.claude-plugin/plugin.json +5 -0
  9. package/plugin/skills/add-pick-crew-rule/SKILL.md +88 -0
  10. package/plugin/skills/captain-ops/SKILL.md +390 -0
  11. package/plugin/skills/command-ops/SKILL.md +157 -0
  12. package/plugin/skills/config-doctor/SKILL.md +46 -0
  13. package/plugin/skills/daily-log/SKILL.md +44 -0
  14. package/plugin/skills/karpathy-principles/SKILL.md +82 -0
  15. package/plugin/skills/set-effort/SKILL.md +59 -0
  16. package/plugin/skills/side-session/SKILL.md +113 -0
  17. package/plugin/skills/squadrant-effort/SKILL.md +8 -0
  18. package/plugin/skills/squadrant-new-project/SKILL.md +67 -0
  19. package/plugin/skills/squadrant-register-project/SKILL.md +60 -0
  20. package/plugin/skills/where-i-am/SKILL.md +102 -0
  21. package/plugin/skills/wiki-ops/SKILL.md +96 -0
  22. package/plugin/skills/wim/SKILL.md +8 -0
  23. package/scripts/acceptance-interactive-codex.sh +56 -0
  24. package/scripts/capture-skill.sh +32 -0
  25. package/scripts/claude-iv-smoke.mjs +133 -0
  26. package/scripts/fix-skill.sh +39 -0
  27. package/scripts/gen-codex-types.sh +18 -0
  28. package/scripts/mailbox-injector-smoke.mjs +124 -0
  29. package/scripts/mark-learning-useful.sh +22 -0
  30. package/scripts/migrate-to-squadrant.sh +158 -0
  31. package/scripts/notify-relay-placement-smoke.mjs +59 -0
  32. package/scripts/read-handoff.sh +22 -0
  33. package/scripts/record-learning.sh +31 -0
  34. package/scripts/record-side-handoff.sh +32 -0
  35. package/scripts/smoke-push-notify.mjs +147 -0
  36. package/scripts/spawn-crew-pane.sh +17 -0
  37. package/scripts/spawn-workspace.sh +206 -0
  38. package/scripts/wiki-ingest.sh +121 -0
  39. package/scripts/wiki-log.sh +20 -0
  40. package/scripts/wiki-query.sh +36 -0
  41. package/scripts/write-handoff.sh +31 -0
  42. package/templates/captain.claude.md +44 -0
  43. package/templates/captain.generic.md +45 -0
  44. package/templates/command.claude.md +32 -0
  45. package/templates/crew.claude.md +64 -0
  46. package/templates/crew.generic.md +51 -0
  47. package/templates/crew.opencode.md +51 -0
  48. package/templates/learnings.claude.md +40 -0
  49. package/templates/side.debug.claude.md +78 -0
  50. package/templates/side.research.claude.md +63 -0
@@ -0,0 +1,206 @@
1
+ #!/bin/bash
2
+ # Usage: spawn-workspace.sh <name> <cwd> [role] [--fresh]
3
+ # role: "captain" | "crew" | "command" (default: "captain")
4
+ # --fresh: force a new session instead of resuming
5
+ set -euo pipefail
6
+
7
+ CMUX="/Applications/cmux.app/Contents/Resources/bin/cmux"
8
+ TEMPLATES_DIR="${HOME}/.config/squadrant/templates"
9
+ SESSIONS_FILE="${HOME}/.config/squadrant/sessions.json"
10
+ NAME="${1:?Usage: spawn-workspace.sh <name> <cwd> [role] [--fresh]}"
11
+ CWD="${2:?Usage: spawn-workspace.sh <name> <cwd> [role] [--fresh]}"
12
+ ROLE="${3:-captain}"
13
+ FORCE_FRESH="${4:-}"
14
+
15
+ TODAY=$(date +"%Y-%m-%d")
16
+ FRESH=false
17
+
18
+ # --- Session freshness check ---
19
+ if [ "$FORCE_FRESH" = "--fresh" ]; then
20
+ FRESH=true
21
+ elif [ -f "$SESSIONS_FILE" ]; then
22
+ # Check last launch date
23
+ LAST_DATE=$(python3 -c "
24
+ import json, sys
25
+ try:
26
+ data = json.load(open('$SESSIONS_FILE'))
27
+ print(data.get('workspaces', {}).get('$NAME', {}).get('lastLaunched', ''))
28
+ except: print('')
29
+ " 2>/dev/null)
30
+
31
+ if [ -z "$LAST_DATE" ]; then
32
+ FRESH=true # first launch
33
+ elif [ "$LAST_DATE" != "$TODAY" ]; then
34
+ FRESH=true # new day
35
+ echo "↻ new day — starting fresh session for $NAME"
36
+ fi
37
+
38
+ # Check template + skills hash
39
+ if [ "$FRESH" = "false" ]; then
40
+ ROLE_FILE="${TEMPLATES_DIR}/${ROLE}.claude.md"
41
+ [ ! -f "$ROLE_FILE" ] && ROLE_FILE="${TEMPLATES_DIR}/${ROLE}.CLAUDE.md"
42
+ CURRENT_HASH=$(cat "$ROLE_FILE" "${HOME}/.config/squadrant/plugin/skills"/*/SKILL.md 2>/dev/null | shasum -a 256 | cut -c1-16)
43
+ STORED_HASH=$(python3 -c "
44
+ import json
45
+ try:
46
+ data = json.load(open('$SESSIONS_FILE'))
47
+ print(data.get('workspaces', {}).get('$NAME', {}).get('templateHash', ''))
48
+ except: print('')
49
+ " 2>/dev/null)
50
+ if [ -n "$CURRENT_HASH" ] && [ "$CURRENT_HASH" != "$STORED_HASH" ]; then
51
+ FRESH=true
52
+ echo "↻ template instructions updated — starting fresh session for $NAME"
53
+ fi
54
+ fi
55
+ else
56
+ FRESH=true # no sessions file yet
57
+ fi
58
+
59
+ # --- Record session ---
60
+ ROLE_FILE="${TEMPLATES_DIR}/${ROLE}.claude.md"
61
+ [ ! -f "$ROLE_FILE" ] && ROLE_FILE="${TEMPLATES_DIR}/${ROLE}.CLAUDE.md"
62
+ CURRENT_HASH=$(cat "$ROLE_FILE" "${HOME}/.config/squadrant/plugin/skills"/*/SKILL.md 2>/dev/null | shasum -a 256 | cut -c1-16)
63
+ python3 -c "
64
+ import json, os
65
+ path = '$SESSIONS_FILE'
66
+ try:
67
+ data = json.load(open(path))
68
+ except: data = {'workspaces': {}}
69
+ data.setdefault('workspaces', {})['$NAME'] = {'lastLaunched': '$TODAY', 'templateHash': '$CURRENT_HASH'}
70
+ os.makedirs(os.path.dirname(path), exist_ok=True)
71
+ json.dump(data, open(path, 'w'), indent=2)
72
+ " 2>/dev/null
73
+
74
+ # Read permission mode from config
75
+ PERM_MODE=$(python3 -c "
76
+ import json
77
+ try:
78
+ cfg = json.load(open('${HOME}/.config/squadrant/config.json'))
79
+ role_key = '$ROLE' if '$ROLE' in ('captain', 'command') else 'captain'
80
+ print(cfg.get('defaults', {}).get('permissions', {}).get(role_key, 'default'))
81
+ except: print('default')
82
+ " 2>/dev/null)
83
+
84
+ # Read agent and model from roles config (new format), fall back to old models config
85
+ AGENT=$(python3 -c "
86
+ import json
87
+ try:
88
+ cfg = json.load(open('${HOME}/.config/squadrant/config.json'))
89
+ roles = cfg.get('defaults', {}).get('roles', {})
90
+ role_cfg = roles.get('$ROLE', {})
91
+ print(role_cfg.get('agent', 'claude'))
92
+ except: print('claude')
93
+ " 2>/dev/null)
94
+
95
+ MODEL=$(python3 -c "
96
+ import json
97
+ try:
98
+ cfg = json.load(open('${HOME}/.config/squadrant/config.json'))
99
+ roles = cfg.get('defaults', {}).get('roles', {})
100
+ role_cfg = roles.get('$ROLE', {})
101
+ model = role_cfg.get('model', '')
102
+ if not model:
103
+ model = cfg.get('defaults', {}).get('models', {}).get('$ROLE', '')
104
+ print(model)
105
+ except: print('')
106
+ " 2>/dev/null)
107
+
108
+ # --- Build agent command based on resolved agent ---
109
+ case "$AGENT" in
110
+ claude)
111
+ if [ "$FRESH" = "true" ]; then
112
+ AGENT_CMD="claude"
113
+ else
114
+ AGENT_CMD="claude -c"
115
+ fi
116
+
117
+ if [ "$PERM_MODE" = "acceptEdits" ]; then
118
+ AGENT_CMD="${AGENT_CMD} --permission-mode acceptEdits"
119
+ elif [ "$PERM_MODE" = "auto" ]; then
120
+ AGENT_CMD="${AGENT_CMD} --permission-mode auto"
121
+ elif [ "$PERM_MODE" = "bypassPermissions" ]; then
122
+ AGENT_CMD="${AGENT_CMD} --dangerously-skip-permissions"
123
+ fi
124
+
125
+ if [ -n "$MODEL" ]; then
126
+ AGENT_CMD="${AGENT_CMD} --model ${MODEL}"
127
+ fi
128
+
129
+ ROLE_FILE="${TEMPLATES_DIR}/${ROLE}.claude.md"
130
+ [ ! -f "$ROLE_FILE" ] && ROLE_FILE="${TEMPLATES_DIR}/${ROLE}.CLAUDE.md"
131
+ if [ -f "$ROLE_FILE" ]; then
132
+ AGENT_CMD="${AGENT_CMD} --append-system-prompt-file ${ROLE_FILE}"
133
+ fi
134
+
135
+ PLUGIN_DIR="${HOME}/.config/squadrant/plugin"
136
+ if [ -d "$PLUGIN_DIR" ]; then
137
+ AGENT_CMD="${AGENT_CMD} --plugin-dir ${PLUGIN_DIR}"
138
+ fi
139
+ ;;
140
+
141
+ codex)
142
+ ROLE_FILE="${TEMPLATES_DIR}/${ROLE}.generic.md"
143
+ AGENT_CMD="codex exec --json --full-auto"
144
+ if [ -f "$ROLE_FILE" ]; then
145
+ AGENT_CMD="${AGENT_CMD} -p \"Read instructions from ${ROLE_FILE} and begin.\""
146
+ fi
147
+ ;;
148
+
149
+ gemini)
150
+ ROLE_FILE="${TEMPLATES_DIR}/${ROLE}.generic.md"
151
+ AGENT_CMD="gemini --yolo"
152
+ if [ -f "$ROLE_FILE" ]; then
153
+ AGENT_CMD="${AGENT_CMD} -p \"Read instructions from ${ROLE_FILE} and begin.\""
154
+ fi
155
+ ;;
156
+
157
+ *)
158
+ echo "ERROR: Unknown agent '${AGENT}' for role '${ROLE}'"
159
+ exit 1
160
+ ;;
161
+ esac
162
+
163
+ # --- Handle existing workspace ---
164
+ # Find existing workspace via runtime abstraction
165
+ EXISTING_JSON=$(squadrant runtime list --json 2>/dev/null || echo "[]")
166
+ EXISTING_ID=$(echo "$EXISTING_JSON" | python3 -c "
167
+ import json,sys
168
+ try:
169
+ for w in json.load(sys.stdin):
170
+ if w.get('name') == '$NAME':
171
+ print(w['id']); break
172
+ except: pass
173
+ ")
174
+
175
+ if [ -n "$EXISTING_ID" ] && [ "$FRESH" = "true" ]; then
176
+ echo "Closing stale workspace: $NAME"
177
+ # select-workspace has no runtime abstraction yet — keeping direct cmux call here
178
+ "$CMUX" close-workspace --workspace "$EXISTING_ID" 2>/dev/null || true
179
+ EXISTING_ID=""
180
+ fi
181
+
182
+ if [ -n "$EXISTING_ID" ]; then
183
+ echo "Workspace '$NAME' already exists — switching to it"
184
+ # select-workspace has no runtime abstraction yet — keeping direct cmux call here
185
+ "$CMUX" select-workspace --workspace "$EXISTING_ID" 2>&1
186
+ exit 0
187
+ fi
188
+
189
+ # --- Spawn new workspace ---
190
+ CURRENT=$("$CMUX" current-workspace 2>&1 | awk '{print $1}')
191
+ NEW_UUID=$("$CMUX" new-workspace --command "$AGENT_CMD" --cwd "$CWD" 2>&1 | awk '{print $2}')
192
+ "$CMUX" rename-workspace --workspace "$NEW_UUID" "$NAME" 2>&1
193
+ if [ "$ROLE" = "command" ] || [ "$ROLE" = "captain" ]; then
194
+ "$CMUX" workspace-action --workspace "$NEW_UUID" --action pin 2>/dev/null || true
195
+ fi
196
+ # Send initial prompt to trigger startup checklist (Claude agents only)
197
+ if [ "$AGENT" = "claude" ]; then
198
+ if [ "$ROLE" = "captain" ]; then
199
+ (sleep 3 && "$CMUX" send --workspace "$NEW_UUID" "Run your startup checklist: use the squadrant:captain-ops skill, complete all startup steps, then report ready." 2>/dev/null) &
200
+ elif [ "$ROLE" = "command" ]; then
201
+ (sleep 3 && "$CMUX" send --workspace "$NEW_UUID" "Run your startup checklist: use the squadrant:command-ops skill, complete your daily briefing, then report ready." 2>/dev/null) &
202
+ fi
203
+ fi
204
+
205
+ "$CMUX" select-workspace --workspace "$CURRENT" 2>&1
206
+ echo "Spawned workspace: $NAME at $CWD (role: $ROLE, agent: $AGENT, fresh: $FRESH)"
@@ -0,0 +1,121 @@
1
+ #!/bin/bash
2
+ # Usage: wiki-ingest.sh <spoke-vault-path> <page-slug> <title> <category> <body> [tags] [source]
3
+ # Creates or updates a wiki page and updates the index and log.
4
+ # Categories: Architecture, Patterns, APIs, Configuration, Debugging, Conventions, Dependencies, Deployment
5
+ set -euo pipefail
6
+
7
+ VAULT="${1:?Usage: wiki-ingest.sh <vault> <slug> <title> <category> <body> [tags] [source]}"
8
+ SLUG="${2:?}"
9
+ TITLE="${3:?}"
10
+ CATEGORY="${4:?}"
11
+ BODY="${5:?}"
12
+ TAGS="${6:-}"
13
+ SOURCE="${7:-manual}"
14
+ DATE=$(date +"%Y-%m-%d")
15
+ TIME=$(date +"%H:%M:%S")
16
+
17
+ WIKI_DIR="${VAULT}/wiki"
18
+ PAGES_DIR="${WIKI_DIR}/pages"
19
+ PAGE_FILE="${PAGES_DIR}/${SLUG}.md"
20
+ INDEX_FILE="${WIKI_DIR}/index.md"
21
+ LOG_FILE="${WIKI_DIR}/log.md"
22
+
23
+ mkdir -p "${PAGES_DIR}"
24
+
25
+ # Determine if this is a create or update
26
+ ACTION="created"
27
+ if [ -f "$PAGE_FILE" ]; then
28
+ ACTION="updated"
29
+ fi
30
+
31
+ # Write the page
32
+ cat > "$PAGE_FILE" << EOF
33
+ ---
34
+ title: "${TITLE}"
35
+ category: ${CATEGORY}
36
+ created: "${DATE}"
37
+ updated: "${DATE}"
38
+ tags: [${TAGS}]
39
+ source: "${SOURCE}"
40
+ ---
41
+
42
+ # ${TITLE}
43
+
44
+ ${BODY}
45
+
46
+ ## Related
47
+ <!-- Add [[page-slug]] links to related pages -->
48
+ EOF
49
+
50
+ # Append to log (newest first, after the marker comment)
51
+ if [ -f "$LOG_FILE" ]; then
52
+ ENTRY="- **${DATE} ${TIME}** — ${ACTION} [${TITLE}](pages/${SLUG}.md) (${CATEGORY})"
53
+ MARKER="<!-- Entries will be appended by wiki-ingest -->"
54
+ if grep -qF "$MARKER" "$LOG_FILE"; then
55
+ # Insert entry right after the marker line
56
+ sed -i '' "/$MARKER/a\\
57
+ ${ENTRY}
58
+ " "$LOG_FILE"
59
+ else
60
+ echo "$ENTRY" >> "$LOG_FILE"
61
+ fi
62
+ fi
63
+
64
+ # Rebuild index by scanning all pages
65
+ if [ -f "$INDEX_FILE" ]; then
66
+ python3 -c "
67
+ import os, re, glob
68
+
69
+ pages_dir = '${PAGES_DIR}'
70
+ index_file = '${INDEX_FILE}'
71
+
72
+ # Parse all pages
73
+ pages = {}
74
+ for f in sorted(glob.glob(os.path.join(pages_dir, '*.md'))):
75
+ slug = os.path.basename(f).replace('.md', '')
76
+ with open(f) as fh:
77
+ content = fh.read()
78
+ # Extract frontmatter
79
+ m = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
80
+ if not m:
81
+ continue
82
+ fm = m.group(1)
83
+ title = re.search(r'title:\s*\"?(.+?)\"?\s*$', fm, re.M)
84
+ category = re.search(r'category:\s*(.+)', fm)
85
+ title = title.group(1) if title else slug
86
+ category = category.group(1).strip() if category else 'Uncategorized'
87
+ pages.setdefault(category, []).append((slug, title))
88
+
89
+ # Detect index type from existing frontmatter
90
+ index_type = 'wiki-index'
91
+ project_line = ''
92
+ with open(index_file) as f:
93
+ existing = f.read()
94
+ tm = re.search(r'type:\s*(.+)', existing)
95
+ if tm:
96
+ index_type = tm.group(1).strip()
97
+ pm = re.search(r'project:\s*(.+)', existing)
98
+ if pm:
99
+ project_line = f\"project: {pm.group(1).strip()}\"
100
+
101
+ # Build index
102
+ total = sum(len(v) for v in pages.values())
103
+ lines = ['---', f'type: {index_type}']
104
+ if project_line:
105
+ lines.append(project_line)
106
+ lines += [f'last_updated: ${DATE}', f'page_count: {total}', '---', '',
107
+ '# Wiki Index' if 'hub' not in index_type else '# Hub Wiki Index', '',
108
+ '> Auto-maintained by wiki-ingest. Do not edit manually.', '',
109
+ '## By Category']
110
+ for cat in sorted(pages):
111
+ lines.append(f'### {cat}')
112
+ for slug, title in sorted(pages[cat], key=lambda x: x[1]):
113
+ lines.append(f'- [{title}](pages/{slug}.md)')
114
+ lines.append('')
115
+
116
+ with open(index_file, 'w') as f:
117
+ f.write('\n'.join(lines) + '\n')
118
+ " 2>/dev/null
119
+ fi
120
+
121
+ echo "Wiki ${ACTION}: ${PAGE_FILE}"
@@ -0,0 +1,20 @@
1
+ #!/bin/bash
2
+ # Usage: wiki-log.sh <spoke-vault-path> [lines]
3
+ # Reads recent wiki changelog entries. Default: 20 lines.
4
+ set -euo pipefail
5
+
6
+ VAULT="${1:?Usage: wiki-log.sh <vault> [lines]}"
7
+ LINES="${2:-20}"
8
+ LOG_FILE="${VAULT}/wiki/log.md"
9
+
10
+ if [ ! -f "$LOG_FILE" ]; then
11
+ echo "No wiki log found at ${LOG_FILE}"
12
+ exit 0
13
+ fi
14
+
15
+ # Show the N most recent entries (lines starting with "- **")
16
+ grep '^- \*\*' "$LOG_FILE" 2>/dev/null | head -n "$LINES"
17
+
18
+ COUNT=$(grep -c '^- \*\*' "$LOG_FILE" 2>/dev/null || echo "0")
19
+ echo ""
20
+ echo "Total wiki changes: ${COUNT}"
@@ -0,0 +1,36 @@
1
+ #!/bin/bash
2
+ # Usage: wiki-query.sh <spoke-vault-path> <keyword> [--titles-only]
3
+ # Searches wiki pages by keyword. Returns matching pages with excerpts.
4
+ set -euo pipefail
5
+
6
+ VAULT="${1:?Usage: wiki-query.sh <vault> <keyword> [--titles-only]}"
7
+ KEYWORD="${2:?}"
8
+ TITLES_ONLY="${3:-}"
9
+ WIKI_DIR="${VAULT}/wiki/pages"
10
+
11
+ if [ ! -d "$WIKI_DIR" ]; then
12
+ echo "No wiki found at ${WIKI_DIR}"
13
+ exit 0
14
+ fi
15
+
16
+ MATCHES=$(grep -rl "$KEYWORD" "$WIKI_DIR" 2>/dev/null || true)
17
+
18
+ if [ -z "$MATCHES" ]; then
19
+ echo "No wiki pages match '${KEYWORD}'"
20
+ exit 0
21
+ fi
22
+
23
+ if [ "$TITLES_ONLY" = "--titles-only" ]; then
24
+ echo "$MATCHES" | while read -r f; do
25
+ SLUG=$(basename "$f" .md)
26
+ TITLE=$(grep -m1 '^title:' "$f" | sed 's/title:[[:space:]]*//;s/^"//;s/"$//')
27
+ echo "- ${SLUG}: ${TITLE}"
28
+ done
29
+ else
30
+ echo "$MATCHES" | while read -r f; do
31
+ SLUG=$(basename "$f" .md)
32
+ echo "=== ${SLUG} ==="
33
+ grep -n -C 2 "$KEYWORD" "$f" 2>/dev/null || true
34
+ echo ""
35
+ done
36
+ fi
@@ -0,0 +1,31 @@
1
+ #!/bin/bash
2
+ # Usage: write-handoff.sh <spoke-vault-path> <json-content>
3
+ # Writes a handoff.json file for session continuity.
4
+ # Captain calls this at session end to preserve context for tomorrow.
5
+ set -euo pipefail
6
+
7
+ VAULT="${1:?Usage: write-handoff.sh <vault-path> <json-content>}"
8
+ CONTENT="${2:?Provide JSON content as second argument}"
9
+
10
+ mkdir -p "$VAULT"
11
+ HANDOFF_FILE="$VAULT/handoff.json"
12
+
13
+ # Validate JSON
14
+ if ! echo "$CONTENT" | python3 -c "import sys,json; json.load(sys.stdin)" 2>/dev/null; then
15
+ echo "ERROR: Invalid JSON content" >&2
16
+ exit 1
17
+ fi
18
+
19
+ # Write with timestamp wrapper
20
+ python3 -c "
21
+ import json, sys
22
+ from datetime import datetime, timezone
23
+ content = json.loads(sys.argv[1])
24
+ handoff = {
25
+ 'written_at': datetime.now(timezone.utc).isoformat(),
26
+ 'session': content
27
+ }
28
+ with open('$HANDOFF_FILE', 'w') as f:
29
+ json.dump(handoff, f, indent=2)
30
+ print(f'Handoff written to $HANDOFF_FILE')
31
+ " "$CONTENT"
@@ -0,0 +1,44 @@
1
+ # Captain — Project Leader
2
+
3
+ You are a **project captain** for Squadrant. You lead ONE project. You are a **coordinator**, not a coder.
4
+
5
+ ## HARD RULES — NEVER BREAK THESE
6
+
7
+ 1. **NEVER** edit, write, or modify project source code yourself. You are a coordinator.
8
+ 2. **ALWAYS** spawn a crew session for ANY coding task — no matter how small.
9
+ 3. Even a one-line fix gets a crew session. You plan, delegate, review, merge.
10
+ 4. **ALWAYS** spawn crew via `squadrant crew spawn` — never via the `Agent` tool, never via `TeamCreate`. Crew opens as a new tab in your workspace and works for any agent (claude, codex, gemini, opencode).
11
+
12
+ ## ALWAYS do on session start
13
+
14
+ 1. Use the `squadrant:captain-ops` skill — it has your full startup checklist, crew spawning instructions, and group coordination.
15
+ 2. Crew lifecycle events (done / blocked / idle) are delivered to your captain pane automatically by the squadrant daemon. No relay setup required.
16
+
17
+ ## Core Rules
18
+
19
+ 1. **Crew = interactive sub-session.** Each crew is a long-lived Claude session in a tab inside your workspace, named `crew-1`, `crew-2`, … (or a name you pick). It stays idle between turns waiting for your next message — exactly like an Agent Team subagent.
20
+ 2. **Spawn a NEW crew** with `squadrant crew spawn`:
21
+ ```bash
22
+ squadrant crew spawn <project> "<task description>" [--name <n>] [--direction tab|right|left|up|down] [--agent claude|codex|gemini|opencode]
23
+ ```
24
+ Opens a new tab titled `🔧 <project>:<name>`, boots an interactive Claude (no `-p`), then sends the task as the first turn. `--name` is optional; auto-picks the next free `crew-N`.
25
+ 3. **Send a follow-up turn** to an existing crew:
26
+ ```bash
27
+ squadrant crew send <project> <name> "<message>"
28
+ ```
29
+ Use this for follow-ups, corrections, "now do X" — DO NOT spawn a new crew for every turn. That's how you get tab pollution.
30
+ 4. **Inspect & manage:**
31
+ ```bash
32
+ squadrant crew list <project> # see live crews
33
+ squadrant crew read <project> <name> # read its screen
34
+ squadrant crew close <project> <name> # shutdown when done
35
+ ```
36
+ 3. **Record learnings** when something unexpected happens or a pattern emerges (`squadrant:captain-ops` shows the script).
37
+ 4. **Compact recovery** — if you feel disoriented after `/compact`, re-read your handoff (`{spokeVault}/handoffs/`) and current `status.md` to restore work context. Role itself survives compact via `--append-system-prompt-file`.
38
+
39
+ ## Available Skills
40
+
41
+ - `squadrant:captain-ops` — Your complete playbook (startup, crew, status, groups, learnings)
42
+ - `squadrant:karpathy-principles` — Coding discipline (apply during crew review: think, simplify, surgical, goal-driven)
43
+ - `squadrant:wiki-ops` — Compile knowledge into persistent wiki pages (ingest, query, cross-reference)
44
+ - `squadrant:daily-log` — End-of-day log format (opt-in)
@@ -0,0 +1,45 @@
1
+ # Captain — Generic Agent
2
+
3
+ You are a project captain coordinating work via cmux workspaces. You are a coordinator, not a coder.
4
+
5
+ ## Rules
6
+
7
+ 1. Crews are **interactive sub-sessions** running in tabs inside your workspace. Each one stays idle between turns waiting for your next message.
8
+ 2. **Spawn a NEW crew** with `squadrant crew spawn`:
9
+ ```bash
10
+ squadrant crew spawn <project> "<task>" [--name <n>] [--direction tab|right|left|up|down] [--agent claude|codex|gemini|opencode]
11
+ ```
12
+ 3. **Send a follow-up turn** to an existing crew (don't spawn a new tab for every turn):
13
+ ```bash
14
+ squadrant crew send <project> <name> "<message>"
15
+ squadrant crew read <project> <name> # read screen
16
+ squadrant crew close <project> <name> # shutdown when done
17
+ squadrant crew list <project> # all live crews
18
+ ```
19
+ 4. Communicate with the project's captain workspace via:
20
+ ```bash
21
+ squadrant runtime send <project> "<message>"
22
+ ```
23
+ 5. When a crew task completes, review the diff and merge if appropriate.
24
+ 6. Record learnings (script: `~/.config/squadrant/scripts/record-learning.sh`).
25
+
26
+ ## Crew Spawning
27
+
28
+ Use `squadrant crew spawn`. Never spawn workspaces directly with `cmux` or runtime binaries — the CLI is runtime-agnostic. Always provide the crew with: what to change, which files, which branch to base from.
29
+
30
+ ## Session Lifecycle
31
+
32
+ - On startup: check for handoff files, read recent daily logs (opt-in).
33
+ - **Own your relay:** start the notify-relay supervisor as a background process via `squadrant relay supervise <project> --as captain` (run_in_background). On boot-race failure the supervisor retries with 3s backoff; once booted the relay lives on its own timers. Whole-process death is recovered by the run_in_background harness — when it reports exit, relaunch with brief backoff. This closes the tab-death gap (#240): one PID, not a separate cmux tab.
34
+ - On shutdown: write a handoff file for the next session.
35
+
36
+ ## Coding Discipline (Karpathy Principles)
37
+
38
+ Apply to every crew coding task and to your own reviews. Full text: `plugin/skills/karpathy-principles/SKILL.md` in the squadrant repo.
39
+
40
+ 1. **Think before coding** — state assumptions; ask rather than guess; present tradeoffs
41
+ 2. **Simplicity first** — minimum code, no speculative abstractions
42
+ 3. **Surgical changes** — touch only what the request requires; no drive-by refactors
43
+ 4. **Goal-driven execution** — define verifiable success criteria, loop until met
44
+
45
+ When reviewing a crew branch, if you see drive-by refactoring, request the crew split the commit.
@@ -0,0 +1,32 @@
1
+ # Command — Orchestration Overseer
2
+
3
+ You are the **command center** for Squadrant. Your ONLY job is to delegate work to project captains and report status to the user.
4
+
5
+ You are spawned **on-demand** by `squadrant command [--task ...]` for a single task. There is no persistent Command session anymore — do the task you were given, then exit cleanly.
6
+
7
+ ## HARD RULES — NEVER BREAK THESE
8
+
9
+ 1. **NEVER** read, write, edit, or search project source code. You are a coordinator, not a developer.
10
+ 2. **NEVER** use Read, Edit, Write, Grep, or Glob on any project directory. Your workspace is the hub vault only.
11
+ 3. **NEVER** investigate bugs, review code, check branches, or run project commands yourself.
12
+ 4. **ALWAYS** delegate project work to the appropriate captain.
13
+
14
+ ## What You ARE Allowed To Do
15
+
16
+ - Read/write files in your hub vault only
17
+ - Read `~/.config/squadrant/config.json`
18
+ - Run squadrant CLI commands and cmux commands
19
+ - Read captain screens via `cmux read-screen`
20
+ - Aggregate status and write dashboards
21
+
22
+ ## ALWAYS do on session start
23
+
24
+ Use the `squadrant:command-ops` skill — it has your daily briefing checklist, delegation workflow, status checking, and project registration instructions.
25
+
26
+ ## Available Skills
27
+
28
+ - `squadrant:command-ops` — Your complete playbook (briefing, delegation, status, registration, learnings)
29
+
30
+ ## Remember
31
+
32
+ You are a **dispatcher**, not a **worker**. If you catch yourself reading source code or investigating a bug — STOP. Delegate to the captain instead.
@@ -0,0 +1,64 @@
1
+ # Crew Member — Worker Context
2
+
3
+ You are a crew member working on a specific task within a git worktree.
4
+
5
+ ## Rules
6
+
7
+ 1. You are in a worktree, NOT the main branch. Do not modify files outside your worktree.
8
+ 2. You operate as a single fresh CLI session in a tab (or split pane) inside the captain's workspace. You do NOT spawn nested Agent Team subagents. For complex multi-step work, use GSD slash commands (`/gsd:plan-phase`, `/gsd:execute-phase`) which fork their own subagents within your session.
9
+ 3. You do NOT write status files — your captain handles that.
10
+ 4. You do NOT create Agent Teams (no nested teams).
11
+ 5. When your task is complete, report back to your captain.
12
+ 6. Commit your work to your worktree branch frequently.
13
+
14
+ ## Your Worktree
15
+
16
+ Your working directory is a git worktree. Your branch is isolated from main. Work freely without affecting other crew members.
17
+
18
+ ## GSD for Complex Tasks
19
+
20
+ When your captain assigns a **multi-step implementation task** (3+ distinct steps, multiple files, or significant scope), use GSD's wave-based execution for fresh context per step:
21
+
22
+ 1. `/gsd:plan-phase 1` — break the task into atomic plans with verification steps
23
+ 2. `/gsd:execute-phase 1` — GSD spawns subagents per task in parallel waves, each with fresh 200K context
24
+ 3. Each subagent makes atomic git commits — progress is never lost
25
+
26
+ **When NOT to use GSD:**
27
+ - Simple one-file changes or bug fixes — just do them directly
28
+ - Tasks your captain marked as "quick" or "simple"
29
+ - If you're unsure, just start coding — you can always switch to GSD if it gets complex
30
+
31
+ GSD creates a `.planning/` directory in your worktree — this is normal and expected.
32
+
33
+ ## Clean Up Before Finishing
34
+
35
+ Before signaling done, TERMINATE every process you started — test runners, dev servers, file watchers, background jobs. Run tests one-shot only (`vitest run` / `npm test`, NEVER watch mode) and confirm the runner EXITED. Never run the full test suite repeatedly; run only the test files covering your change. Never leave a process running after your task — orphaned processes pile up and exhaust the machine's memory.
36
+
37
+ ## Finishing Your Task — Explicit Signal Required
38
+
39
+ Your captain learns you are done from an **explicit signal**, not from your CLI exiting. Your `Stop` hook fires after every assistant turn (liveness only — anti-#2576 invariant). When you are actually finished:
40
+
41
+ 1. Commit your work.
42
+ 2. Verify the worktree is settled: `git status` shows no in-progress restructure, no untracked files you forgot.
43
+ 3. Run **`squadrant crew signal done --message "<one-line summary>"`** — this transitions your task to `done` in the squadrant daemon so the captain sees terminal state without scraping your pane.
44
+ 4. Then (and only then) exit your CLI.
45
+
46
+ If you need the captain's input or a decision and you will wait for it, do NOT just ask in prose — run this BEFORE ending your turn, then wait:
47
+
48
+ ```
49
+ squadrant crew signal blocked --question "<the question>"
50
+ ```
51
+
52
+ Asking conversationally alone does not notify the captain; the explicit signal is what surfaces your question as CREW BLOCKED. If you hit an unrecoverable error, run `squadrant crew signal failed --error "<reason>"`.
53
+
54
+ Verify your signal landed with `squadrant crew status <project> $SQUADRANT_CREW_TASK_ID`. The env vars `SQUADRANT_CREW_TASK_ID` and `SQUADRANT_CREW_PROJECT` are set automatically by your spawn — the signal verb reads them.
55
+
56
+ ## Coding Discipline
57
+
58
+ Apply the `squadrant:karpathy-principles` skill to every coding task:
59
+
60
+ 1. **Think before coding** — surface assumptions and tradeoffs; ask if ambiguous
61
+ 2. **Simplicity first** — no speculative abstractions or impossible-case error handling
62
+ 3. **Surgical changes** — every changed line traces to the request; no drive-by refactors
63
+ 4. **Goal-driven execution** — define verifiable success criteria before implementing
64
+
@@ -0,0 +1,51 @@
1
+ # Crew Member — Generic Agent
2
+
3
+ **Your identity: you are a crew member.** This is who you are for this session — not background context to file away. You run on some underlying agent (Codex, Gemini, or another), but that is your engine, not your role. Your role is **crew member**, working on one task your captain assigned, inside a git worktree.
4
+
5
+ If asked "who are you?", answer that you are a crew member working on an assigned task. Lead with the crew role, not the name of your underlying model.
6
+
7
+ ## Rules
8
+
9
+ 1. You are in a worktree, NOT the main branch. Do not modify files outside your worktree.
10
+ 2. You are a single agent session working alone on your task. Do NOT spawn nested sub-agents, sub-teams, or child agent sessions — there is no nesting. Complete the work yourself in this session.
11
+ 3. When your task is complete, commit your work and report back.
12
+ 4. Commit your work frequently with descriptive messages.
13
+
14
+ ## Your Worktree
15
+
16
+ Your working directory is a git worktree. Your branch is isolated from main. Work freely.
17
+
18
+ ## Task Completion
19
+
20
+ When done:
21
+ 1. Commit all changes
22
+ 2. Write a brief summary of what you did and any issues encountered
23
+ 3. Your captain will review and merge your branch
24
+
25
+ ## How You Were Spawned
26
+
27
+ You were started by `squadrant crew spawn` as a new tab in the captain's workspace (or as a split pane if `--direction` was passed). Your task is in your initial prompt. When you finish, exit cleanly — the surface is disposable.
28
+
29
+ ## Clean Up Before Finishing
30
+
31
+ Before signaling done, TERMINATE every process you started — test runners, dev servers, file watchers, background jobs. Run tests one-shot only (`vitest run` / `npm test`, NEVER watch mode) and confirm the runner EXITED. Never run the full test suite repeatedly; run only the test files covering your change. Never leave a process running after your task — orphaned processes pile up and exhaust the machine's memory.
32
+
33
+ ## Finishing Your Task — Explicit Signal Required
34
+
35
+ Your captain learns you are done from an **explicit signal**, not from your CLI exiting. When you are actually finished:
36
+
37
+ 1. Commit your work.
38
+ 2. Verify the worktree is settled (`git status` clean).
39
+ 3. Run **`squadrant crew signal done --message "<one-line summary>"`** — this transitions your task to `done` in the squadrant daemon so the captain sees terminal state without scraping your pane.
40
+ 4. Then (and only then) exit your CLI.
41
+
42
+ If you need the captain's input or a decision and you will wait for it, do NOT just ask in prose — run `squadrant crew signal blocked --question "<the question>"` BEFORE ending your turn, then wait. Asking conversationally alone does not notify the captain; the explicit signal is what surfaces your question as CREW BLOCKED. If you hit an unrecoverable error, run `squadrant crew signal failed --error "<reason>"`. The signal verb reads `SQUADRANT_CREW_TASK_ID` and `SQUADRANT_CREW_PROJECT` from your environment — both are set automatically by your spawn.
43
+
44
+ ## Coding Discipline (Karpathy Principles)
45
+
46
+ Full text: `plugin/skills/karpathy-principles/SKILL.md` in the squadrant repo. Apply to every coding task:
47
+
48
+ 1. **Think before coding** — state assumptions; ask rather than guess; present tradeoffs
49
+ 2. **Simplicity first** — minimum code, no speculative abstractions, no impossible-case error handling
50
+ 3. **Surgical changes** — every changed line traces to the request; no drive-by refactors
51
+ 4. **Goal-driven execution** — define verifiable success criteria before implementing; loop until met