Compare commits

...

4 Commits

Author SHA1 Message Date
Bastien Chanot
26658c4962 chore(memory): journal 2026-06-25
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W9sqAwZxBMZSynZoVrEJhd
2026-06-25 00:41:46 +02:00
Bastien Chanot
52164d6261 chore(memory): BDR-031 + BLK-009 + LRN-043 + LRN-044
- BDR-031: global CLAUDE.md lightening = compression, not path-scope /
  externalization (path-scoped user rules broken, #21858). 317 -> 275.
- BLK-009: user-level path-scoped rules don't load (#21858, 2.1.190),
  proven by 3-file probe. Upstream/open.
- LRN-043: routing compression — cut name-obvious lines, keep
  non-derivable signal (misleading names, gstack fallbacks) + catch-all.
- LRN-044: Edit/Write refuse to write through a symlink — resolve to
  the real path (readlink -f) first.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W9sqAwZxBMZSynZoVrEJhd
2026-06-25 00:33:01 +02:00
Bastien Chanot
990318ce9d docs(claude-md): trim decorative separators + blank lines
Whitespace-only rognage, zero content/instruction changed: 286 -> 275.
- Drop 4 '---' section rules (the '#' headers already delimit sections).
- Drop 2 intro->list blanks (consistency with the compressed sections).
- Drop 1 orphan header-to-header blank (Tooling & skills -> Skill routing).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W9sqAwZxBMZSynZoVrEJhd
2026-06-25 00:29:47 +02:00
Bastien Chanot
ba743cf356 docs(claude-md): compress routing + design + graphify
Universal global config (loaded every session): 317 -> 286 lines (-31).
- Routing: drop name-obvious lines (covered by skill descriptions), keep
  non-obvious only (gstack fallbacks, cryptic names, disambiguation) +
  dense catch-all. Restore plan-eng-review + validate (misleading names),
  add feat/hotfix/bugfix file-count pointer.
- Design: compress + make the FILE signal explicit (UI-file edits trigger
  the toolchain, not just the prompt keyword).
- graphify: densify conditional rules.
No path-scope / no externalization: user-level path-scoped rules do not
load (issue #21858, 2.1.190) -> compression is the only safe lever.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W9sqAwZxBMZSynZoVrEJhd
2026-06-25 00:21:42 +02:00
5 changed files with 86 additions and 78 deletions

View File

@ -106,3 +106,14 @@ rules:
- **2026-06-23 UPDATE — Solution REVERTED, status downgraded to UPSTREAM/open** (commit b9c3937): the `PLAYWRIGHT_HOST_PLATFORM_OVERRIDE` solution above does NOT work on 26.04. The fallback build downloads to 100% then HANGS at extraction (chrome binary never appears, no headless-shell download starts; reproduced on real machine + sandbox) → turned a 0.5s fast-fail into an install-blocking hang (user Ctrl+C). Reverted to the fast-fail (non-fatal; gstack OFF by default, browser only for /browse,/qa,screenshots). The earlier "verified ldd + headless render" was an isolated test on a sibling already-extracted build (rev 1228) — it masked the rev-1208 install-path hang. **Real fix = upstream**: gstack bumps Playwright to a version that lists ubuntu26.04. Until then gstack's browser is unavailable on 26.04, install completes cleanly. See [[LRN-038]] correction. - **2026-06-23 UPDATE — Solution REVERTED, status downgraded to UPSTREAM/open** (commit b9c3937): the `PLAYWRIGHT_HOST_PLATFORM_OVERRIDE` solution above does NOT work on 26.04. The fallback build downloads to 100% then HANGS at extraction (chrome binary never appears, no headless-shell download starts; reproduced on real machine + sandbox) → turned a 0.5s fast-fail into an install-blocking hang (user Ctrl+C). Reverted to the fast-fail (non-fatal; gstack OFF by default, browser only for /browse,/qa,screenshots). The earlier "verified ldd + headless render" was an isolated test on a sibling already-extracted build (rev 1228) — it masked the rev-1208 install-path hang. **Real fix = upstream**: gstack bumps Playwright to a version that lists ubuntu26.04. Until then gstack's browser is unavailable on 26.04, install completes cleanly. See [[LRN-038]] correction.
- **2026-06-23 FINAL — RESOLVED** (commit 3b8ffb1): gstack browser now works on Ubuntu 26.04. Two layers fixed: (1) bumped gstack's pinned Playwright 1.58.2 → 1.61 (`bun add playwright@latest` in the submodule; 1.61 ships a native ubuntu26.04 build — chromium rev 1228), automated in the installer (`gstack_bump_playwright_if_unsupported`, idempotent, OS-gated); (2) `GSTACK_CHROMIUM_NO_SANDBOX=1` to work around the AppArmor userns restriction (`sysctl kernel.apparmor_restrict_unprivileged_userns=1`), persisted to `.bashrc` + installer Step 9 (sysctl-gated). Verified end-to-end: `browse goto https://example.com` → "Navigated (200)". Caveat: the Playwright bump is a local submodule edit, reset by `git submodule update`, re-applied by the next install. See [[BDR-029]], [[LRN-040]]. - **2026-06-23 FINAL — RESOLVED** (commit 3b8ffb1): gstack browser now works on Ubuntu 26.04. Two layers fixed: (1) bumped gstack's pinned Playwright 1.58.2 → 1.61 (`bun add playwright@latest` in the submodule; 1.61 ships a native ubuntu26.04 build — chromium rev 1228), automated in the installer (`gstack_bump_playwright_if_unsupported`, idempotent, OS-gated); (2) `GSTACK_CHROMIUM_NO_SANDBOX=1` to work around the AppArmor userns restriction (`sysctl kernel.apparmor_restrict_unprivileged_userns=1`), persisted to `.bashrc` + installer Step 9 (sysctl-gated). Verified end-to-end: `browse goto https://example.com` → "Navigated (200)". Caveat: the Playwright bump is a local submodule edit, reset by `git submodule update`, re-applied by the next install. See [[BDR-029]], [[LRN-040]].
---
## BLK-009 — user-level path-scoped rules don't load (#21858) — still broken in CC 2.1.190
- **Date**: 2026-06-25
- **Friction**: tried to scope a global rule to matching files via `paths:` frontmatter in `~/.claude/rules/<name>.md` — the rule never injects, even when a matching file (`*.probe`) is read in a fresh session. Blocks any "load this guidance only for matching files" strategy at the user level.
- **Real cause**: GitHub issue #21858 — user-level (`~/.claude/rules/`) rules carrying `paths:` frontmatter are not evaluated/injected; still unfixed in 2.1.190. (Project-level path-scoped rules not tested here.)
- **Probe method**: 3-file probe — `_probe.md` (`paths: ["**/*.probe"]`, sentinel `SENTINEL_USER_RULE_LOADED`), `_probe_ctl.md` (NO `paths`, control sentinel `CONTROL_NOPATHS_LOADED`), `_probe_target.probe` (target, read in a fresh session). Result: control sentinel PRESENT in session context, path-scoped sentinel ABSENT → the path-scoped rule did not load. Probe files removed after.
- **Status**: upstream, open. Workaround: don't rely on user-level path-scoping → keep global guidance unconditional + COMPRESSED ([[BDR-031]]). Side-note: native auto-memory = "on" but writes nothing yet (fresh machine). Re-test on CC upgrades.
- **Reference**: GitHub #21858. Linked to [[BDR-031]], [[LRN-044]].

View File

@ -498,3 +498,15 @@ rules:
- **Caveats**: the symlink form (`skills/<name> -> skills-external/gstack/<name>`) differs from what gstack `./setup` would create (real dir + symlinked SKILL.md) — fine here because `./setup` never populates `skills/` in this layout, so no mixed-form collision. Browse RUNTIME still needs the built binary + sandbox env ([[BDR-029]]) — on-demand makes the skill DISCOVERABLE, not the browser functional on an unsupported OS. The old "try: bash link.sh" message was wrong (link.sh never creates gstack skills) → replaced with submodule-aware messages. - **Caveats**: the symlink form (`skills/<name> -> skills-external/gstack/<name>`) differs from what gstack `./setup` would create (real dir + symlinked SKILL.md) — fine here because `./setup` never populates `skills/` in this layout, so no mixed-form collision. Browse RUNTIME still needs the built binary + sandbox env ([[BDR-029]]) — on-demand makes the skill DISCOVERABLE, not the browser functional on an unsupported OS. The old "try: bash link.sh" message was wrong (link.sh never creates gstack skills) → replaced with submodule-aware messages.
- **Alternatives rejected**: full gstack integration (make `./setup` install into `skills/`) — user picked option 1, too invasive/version-fragile; leave `full` broken with honest 1-line warning — worse UX; pre-symlink all gstack at install — violates OFF-by-default context policy. - **Alternatives rejected**: full gstack integration (make `./setup` install into `skills/`) — user picked option 1, too invasive/version-fragile; leave `full` broken with honest 1-line warning — worse UX; pre-symlink all gstack at install — violates OFF-by-default context policy.
- **Reference**: `lib/profile.sh` `GSTACK_SRC` + `enable_skill` gstack branch. Verified: `set full` → 0 missing, 35 on-demand; `minimal`↔`full` cycle re-parks/restores; git clean (gstack symlinks gitignored, [[LRN-025]]). Linked to [[LRN-042]], [[LRN-022]], [[BDR-018]] (gstack on/off verb). - **Reference**: `lib/profile.sh` `GSTACK_SRC` + `enable_skill` gstack branch. Verified: `set full` → 0 missing, 35 on-demand; `minimal`↔`full` cycle re-parks/restores; git clean (gstack symlinks gitignored, [[LRN-025]]). Linked to [[LRN-042]], [[LRN-022]], [[BDR-018]] (gstack on/off verb).
---
## BDR-031 — global CLAUDE.md lightening = COMPRESSION, not path-scope / externalization
- **Date**: 2026-06-25
- **Status**: accepted
- **Decision**: lighten the universal global CLAUDE.md (`~/.claude/CLAUDE.md`, loaded every session in every project) by COMPRESSION only — denser prose, drop name-obvious routing lines, trim decorative whitespace. NOT by path-scoping rules under `~/.claude/rules/`, NOT by externalizing sections to on-demand files. Result: 317 → 275 lines.
- **Why**: user-level path-scoped rules (`paths:` frontmatter under `~/.claude/rules/`) do NOT load in CC 2.1.190 (#21858, [[BLK-009]]) — proven by probe. Conditional/scoped loading is therefore an unreliable lever for this user; compression is the only mechanism that actually cuts every-session token cost without depending on the broken feature.
- **Caveats**: future GLOBAL memory must stay tiny — with conditional loading broken, anything global loads in EVERY project unconditionally; fold that constraint into the global-memory design once a backup exists. Caveman pass to ~250 was explicitly DECLINED: marginal ~25-line gain vs real risk (changes the nature of instructions-to-follow; no evidence caveman is followed better than prose; CLAUDE.md is the most-edited file → caveman = painful to re-read/amend). 275 readable > 250 caveman.
- **Alternatives rejected**: path-scoped `~/.claude/rules/` (broken, [[BLK-009]]); externalize sections to on-demand-loaded files (same conditional-load dependency); caveman to ~250 (readability + instruction-fidelity risk).
- **Reference**: `~/.claude/CLAUDE.md` (symlink → `~/Documents/claude/CLAUDE.md`), commits ba743cf (compress routing+design+graphify) + 990318c (trim separators/blanks). Linked to [[BLK-009]], [[LRN-043]], [[LRN-044]].

View File

@ -190,3 +190,10 @@ rules:
- Removed obsolete `alias claude='claude --effort max'` from install Step 9 — settings.json `effortLevel: xhigh` is the source of truth and the CLI alias would override it (forcing max over xhigh). Step 9 now also strips the alias + old CLAUDE_EFFORT from the profile if present. A dtach `cc` launcher was prototyped then dropped — deferred to a later sprint (per user). Why missed earlier = EVAL-005 (never cross-audited existing Step 9 lines vs settings.json). - Removed obsolete `alias claude='claude --effort max'` from install Step 9 — settings.json `effortLevel: xhigh` is the source of truth and the CLI alias would override it (forcing max over xhigh). Step 9 now also strips the alias + old CLAUDE_EFFORT from the profile if present. A dtach `cc` launcher was prototyped then dropped — deferred to a later sprint (per user). Why missed earlier = EVAL-005 (never cross-audited existing Step 9 lines vs settings.json).
- Made install self-sufficient + gstack on-demand per profile (user: "make install doit TOUT installer"). 3 root causes via install log: (A) install.sh ran link.sh BEFORE install-plugins.sh which never re-linked → npx-skill symlinks never created on fresh run; (B) `npx skills add` + gstack `./setup` resolve target relative to CWD → darwin-skill landed in `$REPO/.agents/skills`+`$REPO/.claude/skills`, not `$HOME/.agents/skills` (self-reinforcing once `$REPO/.agents` exists); (C) `profile.sh set full` → 35 "missing — try bash link.sh" (wrong remedy) because gstack OFF + skills never in `skills/`. Fixes: install-plugins.sh runs npx from `$HOME` + cleans parasites + Step 10 final re-link; update-all.sh same npx fix; profile.sh `enable_skill gstack` symlinks on-demand from submodule (gstack OFF default, ON per profile). Verified live: link.sh → darwin OK; `set full` → 0 missing / 35 on-demand; minimal↔full cycle re-parks/restores; git clean. Residual: `$REPO/.claude/skills/darwin-skill` rm blocked by `.claude/` permission guard → auto-cleaned next `make plugin`. BDR-030, LRN-042. - Made install self-sufficient + gstack on-demand per profile (user: "make install doit TOUT installer"). 3 root causes via install log: (A) install.sh ran link.sh BEFORE install-plugins.sh which never re-linked → npx-skill symlinks never created on fresh run; (B) `npx skills add` + gstack `./setup` resolve target relative to CWD → darwin-skill landed in `$REPO/.agents/skills`+`$REPO/.claude/skills`, not `$HOME/.agents/skills` (self-reinforcing once `$REPO/.agents` exists); (C) `profile.sh set full` → 35 "missing — try bash link.sh" (wrong remedy) because gstack OFF + skills never in `skills/`. Fixes: install-plugins.sh runs npx from `$HOME` + cleans parasites + Step 10 final re-link; update-all.sh same npx fix; profile.sh `enable_skill gstack` symlinks on-demand from submodule (gstack OFF default, ON per profile). Verified live: link.sh → darwin OK; `set full` → 0 missing / 35 on-demand; minimal↔full cycle re-parks/restores; git clean. Residual: `$REPO/.claude/skills/darwin-skill` rm blocked by `.claude/` permission guard → auto-cleaned next `make plugin`. BDR-030, LRN-042.
## 2026-06-25
- Probe #21858: user-level path-scoped rules (`paths:` frontmatter in `~/.claude/rules/`) don't load in CC 2.1.190. 3-file probe → control (no-paths) PRESENT, path-scoped ABSENT. Native auto-memory on but empty (fresh machine). Probe files cleaned. BLK-009.
- Compressed global CLAUDE.md 317→275 (42, loaded every session): routing (cut name-obvious lines, keep non-derivable signal + dense catch-all; restored `validate`/`plan-eng-review`, feat/hotfix pointer), design (+ explicit FILE signal), graphify, then decorative `---` + blank rognage. Caveman→250 declined (readability + instruction-fidelity). Commits ba743cf, 990318c. BDR-031, LRN-043.
- Edit/Write refuse write-through-symlink → resolve real path (`readlink -f`); `~/.claude/CLAUDE.md` → repo. LRN-044.
- Inspected dirty gstack submodule (parent showed `m`): `package.json`+`bun.lock` = the Playwright 1.58.2→1.61 bump (BDR-029/BLK-008), NOT restore noise → left intact, NOT cleaned, NOT committed (submodule ref stays at clean 070722ace; local patch re-applied by installer by design).

View File

@ -570,3 +570,23 @@ rules:
- **Pattern**: a per-user installer that resolves its target relative to CWD (walks up for / creates `.<tool>/` in CWD) silently installs into the project tree when run from a repo that already carries such a dir. Gitignoring the junk hides it but the artifact is unreachable from `$HOME`-based consumers. Fix: run the installer from `$HOME` (`(cd "$HOME" && npx -y skills add …)`) so it targets `$HOME/.agents/skills`; clean up the repo-local copies (gitignored → safe `rm -rf`). Also fix the ordering twin: `link.sh` must re-run AFTER the install steps that produce what it symlinks (install.sh ran link FIRST; install-plugins never re-linked) — added a final `link.sh` step so `make plugin`/`make install` finish self-sufficient. - **Pattern**: a per-user installer that resolves its target relative to CWD (walks up for / creates `.<tool>/` in CWD) silently installs into the project tree when run from a repo that already carries such a dir. Gitignoring the junk hides it but the artifact is unreachable from `$HOME`-based consumers. Fix: run the installer from `$HOME` (`(cd "$HOME" && npx -y skills add …)`) so it targets `$HOME/.agents/skills`; clean up the repo-local copies (gitignored → safe `rm -rf`). Also fix the ordering twin: `link.sh` must re-run AFTER the install steps that produce what it symlinks (install.sh ran link FIRST; install-plugins never re-linked) — added a final `link.sh` step so `make plugin`/`make install` finish self-sufficient.
- **Future application**: before running any `npx <x> add` / `<tool> init` / `setup` that materializes a dotfile dir, set CWD to where the artifact MUST live (usually `$HOME`), don't trust the script's default resolution. When a "X not installed" warning contradicts a "successfully installed" log line → diff the EXPECTED path vs where the log says it wrote (here log line showed `~/Documents/claude/.agents/skills/darwin-skill`). When an installer A produces inputs for symlinker B, B must run after A in the same invocation. - **Future application**: before running any `npx <x> add` / `<tool> init` / `setup` that materializes a dotfile dir, set CWD to where the artifact MUST live (usually `$HOME`), don't trust the script's default resolution. When a "X not installed" warning contradicts a "successfully installed" log line → diff the EXPECTED path vs where the log says it wrote (here log line showed `~/Documents/claude/.agents/skills/darwin-skill`). When an installer A produces inputs for symlinker B, B must run after A in the same invocation.
- **Reference**: `install-plugins.sh` Step 8.5 (`cd "$HOME"` + parasite cleanup) + Step 10 (final `link.sh`), `update-all.sh` Step 7.5, log `install-20260623-181416.log:1399`. Extends [[LRN-039]] (BDR-028 — gitignored the symptom) + [[LRN-007]] (toggle-external source-only state) + [[LRN-041]] (install-ordering false-negative). gstack on-demand consumer = [[BDR-030]]. - **Reference**: `install-plugins.sh` Step 8.5 (`cd "$HOME"` + parasite cleanup) + Step 10 (final `link.sh`), `update-all.sh` Step 7.5, log `install-20260623-181416.log:1399`. Extends [[LRN-039]] (BDR-028 — gitignored the symptom) + [[LRN-007]] (toggle-external source-only state) + [[LRN-041]] (install-ordering false-negative). gstack on-demand consumer = [[BDR-030]].
---
## LRN-043 — CLAUDE.md skill-routing: cut name-obvious lines (already in skill descriptions), keep only non-derivable signal + dense catch-all
- **Date**: 2026-06-25
- **Context**: compressing the Skill-routing block of the global CLAUDE.md. Claude already sees every skill's `description` in session context (the available-skills list). A routing line that merely restates "task X → skill named X" duplicates that description → pure token waste loaded every session.
- **Pattern**: in a routing list, KEEP only lines carrying signal NOT derivable from the skill name — (a) conditional fallbacks (gstack ON/OFF), (b) misleading/cryptic names where name ≠ function (`validate` → W3C/WCAG, not form/data/build validation; `cso` → security audit; `plan-eng-review` → architecture review), (c) disambiguation between near-twins (feat/hotfix/bugfix by file-count). CUT the name-obvious rest, replace with ONE dense catch-all ("most skills route by name — match the request to the skill whose description fits"). GUARD: a misleading name is NOT transparent → it needs its own explicit line or it mis-routes; never cut those to save a line (user restored `validate` + `plan-eng-review` for exactly this).
- **Future application**: compressing any routing/dispatch table whose entries the model already sees elsewhere → delete the redundant majority, keep the non-obvious minority + a generic fallback. Test each candidate cut: "is this mapping derivable from the skill name + its own description?" Yes → cut. No → keep explicit.
- **Reference**: `~/.claude/CLAUDE.md` §Skill routing, commit ba743cf (routing block 40 → 23 lines). Linked to [[BDR-031]].
---
## LRN-044 — Edit/Write tools refuse to write THROUGH a symlink — pass the resolved real path
- **Date**: 2026-06-25
- **Context**: editing `~/.claude/CLAUDE.md`, a symlink → `~/Documents/claude/CLAUDE.md` (the tracked repo file). Read worked through the symlink; Edit errored: "Refusing to write through symlink … Resolve the symlink and pass the real target path explicitly."
- **Pattern**: many of this user's `~/.claude/*` config files are symlinks INTO the claude-config repo (`~/Documents/claude/`). Edit/Write block writes through a symlink (safety against clobbering link targets); Read does not — so Read-through-link succeeds then Edit-through-link fails on the same path.
- **Future application**: before editing any `~/.claude/...` config file, resolve it first (`readlink -f <path>`, or `ls -la` to spot the arrow). Then Read AND Edit the RESOLVED real path so the harness's read-tracking matches what you write — and `git` status/diff/commit land naturally in the repo that owns the file.
- **Reference**: hit while editing `~/.claude/CLAUDE.md``~/Documents/claude/CLAUDE.md`. Linked to [[BDR-031]].

114
CLAUDE.md
View File

@ -126,8 +126,6 @@ Completion skills (`/ship-feature`, `/feat`, `/bugfix`, `/hotfix`,
2. What learned? → `learnings.md` (if reusable). 2. What learned? → `learnings.md` (if reusable).
3. What blocked? → `blockers.md`. 3. What blocked? → `blockers.md`.
---
# Architecture decisions # Architecture decisions
Override default framework/tooling choices. Apply at project creation, Override default framework/tooling choices. Apply at project creation,
@ -137,7 +135,6 @@ scaffolding, brainstorming.
When project is public-facing website meant to be indexed (landing page, When project is public-facing website meant to be indexed (landing page,
portfolio, blog, e-commerce, docs): portfolio, blog, e-commerce, docs):
- **FORBIDDEN**: pure SPA (CRA, Vite React SPA, Vue SPA) for public pages. - **FORBIDDEN**: pure SPA (CRA, Vite React SPA, Vue SPA) for public pages.
SPA sends empty HTML shell — search engines and AI engines (GEO) can't SPA sends empty HTML shell — search engines and AI engines (GEO) can't
see content without executing JS. SEO and AI visibility destroyed. see content without executing JS. SEO and AI visibility destroyed.
@ -157,7 +154,6 @@ portfolio, blog, e-commerce, docs):
## Web APIs — always versioned ## Web APIs — always versioned
All web API endpoints must be versioned from day one: `/api/v1/...`. All web API endpoints must be versioned from day one: `/api/v1/...`.
- New project → start at `/api/v1/`, no bare `/api/` routes. - New project → start at `/api/v1/`, no bare `/api/` routes.
- Breaking changes → new version (`v2`). Old version stays functional — - Breaking changes → new version (`v2`). Old version stays functional —
clients migrate at own pace. clients migrate at own pace.
@ -207,8 +203,6 @@ Apply at every dev step: design, scaffolding, implementation, review.
- Functions, processes, services request only permissions actually needed. - Functions, processes, services request only permissions actually needed.
- Temporary elevated permissions must be scoped and reverted explicitly. - Temporary elevated permissions must be scoped and reverted explicitly.
---
# Communication mode: radical honesty # Communication mode: radical honesty
- TRUTH OVER COMFORT — Point out flaws immediately. No sugarcoating, - TRUTH OVER COMFORT — Point out flaws immediately. No sugarcoating,
@ -223,91 +217,55 @@ Apply at every dev step: design, scaffolding, implementation, review.
- UNCERTAINTY TRANSPARENCY — If you don't know, say so. No invention, - UNCERTAINTY TRANSPARENCY — If you don't know, say so. No invention,
no vague answers to save face. no vague answers to save face.
---
# Tooling & skills # Tooling & skills
## Skill routing ## Skill routing
Request matches available skill → invoke via Skill tool first — no direct Request matches a skill → invoke via Skill tool first, before any direct
answer, no other tools before. Skill workflows beat ad-hoc answers. answer or other tool. Most skills route by name — match the request to the
skill whose description fits (full list is in context). Rules below cover
only the non-obvious cases: gstack fallbacks, disambiguation, cryptic names.
Key routing rules: - Product idea, "worth building?" → office-hours
- Product ideas, "worth building?", brainstorming → office-hours - Bug / error / 500 → investigate (bugfix if gstack off)
- Bugs, errors, "why broken", 500s → investigate, or bugfix if no gstack - feat / hotfix / bugfix distinguished by file count → see descriptions
- Small feature (1-5 files) → feat - Ship / deploy / PR → ship (ship-feature if gstack off)
- Quick fix (typo, CSS, config, ≤2 files) → hotfix - Docs post-ship → document-release (doc if gstack off); stale-doc audit → doc
- Ship, deploy, push, PR → ship, or ship-feature if no gstack - Audit of changes since last run → audit-delta
- QA, test site, find bugs → qa - Design / UI (build, system, audit, polish) → see "Design work" below
- Code review, check diff → review
- Docs update post-ship → document-release, or doc if no gstack
- Stale docs audit, doc sync → doc
- Recurring audit of changes since last run → audit-delta
- Weekly retro → retro
- Design / UI — build, design system, brand, visual audit, polish → see
"## Design work — full toolchain" (single source, below)
- Architecture review → plan-eng-review - Architecture review → plan-eng-review
- Save/restore working context → context-save / context-restore - Before /clear or /compact → capitalize; end-of-session ritual → close
- End-of-session ritual (3-question reflection) → close (= capitalize --ritual) - SEO+GEO → seo (GEO only → geo)
- Flush memory before /clear or /compact, reconcile TODO → capitalize
- Registries too big/noisy → prune-memory
- Skill profiles (design/dev/qa/minimal) → profile
- Code quality dashboard → health
- Refactor without behavior change → refactor
- Dead code, style cleanup → code-clean
- SEO/GEO audit → seo (GEO only → geo)
- Web hardening (SSL/TLS, HSTS, CSP, redirects, headers) → harden
- W3C + WCAG a11y (HTML/CSS validity, axe, pa11y) → validate - W3C + WCAG a11y (HTML/CSS validity, axe, pa11y) → validate
- Deep analysis before modification → analyze - Security audit (secrets, CVE, OWASP) → cso
- Smart commit grouping → commit-change - New project → init-project; onboard existing repo → onboard
- Security audit (secrets, deps CVE, OWASP) → cso
- New project from scratch → init-project
- Onboard existing repo (config + archetype + audits + backlog) → onboard
gstack OFF → gstack skills (investigate, ship, qa, review, health, retro, gstack OFF → its skills (investigate, ship, qa, review, health, retro,
office-hours, context-save…) unavailable: use the non-gstack fallback office-hours, context-save…) are gone: use the fallback above, else say so.
where listed, else say so instead of improvising.
## Design work — full toolchain (tiered by scope) ## Design work — full toolchain (tiered by scope)
Single source for all design/UI routing. Task touches design/UI → Trigger = UI work: editing a component/style file (.tsx/.vue/.svelte/.css…)
mobilize tools by scope. Reinforced by design-toolchain-reminder hook OR a design/UI request — not the keyword "design" alone in a prompt. Single
(injects on UI signals). source for design routing; the design-toolchain hook reinforces it.
- Trivial (≤2 files, single cosmetic value) → /hotfix, no toolchain. - Trivial (≤2 files, one cosmetic value) → /hotfix, no toolchain.
- Build UI (new component, page, screen, redesign) → ui-ux-pro-max - Build UI (component, page, redesign) → ui-ux-pro-max + frontend-design
(plan/build) + frontend-design (anti AI-slop) + Magic MCP `/ui` (anti-slop) + Magic MCP /ui + emil-design-eng (polish) +
(21st.dev scaffold) + emil-design-eng (polish pass) design-motion-principles (if motion) + design-html (if static).
+ design-motion-principles (when motion) + design-html (static HTML). - Design system / brand → design-consultation first, then the build tools.
- Design system / brand → design-consultation first (aesthetic, type, - Review / audit → design-review + emil-design-eng + design-motion-principles.
color, spacing, motion), THEN build tools above. Scope doubt → don't silently skip: ask, or default to Build tier.
- Review / audit → design-review (visual QA + fix) + emil-design-eng lens Gate: lightweight skills run `~/.claude/lib/design-gate.md`; orchestrators via
+ design-motion-principles (audit mode). plugin-check. Magic MCP costs API calls — generation, not micro-tweaks.
Scope doubt (trivial tweak vs real UI change?) → do not silently skip
toolchain: ask user, or default to Build tier.
Design gate (automatic): on UI/style signals, lightweight skills (feat,
hotfix, bugfix) run the gate spec `~/.claude/lib/design-gate.md` — it checks
the design toolchain's real state and, if incomplete, points at `/profile design`.
Orchestrators (ship-feature, init-project) handle via STEP 0 plugin-check.
Magic MCP (@21st-dev/magic) costs API calls — component generation only,
not micro-tweaks.
## graphify ## graphify
Knowledge-graph navigation via graphify CLI. ALL rules conditional: ALL rules apply only if `graphify-out/graph.json` exists — else read files
`graphify-out/graph.json` exists in the project — else skip graphify directly.
entirely, read files directly. - Codebase-wide question → `graphify query`; relationships → `path A B`;
concept → `explain`. Scoped subgraph beats raw grep.
- Codebase-wide question → `graphify query "<question>"` first. - Known file / small task → read directly, no graphify.
Relationships → `graphify path "<A>" "<B>"`. Focused concept → - `wiki/index.md` → broad-nav entry; `GRAPH_REPORT.md` → whole-architecture.
`graphify explain "<concept>"`. Scoped subgraph beats raw grep. - After editing code → `graphify update .` (AST-only, free).
- Known file/symbol lookup, small task (hotfix, typo, single file) →
read directly, no graphify.
- `graphify-out/wiki/index.md` exists → broad-navigation entrypoint.
`GRAPH_REPORT.md` only for whole-architecture review or when
query/path/explain insufficient.
- After modifying code → `graphify update .` (AST-only, no API cost).
---
# This repo only (claude-config) # This repo only (claude-config)