superspecs 0.1.0 → 0.2.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.
package/setup.sh CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/bin/bash
2
- # SuperSpecs Setup — symlinks skills into all supported AI agent directories
2
+ # SuperSpecs Setup — symlinks skills into supported AI agent directories
3
3
 
4
4
  set -e
5
5
 
@@ -11,9 +11,11 @@ SKILLS_DIR="$SCRIPT_DIR/.skills"
11
11
  # Falls back to SCRIPT_DIR for direct `bash setup.sh` usage inside the repo.
12
12
  PROJECT_DIR="${SUPERSPECS_PROJECT_DIR:-$SCRIPT_DIR}"
13
13
 
14
- # SUPERSPECS_SKIP_SYMLINKS=1 skips global/project skill symlinking (used by `superspecs init`)
14
+ # SUPERSPECS_SKIP_SYMLINKS=1 skips agent symlinking (used by `superspecs init`)
15
15
  SKIP_SYMLINKS="${SUPERSPECS_SKIP_SYMLINKS:-0}"
16
16
 
17
+ # ─── Banner ───────────────────────────────────────────────────────────────────
18
+
17
19
  echo ""
18
20
  echo "╔══════════════════════════════════════════════════════════╗"
19
21
  echo "║ SuperSpecs Setup ║"
@@ -21,48 +23,250 @@ echo "║ Plan · Execute · Verify · Ship ║"
21
23
  echo "╚══════════════════════════════════════════════════════════╝"
22
24
  echo ""
23
25
 
24
- # ─── Helper ───────────────────────────────────────────────────────────────────
26
+ # ─── Agent definitions ────────────────────────────────────────────────────────
27
+ # Indices 0-3: project-level | Indices 4-11: global
28
+
29
+ LABELS=(
30
+ "Claude Code (project)"
31
+ "Cursor (project)"
32
+ "Windsurf (project)"
33
+ "OpenCode / Aider / generic (project)"
34
+ "Claude Code (global)"
35
+ "Codex (global)"
36
+ "Gemini CLI (global)"
37
+ "GitHub Copilot CLI (global)"
38
+ "OpenCode (global)"
39
+ "Cursor (global)"
40
+ "Kiro (global)"
41
+ "Pi (global)"
42
+ )
43
+
44
+ DIRS=(
45
+ "$PROJECT_DIR/.claude/skills"
46
+ "$PROJECT_DIR/.cursor/skills"
47
+ "$PROJECT_DIR/.windsurf/skills"
48
+ "$PROJECT_DIR/.agents/skills"
49
+ "$HOME/.claude/skills"
50
+ "$HOME/.codex/skills"
51
+ "$HOME/.gemini/skills"
52
+ "$HOME/.copilot/skills"
53
+ "$HOME/.agents/skills"
54
+ "$HOME/.cursor/skills"
55
+ "$HOME/.kiro/skills"
56
+ "$HOME/.pi/agent/skills"
57
+ )
58
+
59
+ # Selection state (1=selected, 0=deselected) — all selected by default
60
+ SEL=( 1 1 1 1 1 1 1 1 1 1 1 1 )
25
61
 
62
+ # ─── Helpers ─────────────────────────────────────────────────────────────────
63
+
64
+ # Skills: create <name>/SKILL.md directory structure (required by Claude + OpenCode discovery)
26
65
  symlink_skills() {
27
66
  local target_dir="$1"
28
67
  local label="$2"
29
68
  mkdir -p "$target_dir"
30
69
  for skill_dir in "$SKILLS_DIR"/*/; do
70
+ local skill_name
31
71
  skill_name=$(basename "$skill_dir")
32
- skill_file="$skill_dir/SKILL.md"
72
+ local skill_file="$skill_dir/SKILL.md"
33
73
  if [ -f "$skill_file" ]; then
34
- ln -sf "$skill_file" "$target_dir/$skill_name.md" 2>/dev/null || true
74
+ rm -f "$target_dir/$skill_name.md" 2>/dev/null || true # remove old flat-file if present
75
+ mkdir -p "$target_dir/$skill_name"
76
+ ln -sf "$skill_file" "$target_dir/$skill_name/SKILL.md" 2>/dev/null || true
35
77
  fi
36
78
  done
37
79
  echo " ✓ $label"
38
80
  }
39
81
 
82
+ # Commands: generate a clean command .md file for each skill
83
+ # File name determines command name — NOT frontmatter.
84
+ # Claude Code: <cmd_dir>/superspecs/<slash_cmd>.md → /superspecs:<slash_cmd>
85
+ # OpenCode: <cmd_dir>/superspecs-<slash_cmd>.md → /superspecs-<slash_cmd>
86
+ # NOTE: Only `description` frontmatter is written — agent-specific fields
87
+ # (slash_command, name, phase) from SKILL.md are intentionally omitted.
88
+ install_commands() {
89
+ local cmd_dir="$1" # base commands directory
90
+ local prefix="$2" # "" (use superspecs/ subdir) or "superspecs-" (flat prefix)
91
+ local label="$3"
92
+ local target_dir
93
+
94
+ if [ -z "$prefix" ]; then
95
+ target_dir="$cmd_dir/superspecs"
96
+ else
97
+ target_dir="$cmd_dir"
98
+ fi
99
+ mkdir -p "$target_dir"
100
+
101
+ for skill_dir in "$SKILLS_DIR"/*/; do
102
+ local skill_file="$skill_dir/SKILL.md"
103
+ [ -f "$skill_file" ] || continue
104
+
105
+ # Read slash_command from frontmatter (determines the command file name)
106
+ local slash_cmd
107
+ slash_cmd=$(grep '^slash_command:' "$skill_file" 2>/dev/null | head -1 \
108
+ | sed 's/^slash_command: *//' | tr -d '"' | tr -d "'")
109
+ [ -z "$slash_cmd" ] && continue
110
+ case "$slash_cmd" in *"<"*) continue ;; esac # skip template placeholders
111
+
112
+ # Read description from frontmatter (the only frontmatter field agents need)
113
+ local description
114
+ description=$(grep '^description:' "$skill_file" 2>/dev/null | head -1 \
115
+ | sed 's/^description: *//')
116
+
117
+ # Extract body = everything after the closing frontmatter `---`
118
+ local body
119
+ body=$(awk 'BEGIN{c=0} /^---/{c++; next} c>=2{print}' "$skill_file")
120
+
121
+ # Remove old file or symlink, then write a real generated command file
122
+ local cmd_file="$target_dir/${prefix}${slash_cmd}.md"
123
+ rm -f "$cmd_file" 2>/dev/null || true
124
+ {
125
+ printf -- '---\ndescription: %s\n---\n\n' "$description"
126
+ printf '%s\n' "$body"
127
+ } > "$cmd_file"
128
+ done
129
+ echo " ✓ $label"
130
+ }
131
+
132
+ # ─── Selection helpers ────────────────────────────────────────────────────────
133
+
134
+ _apply_selection() {
135
+ # Reads newline-separated selected labels from $1, updates SEL array
136
+ local result="$1"
137
+ SEL=( 0 0 0 0 0 0 0 0 0 0 0 0 )
138
+ while IFS= read -r line; do
139
+ [ -z "$line" ] && continue
140
+ for ((i=0; i<12; i++)); do
141
+ [ "${LABELS[$i]}" = "$line" ] && SEL[$i]=1
142
+ done
143
+ done <<< "$result"
144
+ }
145
+
146
+ _select_with_fzf() {
147
+ local result
148
+ result=$(printf '%s\n' "${LABELS[@]}" | \
149
+ fzf --multi \
150
+ --bind 'start:select-all' \
151
+ --bind 'ctrl-a:select-all' \
152
+ --bind 'ctrl-d:deselect-all' \
153
+ --height='~100%' \
154
+ --layout=reverse \
155
+ --border=rounded \
156
+ --prompt=' Install › ' \
157
+ --header=$'TAB/SPACE toggle · CTRL-A select all · CTRL-D deselect all · ENTER confirm\n\n Project: Claude Code · Cursor · Windsurf · OpenCode\n Global: Claude Code · Codex · Gemini · Copilot · OpenCode · Cursor · Kiro · Pi'
158
+ ) || return 1
159
+ _apply_selection "$result"
160
+ }
161
+
162
+ _select_with_gum() {
163
+ local selected_str result
164
+ # Build comma-separated pre-selection string from all labels
165
+ selected_str=$(printf '%s,' "${LABELS[@]}")
166
+ selected_str="${selected_str%,}" # remove trailing comma
167
+
168
+ result=$(gum choose --no-limit \
169
+ --height=16 \
170
+ --header="Select agents to install (SPACE toggle, ENTER confirm):" \
171
+ --selected="$selected_str" \
172
+ "${LABELS[@]}") || return 1
173
+ _apply_selection "$result"
174
+ }
175
+
176
+ _select_fallback() {
177
+ # Simple numbered list — press ENTER to install all, or enter numbers to skip
178
+ echo " Agents available:"
179
+ echo ""
180
+ echo " ── Project ──────────────────────────────────"
181
+ for ((i=0; i<4; i++)); do
182
+ printf " %2d) %s\n" $((i+1)) "${LABELS[$i]}"
183
+ done
184
+ echo ""
185
+ echo " ── Global ───────────────────────────────────"
186
+ for ((i=4; i<12; i++)); do
187
+ printf " %2d) %s\n" $((i+1)) "${LABELS[$i]}"
188
+ done
189
+ echo ""
190
+ printf " Enter numbers to SKIP (e.g. 5 6 7), or press ENTER to install all: "
191
+ local skip_input
192
+ read -r skip_input
193
+ if [ -n "$skip_input" ]; then
194
+ for n in $skip_input; do
195
+ local idx=$((n-1))
196
+ [ "$idx" -ge 0 ] && [ "$idx" -lt 12 ] && SEL[$idx]=0
197
+ done
198
+ fi
199
+ }
200
+
201
+ # ─── Tool detection + multiselect ─────────────────────────────────────────────
202
+
203
+ run_multiselect() {
204
+ [ -t 0 ] && [ -t 1 ] || return 0 # Skip when non-interactive (CI, piped)
205
+
206
+ if command -v fzf >/dev/null 2>&1; then
207
+ _select_with_fzf && return 0
208
+ fi
209
+
210
+ if command -v gum >/dev/null 2>&1; then
211
+ _select_with_gum && return 0
212
+ fi
213
+
214
+ # Neither fzf nor gum found — offer to install gum via brew
215
+ if command -v brew >/dev/null 2>&1; then
216
+ echo " For a better selection UI, install gum (Charm):"
217
+ echo " brew install gum"
218
+ echo ""
219
+ printf " Install gum now? [y/N] "
220
+ local answer
221
+ read -r answer
222
+ echo ""
223
+ if [[ "$answer" =~ ^[Yy]$ ]]; then
224
+ brew install gum
225
+ _select_with_gum && return 0
226
+ fi
227
+ fi
228
+
229
+ # Final fallback: numbered list
230
+ _select_fallback
231
+ }
232
+
40
233
  # ─── Project-level + Global symlinks ────────────────────────────────────────
41
234
 
42
235
  if [ "$SKIP_SYMLINKS" != "1" ]; then
43
- echo "→ Project-level agent skills..."
44
- symlink_skills "$PROJECT_DIR/.claude/skills" "Claude Code (project)"
45
- symlink_skills "$PROJECT_DIR/.cursor/skills" "Cursor (project)"
46
- symlink_skills "$PROJECT_DIR/.windsurf/skills" "Windsurf (project)"
47
- symlink_skills "$PROJECT_DIR/.agents/skills" "OpenCode / Aider / generic (project)"
236
+ run_multiselect
237
+
238
+ proj_done=0
239
+ glob_done=0
240
+
241
+ for ((i=0; i<4; i++)); do
242
+ if [ "${SEL[$i]}" -eq 1 ]; then
243
+ [ "$proj_done" -eq 0 ] && echo "→ Project-level agent skills..." && proj_done=1
244
+ symlink_skills "${DIRS[$i]}" "${LABELS[$i]}"
245
+ fi
246
+ done
247
+ [ "$proj_done" -eq 1 ] && echo ""
48
248
 
249
+ for ((i=4; i<12; i++)); do
250
+ if [ "${SEL[$i]}" -eq 1 ]; then
251
+ [ "$glob_done" -eq 0 ] && echo "→ Global agent skills..." && glob_done=1
252
+ symlink_skills "${DIRS[$i]}" "${LABELS[$i]}"
253
+ fi
254
+ done
255
+ [ "$glob_done" -eq 1 ] && echo ""
256
+
257
+ # ── Commands ── always install for Claude Code + OpenCode (project + global)
258
+ echo "→ Installing slash commands..."
259
+ # Claude Code (subdir style → /superspecs:<cmd>)
260
+ install_commands "$PROJECT_DIR/.claude/commands" "" "Claude Code commands (project)"
261
+ install_commands "$HOME/.claude/commands" "" "Claude Code commands (global)"
262
+ # OpenCode (flat prefix → /superspecs-<cmd>)
263
+ install_commands "$PROJECT_DIR/.opencode/commands" "superspecs-" "OpenCode commands (project)"
264
+ install_commands "$HOME/.config/opencode/commands" "superspecs-" "OpenCode commands (global)"
49
265
  echo ""
50
- echo "→ Global agent skills..."
51
- symlink_skills "$HOME/.claude/skills" "Claude Code (global)"
52
- symlink_skills "$HOME/.codex/skills" "Codex (global)"
53
- symlink_skills "$HOME/.gemini/skills" "Gemini CLI (global)"
54
- symlink_skills "$HOME/.copilot/skills" "GitHub Copilot CLI (global)"
55
- symlink_skills "$HOME/.agents/skills" "OpenCode (global)"
56
-
57
- [ -d "$HOME/.windsurf" ] && symlink_skills "$HOME/.windsurf/skills" "Windsurf (global)"
58
- [ -d "$HOME/.cursor" ] && symlink_skills "$HOME/.cursor/skills" "Cursor (global)"
59
- [ -d "$HOME/.kiro" ] && symlink_skills "$HOME/.kiro/skills" "Kiro (global)"
60
- [ -d "$HOME/.pi" ] && symlink_skills "$HOME/.pi/agent/skills" "Pi (global)"
61
266
  fi
62
267
 
63
268
  # ─── Initialize SuperSpecs directories ───────────────────────────────────────
64
269
 
65
- echo ""
66
270
  echo "→ Initializing project structure..."
67
271
 
68
272
  mkdir -p "$PROJECT_DIR/superspec/specs"
@@ -70,26 +274,257 @@ mkdir -p "$PROJECT_DIR/superspec/phases"
70
274
  mkdir -p "$PROJECT_DIR/superspec/archive"
71
275
  mkdir -p "$PROJECT_DIR/superspec/wiki"
72
276
 
73
- if [ ! -f "$PROJECT_DIR/superspec/wiki/_index.md" ]; then
74
- cat > "$PROJECT_DIR/superspec/wiki/_index.md" << 'WIKIEOF'
277
+ # ── Obsidian vault config ──────────────────────────────────────────────────
278
+ # Creates superspec/wiki/.obsidian/ so the wiki can be opened as an Obsidian
279
+ # vault directly. Workspace and plugin-data files are gitignored.
280
+
281
+ OBSIDIAN_DIR="$PROJECT_DIR/superspec/wiki/.obsidian"
282
+ mkdir -p "$OBSIDIAN_DIR"
283
+
284
+ if [ ! -f "$OBSIDIAN_DIR/app.json" ]; then
285
+ cat > "$OBSIDIAN_DIR/app.json" << 'APPEOF'
286
+ {
287
+ "attachmentFolderPath": "_attachments",
288
+ "newFileLocation": "folder",
289
+ "newFileFolderPath": "",
290
+ "useMarkdownLinks": false,
291
+ "showUnsupportedFiles": false,
292
+ "promptDelete": true,
293
+ "trashOption": "local"
294
+ }
295
+ APPEOF
296
+ fi
297
+
298
+ if [ ! -f "$OBSIDIAN_DIR/core-plugins.json" ]; then
299
+ cat > "$OBSIDIAN_DIR/core-plugins.json" << 'CPEOF'
300
+ [
301
+ "file-explorer",
302
+ "global-search",
303
+ "switcher",
304
+ "graph",
305
+ "backlinks",
306
+ "outgoing-link",
307
+ "tag-pane",
308
+ "page-preview",
309
+ "outline",
310
+ "starred",
311
+ "command-palette",
312
+ "file-recovery",
313
+ "templates",
314
+ "word-count"
315
+ ]
316
+ CPEOF
317
+ fi
318
+
319
+ # Gitignore for vault-local / user-specific Obsidian files
320
+ if [ ! -f "$OBSIDIAN_DIR/.gitignore" ]; then
321
+ cat > "$OBSIDIAN_DIR/.gitignore" << 'OGIEOF'
322
+ # User-specific Obsidian state — do not commit
323
+ workspace.json
324
+ workspace-mobile.json
325
+ cache
326
+ .trash/
327
+ plugins/*/data.json
328
+ OGIEOF
329
+ fi
330
+
331
+ # ── Wiki 3-layer structure (Karpathy LLM Wiki pattern) ────────────────────
332
+ # raw/ — immutable source material (agent reads, never modifies)
333
+ # wiki/ — compiled knowledge base (agent writes on ingest/query/lint-fix)
334
+ # .skills/verify-wiki/SKILL.md — schema / operating rules
335
+
336
+ mkdir -p "$PROJECT_DIR/superspec/wiki/raw"
337
+
338
+ # raw/.gitkeep so the folder is tracked in git
339
+ if [ ! -f "$PROJECT_DIR/superspec/wiki/raw/.gitkeep" ]; then
340
+ touch "$PROJECT_DIR/superspec/wiki/raw/.gitkeep"
341
+ fi
342
+
343
+ # raw/README.md — instructions for humans dropping in source material
344
+ if [ ! -f "$PROJECT_DIR/superspec/wiki/raw/README.md" ]; then
345
+ cat > "$PROJECT_DIR/superspec/wiki/raw/README.md" << 'RAWEOF'
346
+ # raw/ — Source Material
347
+
348
+ Drop articles, PDFs, bookmarks, meeting notes, and external docs here.
349
+
350
+ **Rules:**
351
+ - Agent reads this folder but never edits or deletes files here.
352
+ - You commit these files; the agent compiles them into `../` (the wiki).
353
+ - To compile a raw document: `/superspecs:wiki-ingest <filename>`
354
+ - To compile a completed spec: `/superspecs:wiki <slug>`
355
+
356
+ Supported: `.md`, `.txt`, `.pdf` (text-extractable)
357
+ RAWEOF
358
+ fi
359
+
360
+ # ── Wiki home page ─────────────────────────────────────────────────────────
361
+
362
+ TODAY=$(date +%Y-%m-%d 2>/dev/null || echo "")
363
+
364
+ if [ ! -f "$PROJECT_DIR/superspec/wiki/Home.md" ]; then
365
+ cat > "$PROJECT_DIR/superspec/wiki/Home.md" << HOMEEOF
366
+ ---
367
+ title: Wiki Home
368
+ tags: [index, home]
369
+ updated: $TODAY
370
+ ---
371
+
75
372
  # Project Wiki
76
373
 
77
- Maintained by SuperSpecs. Distilled knowledge from shipped features.
374
+ Compiled knowledge base architecture decisions, patterns, trade-offs, gotchas.
375
+
376
+ > **Obsidian vault** — open \`superspec/wiki/\` in [Obsidian](https://obsidian.md) for graph view, backlinks, tag search, and hover previews.
78
377
 
79
378
  ## Domains
80
379
 
81
- (Added automatically via /wiki after each shipped feature)
380
+ | Domain | Description | Last updated |
381
+ |--------|-------------|-------------|
382
+
383
+ _(domains added automatically by \`/superspecs:wiki\` as features ship)_
82
384
 
83
385
  ## Recent Updates
84
386
 
85
- (Updated by /wiki)
86
- WIKIEOF
387
+ _(last 10 entries — full history in [[log]])_
388
+
389
+ ---
390
+
391
+ ## Wiki Operations
392
+
393
+ | Command | What it does |
394
+ |---------|-------------|
395
+ | \`/superspecs:wiki <slug>\` | Compile a shipped spec into wiki pages |
396
+ | \`/superspecs:wiki-query\` | Query the compiled wiki |
397
+ | \`/superspecs:wiki-lint\` | Health check: orphans, broken links, contradictions |
398
+
399
+ ---
400
+
401
+ _Maintained by [SuperSpecs](https://github.com/fokkerone/superspecs)_
402
+ HOMEEOF
403
+ fi
404
+
405
+ # ── Wiki log (append-only activity log) ───────────────────────────────────
406
+
407
+ if [ ! -f "$PROJECT_DIR/superspec/wiki/log.md" ]; then
408
+ cat > "$PROJECT_DIR/superspec/wiki/log.md" << LOGEOF
409
+ ---
410
+ title: Wiki Log
411
+ tags: [log, activity]
412
+ ---
413
+
414
+ # Wiki Log
415
+
416
+ Append-only activity log. Every ingest, query, and lint run appends an entry here.
417
+
418
+ > grep-friendly: \`grep "## \[" log.md\` lists all events
419
+
420
+ ---
421
+
422
+ ## [$TODAY] init | Wiki initialized
423
+
424
+ - Structure: \`raw/\` (sources) + \`wiki/\` (compiled) + \`.skills/verify-wiki/SKILL.md\` (schema)
425
+ - Vault ready to open in Obsidian
426
+
427
+ LOGEOF
87
428
  fi
88
429
 
89
430
  if [ ! -f "$PROJECT_DIR/superspec/wiki/_manifest.json" ]; then
90
431
  echo '{"sources":[]}' > "$PROJECT_DIR/superspec/wiki/_manifest.json"
91
432
  fi
92
433
 
434
+ # ── Wiki meta directory (taxonomy, insights) ───────────────────────────────
435
+
436
+ mkdir -p "$PROJECT_DIR/superspec/wiki/_meta"
437
+ mkdir -p "$PROJECT_DIR/superspec/wiki/_archives"
438
+
439
+ if [ ! -f "$PROJECT_DIR/superspec/wiki/_meta/taxonomy.md" ]; then
440
+ cat > "$PROJECT_DIR/superspec/wiki/_meta/taxonomy.md" << 'TAXEOF'
441
+ ---
442
+ title: Wiki Taxonomy
443
+ updated: ""
444
+ ---
445
+
446
+ # Wiki Taxonomy
447
+
448
+ Canonical vocabulary for this vault: domain folders and tags.
449
+ - Run `/superspecs:tag-taxonomy` to audit and normalize tags.
450
+ - Run `/superspecs:wiki-lint` to detect domain drift.
451
+
452
+ ---
453
+
454
+ ## Domains
455
+
456
+ Domains are concern-centric, not feature-centric. A page's domain describes *what the
457
+ knowledge is about*, not which feature introduced it. Feature traceability lives in
458
+ `spec:` frontmatter, not in the folder name.
459
+
460
+ ### Core Domains
461
+
462
+ | Domain | Folder | What goes here |
463
+ |--------|--------|----------------|
464
+ | `patterns` | `patterns/` | Cross-cutting implementation patterns: error handling, caching, retry, testing |
465
+ | `decisions` | `decisions/` | Architecture Decision Records — why X was chosen over Y |
466
+ | `auth` | `auth/` | Authentication, authorization, sessions, tokens |
467
+ | `api` | `api/` | API contracts, endpoint design, versioning, request/response shapes |
468
+ | `data` | `data/` | Data models, schemas, storage strategy, migrations |
469
+ | `ui` | `ui/` | Frontend components, routing, state management, styling patterns |
470
+ | `infra` | `infra/` | Deployment, CI/CD, environment config, hosting |
471
+ | `techstack` | `techstack/` | Stack profile and library choices (managed by /techstack) |
472
+
473
+ ### Routing Rules
474
+
475
+ When ingesting a feature, assign each knowledge unit to a domain using this decision tree:
476
+
477
+ 1. **Reusable cross-cutting pattern** (error handling, caching, retry, logging)? → `patterns/`
478
+ 2. **Architecture decision** — why X was chosen over Y? → `decisions/`
479
+ 3. **Auth, sessions, tokens, permissions**? → `auth/`
480
+ 4. **API contract, endpoint, or request/response shape**? → `api/`
481
+ 5. **Data model, schema, or storage decision**? → `data/`
482
+ 6. **Infrastructure or deployment**? → `infra/`
483
+ 7. **Frontend / UI concern**? → `ui/`
484
+ 8. **Feature-specific knowledge that fits none of the above**?
485
+ → Create a domain named after the feature slug (e.g. `payment-flow/`)
486
+ → Add it to this file under "Project Domains" before creating the folder
487
+
488
+ **One domain per page.** If a page spans multiple concerns, split it into separate pages.
489
+ **Prefer existing domains.** Only create a new domain if nothing above fits.
490
+
491
+ ### Project Domains
492
+
493
+ _(feature-specific domains added here as the project grows)_
494
+
495
+ ---
496
+
497
+ ## Domain Tags
498
+
499
+ Tags mirror domain names. Every page gets a tag matching its domain.
500
+
501
+ - `auth` — authentication and authorization
502
+ - `api` — API design and contracts
503
+ - `data` — data models and storage
504
+ - `ui` — frontend and interface
505
+ - `infra` — infrastructure and deployment
506
+ - `patterns` — reusable implementation patterns
507
+ - `decisions` — architecture decision records
508
+
509
+ ## Topic Tags
510
+
511
+ _(add project-specific topic tags here)_
512
+
513
+ ## Meta Tags
514
+
515
+ - `index` — index and home pages (reserved)
516
+ - `log` — activity log (reserved)
517
+ - `insights` — generated insights pages (reserved)
518
+ - `lint` — lint report pages (reserved)
519
+ - `query-derived` — pages created from /wiki-query results
520
+ - `capture` — pages created from /wiki-capture
521
+
522
+ ## Aliases
523
+
524
+ _(non-canonical → canonical mappings, managed by /tag-taxonomy)_
525
+ TAXEOF
526
+ fi
527
+
93
528
  # ─── Done ─────────────────────────────────────────────────────────────────────
94
529
 
95
530
  echo ""
@@ -99,13 +534,22 @@ echo "╚═══════════════════════
99
534
  echo ""
100
535
  echo " Open your agent and say: \"Tell me about your superspecs\""
101
536
  echo ""
102
- echo " Start your first feature:"
103
- echo " /discuss ← capture decisions"
104
- echo " /spec ← write the spec"
105
- echo " /pick-spec validate + prepare"
106
- echo " /branch ← create worktree"
107
- echo " /subagent execute with TDD"
108
- echo " /check-tests"
109
- echo " /wiki"
110
- echo " /ship"
537
+ echo " Claude Code / Cursor: /superspecs:<cmd>"
538
+ echo " OpenCode: /superspecs-<cmd>"
539
+ echo ""
540
+ echo " Wiki as Obsidian vault → open superspec/wiki/ in Obsidian"
541
+ echo ""
542
+ echo " First feature workflow:"
543
+ echo " /superspecs:techstack (or /superspecs-techstack)"
544
+ echo " /superspecs:discuss (or /superspecs-discuss)"
545
+ echo " /superspecs:spec (or /superspecs-spec)"
546
+ echo " /superspecs:grill (or /superspecs-grill)"
547
+ echo " /superspecs:pick-spec (or /superspecs-pick-spec)"
548
+ echo " /superspecs:branch (or /superspecs-branch)"
549
+ echo " /superspecs:subagent (or /superspecs-subagent)"
550
+ echo " /superspecs:tdd (or /superspecs-tdd)"
551
+ echo " /superspecs:code-review (or /superspecs-code-review)"
552
+ echo " /superspecs:check-tests (or /superspecs-check-tests)"
553
+ echo " /superspecs:wiki (or /superspecs-wiki)"
554
+ echo " /superspecs:ship (or /superspecs-ship)"
111
555
  echo ""