# GNO Agent Skill System Create a skill distribution system that enables AI agents (Claude Code, Codex) to use GNO perfectly. ## Overview GNO needs to be installable as an Agent Skill so that CLI-based AI agents can: - Initialize and configure GNO indexes - Search documents (BM25, vector, hybrid) - Get AI-powered answers with citations - Set up MCP server integration The system consists of: 1. **SKILL.md** - Core skill file with frontmatter + instructions 2. **Reference files** - CLI reference, MCP reference, examples (progressive disclosure) 3. **`gno skill install`** - CLI command to install skill to target agent ## Scope **In Scope**: - SKILL.md following Claude Code skills spec - `gno skill install` command with `--scope` (project|user) and `--target` (claude|codex|all) - `gno skill uninstall` command with path safety guards - Supporting reference files for progressive disclosure - Injectable path resolver for testability **Out of Scope**: - Cursor/Windsurf/other agent support (future) - Auto-updating claude_desktop_config.json for MCP - Skill versioning/upgrade detection - Interactive merge mode - Section markers / partial merges (full directory overwrite only) ## Approach ### Phase 1: Skill Content Files Skill files shipped in package, copied on install: ```plaintext assets/skill/ ├── SKILL.md # Core instructions + frontmatter (< 500 lines) ├── cli-reference.md # Full CLI command reference ├── mcp-reference.md # MCP tools/resources reference └── examples.md # Real-world usage examples ``` **SKILL.md Structure** (following flow-plan/flow-work pattern): ```yaml --- name: gno description: Local semantic search for documents. Initialize indexes, search with BM25/vector/hybrid, get AI answers with citations. Use when searching files, indexing documents, querying knowledge bases, or setting up MCP. allowed-tools: Bash(gno:*), Read --- # GNO - Local Document Search Fast local semantic search for your documents. **Role**: document search assistant **Goal**: help users index, search, and query their documents ## Quick Start 1. Initialize: `gno init` 2. Index: `gno update` 3. Search: `gno search "your query"` ## Core Commands - `gno init` - Initialize index in current directory - `gno update` - Re-index documents - `gno search ` - Search with BM25 (default) - `gno search --mode vector` - Semantic search - `gno ask ` - AI-powered Q&A with citations ## Reference For complete CLI details, see [cli-reference.md](cli-reference.md). For MCP server setup, see [mcp-reference.md](mcp-reference.md). For usage examples, see [examples.md](examples.md). ``` **Key points from skills docs**: - `name` and `description` required in frontmatter - `allowed-tools` is **experimental** per Agent Skills spec - Claude Code supports it, Codex support unclear - Keep SKILL.md under 500 lines - detailed docs in reference files - Reference files loaded via progressive disclosure when needed - Description is crucial for triggering - include keywords users would say ### Phase 2: Path Resolution Module Centralized path resolver with injection for testability: ```ts // src/cli/commands/skill/paths.ts interface SkillPathOptions { scope: "project" | "user"; target: "claude" | "codex"; cwd?: string; // Override for project scope homeDir?: string; // Override for user scope (tests) } interface SkillPaths { base: string; // e.g., ~/.claude or ./.claude skillsDir: string; // e.g., ~/.claude/skills gnoDir: string; // e.g., ~/.claude/skills/gno } export function resolveSkillPaths(opts: SkillPathOptions): SkillPaths; // Environment overrides for CI/debugging: // - GNO_SKILLS_HOME_OVERRIDE: override home dir for user scope // - CLAUDE_SKILLS_DIR: override Claude skills directory // - CODEX_SKILLS_DIR: override Codex skills directory ``` **Target Paths** (defaults, overridable): | Target | Scope | Default Path | | ----------- | ------- | --------------------------- | | Claude Code | project | `/.claude/skills/gno/` | | Claude Code | user | `~/.claude/skills/gno/` | | Codex | project | `/.codex/skills/gno/` | | Codex | user | `~/.codex/skills/gno/` | ### Phase 3: Install Command New command group: `gno skill` **`gno skill install`**: ```bash gno skill install [--scope ] [--target ] Options: --scope project Install to .claude/skills/ or .codex/skills/ (default) user Install to ~/.claude/skills/ or ~/.codex/skills/ --target claude Claude Code only (default) codex Codex only all Both Claude Code and Codex --force Overwrite existing skill without prompting Global flags honored: --yes Same as --force (suppress prompts) --quiet Suppress non-essential output --json Output result as JSON (uses CliError envelope on failure) ``` **Install Algorithm** (atomic, Windows-safe): 1. Resolve source path via `import.meta.dir` → `assets/skill/` 2. Resolve dest paths via `resolveSkillPaths()` 3. If dest exists and not (`--force` || `--yes`): throw `CliError('VALIDATION', 'Skill already installed. Use --force to overwrite.')` 4. Create temp dir as sibling: `/.gno-skill.tmp.` 5. Copy all files from source to temp dir 6. If dest exists: remove with retry (Windows-safe, like `safeRm()`) 7. Rename temp dir → dest dir 8. On failure: best-effort cleanup temp dir 9. Output success message (or JSON if `--json`) **`gno skill uninstall`**: ```bash gno skill uninstall [--scope ] [--target ] ``` **Uninstall Safety Checks** (critical): 1. Resolve `destDir` via `resolveSkillPaths()` 2. Normalize to absolute path via `realpath` where possible 3. **Reject if**: - `destDir` doesn't end with expected suffix (`/skills/gno` or `\skills\gno`) - `destDir` length < 20 chars (sanity check) - `destDir` equals base dir - `destDir` is not inside expected base (prefix check on normalized paths) 4. Only then: remove directory with retry (Windows-safe) **`gno skill show`**: ```bash gno skill show [--file ] # Preview skill files Options: --file SKILL.md Show specific file (default: SKILL.md) cli-reference.md mcp-reference.md examples.md --all Show all files with separators Output: Without --file: prints SKILL.md content With --file: prints specified file With --all: prints all files with "--- ---" separators Always lists available files at end: "Files: SKILL.md, cli-reference.md, ..." ``` **`gno skill paths`** (debugging helper): ```bash gno skill paths [--scope ] [--target ] [--json] Output: Shows resolved paths for each target without installing ``` ### Phase 4: Implementation **File Structure**: ```plaintext assets/skill/ # Skill files shipped with package ├── SKILL.md ├── cli-reference.md ├── mcp-reference.md └── examples.md src/cli/commands/skill/ ├── paths.ts # Path resolution with injection ├── install.ts # Install command ├── uninstall.ts # Uninstall command (with safety guards) ├── show.ts # Show/preview command ├── paths-cmd.ts # Paths debugging command └── index.ts # Subcommand wiring ``` **Ensure files ship with package** (package.json): ```jsonc { "files": ["dist", "assets"], } ``` **Locate source files at runtime**: ```ts import { dirname, join } from "node:path"; import { fileURLToPath } from "node:url"; // Works in both dev and after Bun build const __dirname = dirname(fileURLToPath(import.meta.url)); const SKILL_SOURCE_DIR = join(__dirname, "../../assets/skill"); ``` **Error Handling** (follow existing patterns): - Validation errors (bad args, existing install): `throw new CliError('VALIDATION', message)` - IO failures: `throw new CliError('RUNTIME', message)` - Let `run.ts` handle exit codes and `--json` error envelopes - Output to stdout; diagnostics to stderr via `src/cli/ui.ts` patterns **Wire into program.ts**: ```ts // In wireManagementCommands() or similar const skillCmd = program.command("skill").description("Manage GNO agent skill"); skillCmd .command("install") .option("--scope ", "project or user", "project") .option("--target ", "claude, codex, or all", "claude") .option("--force", "Overwrite existing skill") .action(async (opts) => { const { installSkill } = await import("./skill/install.js"); await installSkill(opts); }); // Similar for uninstall, show, paths ``` ## Key Decisions 1. **Skill directory structure**: Flat files (`gno/SKILL.md` + refs) matching flow-plan/flow-work pattern 2. **Merge strategy**: Overwrite entire skill directory (atomic via temp+rename), no partial merges 3. **Content source**: Files shipped in `assets/skill/`, located via `import.meta.url` 4. **Progressive disclosure**: SKILL.md < 500 lines, reference files for details 5. **MCP config**: Instructions only, no auto-edit of claude_desktop_config.json 6. **Path resolution**: Centralized module with injection + env overrides for testability 7. **Safety**: Strict path validation before any rm operations ## Acceptance Criteria - [ ] `gno skill install` creates skill directory with SKILL.md + reference files - [ ] `gno skill install --scope user --target all` installs to both ~/.claude and ~/.codex - [ ] `gno skill uninstall` removes skill directory cleanly with safety guards - [ ] `gno skill show` outputs SKILL.md; `--file` and `--all` work - [ ] `gno skill paths` shows resolved paths for debugging - [ ] Skill triggers correctly when user asks about searching/indexing documents - [ ] Reference files load via progressive disclosure when agent needs details - [ ] Works on macOS, Linux, Windows (path handling) - [ ] Honors global flags: `--yes` (like --force), `--quiet`, `--json` - [ ] Throws `CliError` for proper exit codes and JSON envelopes - [ ] Spec updated at spec/cli.md before implementation - [ ] Tests cover install/uninstall/show commands with path injection - [ ] `assets/skill/` included in package.json files ## Test Plan 1. **Unit tests** (all use injected paths, never touch real HOME): - `resolveSkillPaths()` returns correct paths for all scope/target combos - `resolveSkillPaths()` respects env overrides - Install copies all files from source - Uninstall safety: rejects paths that don't match expected pattern - Show outputs correct file content 2. **Integration tests** (use temp dirs via `homeDirOverride`): - Install to project scope → verify `/.claude/skills/gno/SKILL.md` exists - Install to user scope → verify `/.claude/skills/gno/SKILL.md` exists - Install twice without --force → error - Install with --force → overwrites - Uninstall removes directory - Atomic install: partial failure leaves no partial state 3. **Manual verification**: - Load skill in Claude Code, test trigger phrases - Verify skill triggers on "how do I search documents" etc. - Verify reference files load when Claude needs CLI details ## Risks | Risk | Mitigation | | ---------------------------------- | -------------------------------------------------------- | | Claude Code/Codex paths change | Centralized resolver + env overrides, easy to update | | Skill doesn't trigger | Strong description with keywords; test manually | | Reference files bloat context | Keep focused; SKILL.md < 500 lines | | Windows path/locking issues | Use atomic temp+rename pattern; retry on EBUSY | | Source files missing after install | Verify `assets/` in package.json files; integration test | | Unsafe uninstall | Strict path validation before any rm | ## Dependencies - None external - Uses existing: `Bun.write()`, `node:fs/promises` mkdir/rm, `node:path` utilities - Reuse patterns from: `safeRm()`, `saveConfigToPath()` atomic writes ## References - CLI command pattern: `src/cli/commands/init.ts` - Config paths: `src/app/constants.ts` - File operations: `src/config/saver.ts` - Existing skill structure: `~/.claude/skills/convex/`, flow-plan, flow-work - Error handling: `src/cli/errors.ts` (CliError) - Spec location: `spec/cli.md` (must update first) - Claude Code skills: ## Tasks 1. **Update spec/cli.md** - Add `gno skill` command group (install/uninstall/show/paths) 2. **Create assets/skill/SKILL.md** - Core skill (< 500 lines, strong description) 3. **Create assets/skill/cli-reference.md** - Full CLI reference 4. **Create assets/skill/mcp-reference.md** - MCP setup reference 5. **Create assets/skill/examples.md** - Usage examples 6. **Update package.json** - Add `assets` to files array 7. **Implement src/cli/commands/skill/paths.ts** - Path resolver with injection + env overrides 8. **Implement src/cli/commands/skill/install.ts** - Atomic install with Windows-safe temp+rename 9. **Implement src/cli/commands/skill/uninstall.ts** - Safe uninstall with path validation 10. **Implement src/cli/commands/skill/show.ts** - Show with --file and --all options 11. **Implement src/cli/commands/skill/paths-cmd.ts** - Debug command for path resolution 12. **Wire commands in program.ts** - Add skill subcommand group following existing patterns 13. **Write tests** - Unit + integration with path injection 14. **Manual test** - Verify skill triggers in Claude Code