docs(skills): add skills infrastructure plan

- Three-phase plan for skills system improvements
- Phase 1: Command Dispatch (flynn skills CLI commands)
- Phase 2: Skills Watcher (auto-reload with chokidar)
- Phase 3: Installer Specs (auto-install brew/node/go/download)
- Model strategy: glm-4.7-flash for mechanical, glm-4.7 for complex
- Estimated 8-11 hours total
This commit is contained in:
William Valentin
2026-02-11 14:48:21 -08:00
parent 6090508bad
commit fae3565480
2 changed files with 755 additions and 19 deletions
@@ -0,0 +1,710 @@
# Skills Infrastructure Improvement Plan
**Created:** 2026-02-11
**Branch:** feature/skills-infrastructure
**Goal:** Improve Flynn's skills system to match OpenClaw's maintenance capabilities
**Model Strategy:** Use `glm-4.7-flash` for mechanical tasks, `glm-4.7` for complex tasks/orchestration
---
## Executive Summary
This plan implements three critical infrastructure improvements to Flynn's skills system:
1. **Command Dispatch Mode** - Expose `flynn skills` CLI commands for skill management
2. **Skills Watcher** - Auto-reload skills when files change
3. **Installer Specs** - Auto-install dependencies (brew/node/go) when installing skills
**Approach:** Infrastructure first, then integrate high-value skills from ClawHub in future phases.
---
## Prioritization Rationale
Based on user decisions:
- **Feature set:** All three P0-P1 features (command dispatch, watcher, installer specs)
- **Approach:** Infrastructure first - build solid foundation before adding skills
- **Skill format:** Keep `manifest.json` (more explicit than YAML frontmatter)
- **Agent isolation:** Defer - focus on single-agent optimization
- **Skill registry:** Keep private - no public FlyHub
---
## Phase 1: Command Dispatch Mode (P0)
**Impact:** High (users can manage skills without manual file operations)
**Complexity:** Low (exposes existing SkillInstaller/SkillRegistry)
**Estimated effort:** 2-3 hours
### 1.1 Create CLI Skills Module
**File:** `src/cli/skills.ts`
**Structure:**
```typescript
import { Command } from 'commander';
import { SkillRegistry } from '../skills/registry.js';
import { SkillInstaller } from '../skills/installer.js';
import { loadAllSkills } from '../skills/loader.js';
export const skillsCommand = new Command('skills')
.description('Manage Flynn skills')
.action(async () => {
await skillsCommand.outputHelp();
});
// Subcommands will be registered here
```
**Subcommands to implement:**
#### `flynn skills list`
- List all registered skills
- Show tier (bundled/managed/workspace)
- Show availability status (available/unavailable with reasons)
- Output format: table (default) or JSON (with `--json` flag)
#### `flynn skills info <name>`
- Show detailed information about a specific skill
- Display: name, description, version, author, tier, requirements, tools
- Show availability status and reasons if unavailable
- Show directory path
#### `flynn skills install <path>`
- Install a skill from a local directory or remote URL
- Validate skill structure (manifest.json + SKILL.md)
- Run requirement checks
- Install to `skills.managed_dir` (default: `~/.flynn/workspace/skills`)
- Register with SkillRegistry
- Support `--force` flag to overwrite existing
#### `flynn skills uninstall <name>`
- Remove skill from managed directory
- Unregister from SkillRegistry
- Confirm before deletion unless `--yes` flag
- Check if skill is bundled (deny uninstallation of bundled skills)
#### `flynn skills refresh`
- Reload all skills from disk
- Update SkillRegistry
- Show count of skills loaded/removed
### 1.2 Register Skills Command
**File:** `src/cli/index.ts`
Add skills command to CLI:
```typescript
import { skillsCommand } from './skills.js';
program.addCommand(skillsCommand);
```
### 1.3 Update Doctor Checks
**File:** `src/cli/doctor.ts`
Enhance skills check (line 192-198):
- Show per-skill availability details
- Report missing binaries with `which` output
- Report missing environment variables
- Suggest installation commands
### 1.4 Tests
**File:** `src/cli/skills.test.ts`
Test coverage for all subcommands:
- `skills list` - output format, filtering
- `skills info` - single skill, non-existent skill
- `skills install` - local path, remote URL, duplicate, force
- `skills uninstall` - normal, bundled skill denial, non-existent
- `skills refresh` - registry update
---
## Phase 2: Skills Watcher (P1)
**Impact:** Medium (hot-reload skills without daemon restart)
**Complexity:** Medium (integrate file watcher into daemon lifecycle)
**Estimated effort:** 3-4 hours
### 2.1 Install Dependencies
Add to `package.json`:
```json
{
"dependencies": {
"chokidar": "^3.5.3"
}
}
```
### 2.2 Create Skills Watcher Module
**File:** `src/skills/watcher.ts`
**Interface:**
```typescript
import { SkillRegistry } from './registry.js';
import type { Skill } from './types.js';
export interface SkillsWatcherConfig {
registry: SkillRegistry;
skillDirs: string[]; // bundled, managed, workspace
debounceMs?: number; // default: 250
onSkillChange?: (skill: Skill, action: 'add' | 'update' | 'remove') => void;
}
export class SkillsWatcher {
constructor(config: SkillsWatcherConfig);
start(): void;
stop(): void;
reloadSkill(path: string): void;
reloadAll(): void;
}
```
**Implementation:**
- Use chokidar to watch all three skill directories
- Debounce file changes (configurable, default 250ms)
- Watch for: `SKILL.md`, `manifest.json`, directory add/remove
- On change: call `loadSkill()` and register/unregister with SkillRegistry
- Emit events via callback for logging/debugging
### 2.3 Integrate Watcher into Daemon
**File:** `src/daemon/services.ts`
Modify `initSkills()`:
```typescript
import { SkillsWatcher } from '../skills/watcher.js';
async function initSkills(config: Config): Promise<void> {
// Existing skill loading code
const skills = loadAllSkills({
bundledDir: config.skills.bundled_dir,
managedDir: config.skills.managed_dir,
workspaceDir: config.skills.workspace_dir,
});
skills.forEach(skill => skillRegistry.register(skill));
// NEW: Start watcher if enabled
if (config.skills.load?.watch) {
const watcher = new SkillsWatcher({
registry: skillRegistry,
skillDirs: [
config.skills.bundled_dir,
config.skills.managed_dir,
config.skills.workspace_dir,
].filter(Boolean) as string[],
debounceMs: config.skills.load.watch_debounce_ms || 250,
onSkillChange: (skill, action) => {
console.log(`Skill ${skill.manifest.name} ${action}d`);
},
});
watcher.start();
// Store watcher reference for cleanup
(global as any).skillsWatcher = watcher;
}
}
```
Add cleanup in shutdown handler:
```typescript
process.on('SIGTERM', () => {
const watcher = (global as any).skillsWatcher;
if (watcher) {
watcher.stop();
}
// ... existing cleanup
});
```
### 2.4 Add Configuration Schema
**File:** `src/config/schema.ts`
Add to SkillsLoadConfig:
```typescript
skills_load_config: z.object({
watch: z.boolean().default(false),
watch_debounce_ms: z.number().default(250),
})
```
### 2.5 Tests
**File:** `src/skills/watcher.test.ts`
Test coverage:
- Watcher initialization
- File change detection (add skill)
- File change detection (update skill)
- File change detection (remove skill)
- Debounce behavior
- Multiple skill directories
- Stop/start lifecycle
---
## Phase 3: Installer Specs (P1)
**Impact:** Medium (automatic dependency installation)
**Complexity:** Medium (detect package managers, run install commands)
**Estimated effort:** 3-4 hours
### 3.1 Update SkillManifest Type
**File:** `src/skills/types.ts`
Add installer specs to manifest:
```typescript
export interface SkillManifest {
// ... existing fields
/** Installation specifications for automatic dependency installation */
installers?: SkillInstaller[];
}
export type SkillInstallerKind = 'brew' | 'node' | 'go' | 'download' | 'manual';
export interface SkillInstaller {
/** Installer type */
kind: SkillInstallerKind;
/** Display label shown to user */
label: string;
/** For brew: formula name. For node: package name. For go: import path. */
package?: string;
/** For download: URL to download */
url?: string;
/** For download: archive format (tar.gz, zip, etc.) */
archive?: string;
/** For download: extract directory */
extract?: boolean;
/** Binaries to verify after installation */
bins?: string[];
/** OS platforms this installer supports */
os?: string[];
}
```
### 3.2 Create Package Manager Detector
**File:** `src/skills/package-manager.ts`
**Interface:**
```typescript
export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun';
export interface PackageManagerInfo {
name: PackageManager;
command: string;
available: boolean;
}
export function detectPackageManager(): PackageManagerInfo | null;
export function runPackageInstall(pkgManager: PackageManager, packages: string[]): Promise<void>;
```
**Implementation:**
- Detect available package managers (check `npm --version`, `pnpm --version`, etc.)
- Prefer `pnpm` over `npm`, `yarn`, `bun` (matching Flynn's runtime preference)
- Run install with correct command for detected manager
- Capture output and errors
### 3.3 Extend SkillInstaller
**File:** `src/skills/installer.ts`
Add auto-installation logic:
#### `installDependencies(skill: Skill): Promise<void>`
**Algorithm:**
1. Check if skill has `installers` in manifest
2. Filter installers by current OS
3. If multiple installers available, ask user to choose (or pick first)
4. For each installer:
- **brew**: Run `brew install <formula>`
- **node**: Run `<pm> install <package>` (using detected package manager)
- **go**: Check for `go` binary, install via `brew` if missing, then `go install <import>`
- **download**: Download URL, extract archive, move to `~/.flynn/tools/<skill-name>/`
5. After installation, verify binaries (if specified) using `which`
6. Log warnings for failed installations (don't block skill registration)
#### `uninstallDependencies(skill: Skill): Promise<void>`
**Algorithm:**
1. Check if skill has `installers`
2. Reverse installation:
- **brew**: Run `brew uninstall <formula>`
- **node**: Run `<pm> uninstall <package>`
- **go**: Remove binary from `GOBIN`
- **download**: Remove `~/.flynn/tools/<skill-name>/`
3. Ask user before removal unless `--yes` flag
### 3.4 Update CLI Install Command
**File:** `src/cli/skills.ts`
Enhance `flynn skills install`:
```typescript
skillsCommand
.command('install <path>')
.description('Install a skill from path or URL')
.option('--auto-install', 'Automatically install dependencies')
.action(async (path, options) => {
// Load skill from path
const skill = loadSkill(path, 'managed');
if (!skill) {
console.error('Failed to load skill');
return;
}
// Check requirements
const { available, reasons } = checkRequirements(skill.manifest.requirements);
if (!available) {
console.error('Skill requirements not met:');
reasons.forEach(reason => console.error(` - ${reason}`));
return;
}
// Install dependencies
if (options.autoInstall || skill.manifest.installers) {
console.log('Installing dependencies...');
await installDependencies(skill);
}
// Install skill
await skillInstaller.install(path);
});
```
### 3.5 Create Example Skills
Create example skills to test installer specs:
**Example 1: Skill with brew dependency**
```
~/.flynn/workspace/skills/example-brew/
├── manifest.json
└── SKILL.md
```
**manifest.json:**
```json
{
"name": "example-brew",
"description": "Example skill with brew dependency",
"version": "1.0.0",
"tier": "workspace",
"installers": [
{
"kind": "brew",
"label": "Install jq (brew)",
"formula": "jq",
"bins": ["jq"]
}
]
}
```
**Example 2: Skill with node dependency**
```
~/.flynn/workspace/skills/example-node/
├── manifest.json
└── SKILL.md
```
**manifest.json:**
```json
{
"name": "example-node",
"description": "Example skill with node dependency",
"version": "1.0.0",
"tier": "workspace",
"installers": [
{
"kind": "node",
"label": "Install typescript (npm)",
"package": "typescript",
"bins": ["tsc"]
}
]
}
```
### 3.6 Tests
**File:** `src/skills/package-manager.test.ts`
Test coverage:
- Package manager detection (npm, pnpm, yarn, bun)
- Install execution
- Error handling for missing package manager
**File:** `src/skills/installer.test.ts` (extend existing tests)
Additional test coverage:
- `installDependencies()` with brew installer
- `installDependencies()` with node installer
- `installDependencies()` with go installer
- `installDependencies()` with download installer
- OS filtering for installers
- `uninstallDependencies()`
---
## Configuration Changes
### Add Skills Watcher Settings
**Default config (`~/.flynn/flynn.yaml`):**
```yaml
skills:
load:
watch: true # Enable skills watcher
watch_debounce_ms: 250 # Debounce file changes
```
### Add Package Manager Preference
**Optional config:**
```yaml
skills:
install:
package_manager: pnpm # Preferred manager: npm | pnpm | yarn | bun
```
---
## Git Workflow
### Branch Setup
```bash
# Create feature branch
git checkout -b feature/skills-infrastructure
# Ensure we're up to date
git fetch origin
git rebase origin/main
```
### Commit Strategy
Commit frequently with atomic changes:
1. **Initial commit:**
```
git add .
git commit -m "feat(skills): add command dispatch mode
- Create src/cli/skills.ts with subcommands
- Add skills list/info/install/uninstall/refresh
- Register skills command in CLI
- Enhance doctor with per-skill details
- Add CLI tests
```
2. **Second commit:**
```
git add src/skills/watcher.ts
git add src/daemon/services.ts
git add src/config/schema.ts
git commit -m "feat(skills): add skills watcher for auto-reload
- Implement SkillsWatcher class with chokidar
- Watch bundled/managed/workspace directories
- Debounce file changes (configurable)
- Integrate watcher into daemon lifecycle
- Add configuration schema for watcher
- Add watcher tests
```
3. **Third commit:**
```
git add src/skills/types.ts
git add src/skills/package-manager.ts
git add src/skills/installer.ts
git add src/cli/skills.ts
git commit -m "feat(skills): add installer specs for auto-install
- Add SkillInstaller type to manifest
- Implement package manager detection
- Extend installer with dependency installation
- Support brew/node/go/download installers
- Add CLI --auto-install flag
- Add example skills for testing
- Add package manager and installer tests
```
4. **Final commit:**
```
git add package.json
git add package-lock.json
git add .flynn/
git add docs/
git commit -m "docs(skills): update documentation and configuration
- Add chokidar dependency
- Add skills watcher config to default config
- Create SKILLS.md documentation
- Update CHANGELOG.md"
```
### Documentation Updates
**File:** `docs/plans/2026-02-11-skills-infrastructure-plan.md` (this file)
**File:** `CHANGELOG.md` (update with new features)
**File:** `README.md` (update with skills CLI commands)
---
## Testing Strategy
### Unit Tests (already extensive)
- `src/skills/registry.test.ts` - 11 tests
- `src/skills/loader.test.ts` - 21 tests
- `src/skills/installer.test.ts` - 13 tests (extend)
- Total: 45+ tests
### New Tests Required
- `src/cli/skills.test.ts` - 20+ tests (CLI commands)
- `src/skills/watcher.test.ts` - 15+ tests (file watching)
- `src/skills/package-manager.test.ts` - 10+ tests (package managers)
- Total: ~45 new tests
### Integration Tests
- Test skills watcher with real file system changes
- Test installer specs with real package manager (use temp directories)
- Test CLI commands end-to-end (install → list → info → uninstall)
### Test Execution
```bash
# Run all tests
pnpm test:run
# Run specific test file
pnpm test:run src/skills/watcher.test.ts
# Run tests in watch mode during development
pnpm test
```
---
## Future Phases (Post-Infrastructure)
After completing these three phases, the foundation will be solid for integrating skills from ClawHub. Suggested next steps:
### Phase 4: Integrate Top 3 Skills from ClawHub
1. **github** skill (12,020 downloads)
- Wrap `gh` CLI as a tool
- Implement: issues, PRs, CI runs, API queries
- File: `src/tools/github.ts`
2. **self-improving-agent** skill (17,007 downloads)
- Enhance memory extraction hooks
- Capture learnings from errors/corrections
- Extend: `src/backends/native/orchestrator.ts`
3. **agent-browser** skill (12,862 downloads)
- Evaluate Rust-based browser CLI vs current Puppeteer
- Consider performance improvements
- File: `src/tools/browser/` (enhance or replace)
### Phase 5: Per-Agent Skill Isolation (P2)
Add `skills.allow` and `skills.deny` arrays to agent config:
- Allowlist skills per agent
- Modify `getSystemPromptAdditions()` to filter by agent
- Update CLI to show per-agent skill sets
### Phase 6: Session Skill Snapshot (P2)
Cache skill snapshot in session metadata:
- Store `skillNames[]` in SessionStore
- Use consistent skill set across compaction
- Add `snapshotSkills()` method to SkillRegistry
### Phase 7: Remote Skills Registry (P3) - Optional
Consider building a private or public skill registry:
- Skill discovery API
- Skill download and install
- Version management
- Requires infrastructure decision (keep private per user preference)
---
## Success Criteria
### Phase 1 (Command Dispatch)
- [ ] `flynn skills list` shows all registered skills
- [ ] `flynn skills info <name>` displays skill details
- [ ] `flynn skills install <path>` installs local skill
- [ ] `flynn skills uninstall <name>` removes skill
- [ ] `flynn skills refresh` reloads skills
- [ ] Doctor shows per-skill availability details
- [ ] All CLI commands have test coverage
- [ ] Help text is clear and complete
### Phase 2 (Skills Watcher)
- [ ] Skills reload automatically when SKILL.md changes
- [ ] Skills reload automatically when manifest.json changes
- [ ] Skills reload when skill directory is added/removed
- [ ] File changes are debounced (configurable)
- [ ] Watcher stops cleanly on daemon shutdown
- [ ] Configuration toggle enables/disables watcher
- [ ] All watcher features have test coverage
### Phase 3 (Installer Specs)
- [ ] Brew dependencies install automatically
- [ ] Node dependencies install with detected package manager
- [ ] Go dependencies install (including installing go if needed)
- [ ] Download installers work (URL fetch + extract)
- [ ] Installers respect OS filtering
- [ ] Failed installations don't block skill registration
- [ ] CLI `--auto-install` flag works
- [ ] Example skills demonstrate all installer types
- [ ] All installer features have test coverage
### Overall
- [ ] All tests pass (`pnpm test:run`)
- [ ] Linting passes (`pnpm lint`)
- [ ] Type checking passes (`pnpm typecheck`)
- [ ] Documentation is updated
- [ ] Change log is documented
- [ ] Git history is clean (atomic commits)
---
## Risks and Mitigations
| Risk | Likelihood | Impact | Mitigation |
|-------|-----------|---------|-------------|
| **Chokidar file descriptor limits** | Low | Medium | Add warning in docs, recommend increasing ulimit |
| **Package manager detection conflicts** | Low | Low | Prefer pnpm, fall back gracefully |
| **Installer execution security** | Medium | High | Prompt for user confirmation before running installs |
| **Watcher performance with many skills** | Low | Low | Debounce by default (250ms), make configurable |
| **Circular dependency in installers** | Very Low | High | Manual review of manifest.json, no auto-resolution |
---
## References
- OpenClaw Skills Documentation: https://docs.openclaw.ai/tools/skills.md
- ClawHub: https://clawhub.ai
- Chokidar: https://github.com/paulmillr/chokidar
- Flynn Skills System: `/home/will/lab/flynn/src/skills/`
- Previous Gap Analysis: `/home/will/lab/flynn/docs/plans/2026-02-06-openclaw-feature-gap-analysis.md`
---
**Plan Status:** Ready for implementation
**Estimated Total Effort:** 8-11 hours
**Next Step:** Create branch and begin Phase 1
+45 -19
View File
@@ -1040,27 +1040,53 @@
}
}
},
"earlier_plans": {
"plans": [
{ "file": "2026-02-02-flynn-design.md", "status": "completed" },
{ "file": "2026-02-02-flynn-phase1-implementation.md", "status": "completed" },
{ "file": "2026-02-02-flynn-phase2-implementation.md", "status": "completed" },
{ "file": "2026-02-05-flynn-phase3-implementation.md", "status": "completed" },
{ "file": "2026-02-05-tui-redesign.md", "status": "completed" },
{ "file": "2026-02-05-tui-redesign-implementation.md", "status": "completed" },
{ "file": "2026-02-05-llamacpp-integration-design.md", "status": "completed" },
{ "file": "2026-02-05-llamacpp-implementation.md", "status": "completed" },
{ "file": "2026-02-05-backend-switch-design.md", "status": "completed" },
{ "file": "2026-02-05-backend-switch-implementation.md", "status": "completed" },
{ "file": "2026-02-05-openclaw-parity-design.md", "status": "completed" },
{ "file": "2026-02-05-phase1-tool-framework.md", "status": "completed" },
{ "file": "2026-02-05-phase2-websocket-gateway.md", "status": "completed" },
{ "file": "2026-02-05-phase3-channel-adapters.md", "status": "completed" },
{ "file": "2026-02-05-phase5-cli-cron-doctor-design.md", "status": "completed" },
{ "file": "2026-02-05-phase5a-implementation.md", "status": "completed" }
]
"skills_infrastructure": {
"file": "2026-02-11-skills-infrastructure-plan.md",
"status": "planned",
"date": "2026-02-11",
"summary": "Three-phase plan to improve skills system: Command Dispatch (P0), Skills Watcher (P1), Installer Specs (P1). Infrastructure-first approach before integrating ClawHub skills. Estimated 8-11 hours total. Model strategy: glm-4.7-flash for mechanical tasks, glm-4.7 for complex/orchestration tasks.",
"phases": {
"phase_1_command_dispatch": {
"priority": "P0",
"status": "not_started",
"description": "flynn skills CLI commands (list/info/install/uninstall/refresh) with doctor enhancement",
"effort": "2-3 hours"
},
"phase_2_skills_watcher": {
"priority": "P1",
"status": "not_started",
"description": "Auto-reload skills with chokidar file watcher, configurable debounce",
"effort": "3-4 hours"
},
"phase_3_installer_specs": {
"priority": "P1",
"status": "not_started",
"description": "Auto-install dependencies (brew/node/go/download) with package manager detection",
"effort": "3-4 hours"
}
}
},
"earlier_plans": {
"plans": [
{ "file": "2026-02-02-flynn-design.md", "status": "completed" },
{ "file": "2026-02-02-flynn-phase1-implementation.md", "status": "completed" },
{ "file": "2026-02-02-flynn-phase2-implementation.md", "status": "completed" },
{ "file": "2026-02-05-flynn-phase3-implementation.md", "status": "completed" },
{ "file": "2026-02-05-tui-redesign.md", "status": "completed" },
{ "file": "2026-02-05-tui-redesign-implementation.md", "status": "completed" },
{ "file": "2026-02-05-llamacpp-integration-design.md", "status": "completed" },
{ "file": "2026-02-05-llamacpp-implementation.md", "status": "completed" },
{ "file": "2026-02-05-backend-switch-design.md", "status": "completed" },
{ "file": "2026-02-05-backend-switch-implementation.md", "status": "completed" },
{ "file": "2026-02-05-openclaw-parity-design.md", "status": "completed" },
{ "file": "2026-02-05-phase1-tool-framework.md", "status": "completed" },
{ "file": "2026-02-05-phase2-websocket-gateway.md", "status": "completed" },
{ "file": "2026-02-05-phase3-channel-adapters.md", "status": "completed" },
{ "file": "2026-02-05-phase5-cli-cron-doctor-design.md", "status": "completed" },
{ "file": "2026-02-05-phase5a-implementation.md", "status": "completed" }
]
}
},
"overall_progress": {
"total_test_count": 1331,