Four require() examples in commands/gsd/surface.md used bare 'gsd-core/...' specifiers that Node cannot resolve (wrong package name + runtime-mirror layout off module path). Now derives the path from runtimeConfigDir. Also fixes reinstall hint from 'npm i -g gsd-core' to 'npm i -g @opengsd/gsd-core'.
163 lines
5.5 KiB
Markdown
163 lines
5.5 KiB
Markdown
---
|
|
name: gsd:surface
|
|
description: Toggle which skills are surfaced — apply a profile, list, or disable a cluster without reinstall
|
|
argument-hint: "[list|status|profile <name>|disable <cluster>|enable <cluster>|reset]"
|
|
allowed-tools:
|
|
- Read
|
|
- Write
|
|
- Bash
|
|
requires: [config, update]
|
|
---
|
|
|
|
<objective>
|
|
Manage the runtime skill surface without reinstall. Reads/writes `~/.claude/.gsd-surface.json`
|
|
(sibling to `~/.claude/.gsd-profile`) and re-stages the active skills directory in place.
|
|
Skill dirs live at `~/.claude/skills/gsd-*/`.
|
|
|
|
Sub-commands: list · status · profile · disable · enable · reset
|
|
</objective>
|
|
|
|
## Sub-command routing
|
|
|
|
Parse the first token of $ARGUMENTS:
|
|
|
|
| Token | Action |
|
|
|---|---|
|
|
| `list` | Show enabled + disabled clusters and skills |
|
|
| `status` | Alias for `list` plus token cost summary |
|
|
| `profile <name>` | Write `baseProfile` and re-stage |
|
|
| `profile <n1>,<n2>` | Composed profiles (comma-separated, no spaces) |
|
|
| `disable <cluster>` | Add cluster to `disabledClusters`, re-stage |
|
|
| `enable <cluster>` | Remove cluster from `disabledClusters`, re-stage |
|
|
| `reset` | Delete `.gsd-surface.json`, return to install-time profile |
|
|
| *(none)* | Treat as `list` |
|
|
|
|
---
|
|
|
|
## list / status
|
|
|
|
Load the capability registry and call `listSurface(runtimeConfigDir, manifest, CLUSTERS, registry)` from
|
|
the engine module at `${runtimeConfigDir}/gsd-core/bin/lib/surface.cjs`. The registry is loaded via:
|
|
```js
|
|
const registry = require(runtimeConfigDir + '/gsd-core/bin/lib/capability-registry.cjs');
|
|
```
|
|
Display:
|
|
|
|
```
|
|
Enabled (N skills, ~T tokens):
|
|
core_loop: new-project discuss-phase plan-phase execute-phase help update
|
|
audit_review: …
|
|
…
|
|
|
|
Disabled:
|
|
utility: health stats settings …
|
|
|
|
Token cost: ~T (budget cap ~500 tokens for 200k context @ 1%)
|
|
```
|
|
|
|
For `status` also append:
|
|
|
|
```
|
|
Base profile: standard (from .gsd-surface.json)
|
|
Install profile: standard (from .gsd-profile)
|
|
```
|
|
|
|
---
|
|
|
|
## profile \<name\>
|
|
|
|
1. Read current surface: `readSurface(runtimeConfigDir)` → if null, seed from `readActiveProfile(runtimeConfigDir)`.
|
|
2. Set `surfaceState.baseProfile = name`.
|
|
3. `writeSurface(runtimeConfigDir, surfaceState)`.
|
|
4. Resolve and re-apply:
|
|
```js
|
|
const registry = require(runtimeConfigDir + '/gsd-core/bin/lib/capability-registry.cjs');
|
|
const layout = resolveRuntimeArtifactLayout(runtime, runtimeConfigDir, scope);
|
|
applySurface(runtimeConfigDir, layout, manifest, CLUSTERS, registry);
|
|
```
|
|
5. Confirm: "Surface updated to profile `<name>`. N skills enabled."
|
|
|
|
---
|
|
|
|
## disable \<cluster\>
|
|
|
|
Valid cluster names: `core_loop`, `audit_review`, `milestone`, `research_ideate`,
|
|
`workspace_state`, `docs`, `ui`, `ai_eval`, `ns_meta`, `utility`.
|
|
|
|
1. Validate cluster name against `Object.keys(CLUSTERS)`.
|
|
2. Read or initialize surface state.
|
|
3. Add cluster to `surfaceState.disabledClusters` (deduplicate).
|
|
4. `writeSurface` → resolve layout → `applySurface`:
|
|
```js
|
|
const registry = require(runtimeConfigDir + '/gsd-core/bin/lib/capability-registry.cjs');
|
|
const layout = resolveRuntimeArtifactLayout(runtime, runtimeConfigDir, scope);
|
|
applySurface(runtimeConfigDir, layout, manifest, CLUSTERS, registry);
|
|
```
|
|
5. Confirm: "Disabled cluster `<cluster>`. N skills removed from surface."
|
|
|
|
---
|
|
|
|
## enable \<cluster\>
|
|
|
|
1. Read surface state; if null, nothing to enable — print "No surface delta active."
|
|
2. Remove cluster from `surfaceState.disabledClusters`.
|
|
3. `writeSurface` → resolve layout → `applySurface`:
|
|
```js
|
|
const registry = require(runtimeConfigDir + '/gsd-core/bin/lib/capability-registry.cjs');
|
|
const layout = resolveRuntimeArtifactLayout(runtime, runtimeConfigDir, scope);
|
|
applySurface(runtimeConfigDir, layout, manifest, CLUSTERS, registry);
|
|
```
|
|
4. Confirm: "Enabled cluster `<cluster>`. N skills added back to surface."
|
|
|
|
---
|
|
|
|
## reset
|
|
|
|
1. Check if `.gsd-surface.json` exists.
|
|
2. Delete it.
|
|
3. Re-apply using only `readActiveProfile(runtimeConfigDir)` (install-time profile).
|
|
4. Confirm: "Surface reset to install-time profile `<name>`."
|
|
|
|
---
|
|
|
|
## runtimeConfigDir resolution
|
|
|
|
The `runtimeConfigDir` for `applySurface` is the **base Claude config directory**
|
|
(`~/.claude`), NOT the skills sub-directory (`~/.claude/skills`).
|
|
|
|
This matches `installRuntimeArtifacts` and `uninstallRuntimeArtifacts`, which also
|
|
receive `~/.claude` as `configDir`. The skill dirs themselves live at
|
|
`~/.claude/skills/gsd-*/` because the `claude global` layout has `destSubpath =
|
|
'skills'` — they are derived from `configDir`, not the root for it.
|
|
|
|
```bash
|
|
# Claude Code — global install
|
|
RUNTIME_CONFIG_DIR="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
|
|
SCOPE="global"
|
|
|
|
# Artifact destinations are derived from runtime layout
|
|
# via resolveRuntimeArtifactLayout(runtime, RUNTIME_CONFIG_DIR, SCOPE)
|
|
# then applySurface(RUNTIME_CONFIG_DIR, layout, manifest, CLUSTERS)
|
|
```
|
|
|
|
Surface state is stored at `${RUNTIME_CONFIG_DIR}/.gsd-surface.json`
|
|
(i.e. `~/.claude/.gsd-surface.json`).
|
|
|
|
All paths can be overridden by reading the `CLAUDE_CONFIG_DIR` env var if set.
|
|
|
|
---
|
|
|
|
## Error handling
|
|
|
|
- Unknown cluster name → list valid cluster names, exit without writing.
|
|
- Unknown profile name → list known profiles (`core`, `standard`, `full`), exit.
|
|
- Missing `surface.cjs` → prompt: "Run `npm i -g @opengsd/gsd-core` to reinstall GSD."
|
|
|
|
<execution_context>
|
|
Surface state file: `~/.claude/.gsd-surface.json`
|
|
Install profile marker: `~/.claude/.gsd-profile`
|
|
Skill dirs: `~/.claude/skills/gsd-*/`
|
|
Engine module: `~/.claude/gsd-core/bin/lib/surface.cjs`
|
|
Cluster definitions: `~/.claude/gsd-core/bin/lib/clusters.cjs`
|
|
</execution_context>
|