
Self Improvement
- 91 installs
- 272 repo stars
- Updated June 12, 2026
- pskoett/pskoett-skills
This is a copy of self-improvement by pskoett - installs and ranking accrue to the original listing.
Helps with ai & agent building tasks.
About
self-improvement is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- self-improvement
- AI & Agent Building
- AI-coding skill
Self Improvement by the numbers
- 91 all-time installs (skills.sh)
- +4 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/pskoett/pskoett-skills --skill self-improvementAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 91 |
|---|---|
| repo stars | ★ 272 |
| Last updated | June 12, 2026 |
| Repository | pskoett/pskoett-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
Self-Improvement Skill
Install
gh skill install pskoett/pskoett-skills self-improvementFor CI-only execution, use:
gh skill install pskoett/pskoett-skills self-improvement-ciFallback using the Agent Skills CLI:
npx skills add pskoett/pskoett-skills/skills/self-improvement
npx skills add pskoett/pskoett-skills/skills/self-improvement-ciLog learnings and errors to markdown files for continuous improvement. Coding agents can later process these into fixes, and important learnings get promoted to project memory.
Pair with [`self-healing`](../self-healing/SKILL.md): self-healing is the active runtime recovery primitive — it diagnoses, patches, verifies, and files HEAL- entries to .learnings/HEALS.md when something breaks mid-task. Self-improvement (this skill) is the passive accumulation and promotion layer — it logs corrections, knowledge gaps, and feature requests, and promotes recurring heal handoffs to permanent memory. They share .learnings/ but write to different files; verify discipline lives in self-healing, promotion logic lives here.
Quick Reference
| Situation | Action |
|---|---|
| Active failure mid-task — agent needs to fix it now | Use `self-healing` instead (files verified HEAL- to .learnings/HEALS.md) |
| Command/operation failed in the past (not actively healing) | Log to .learnings/ERRORS.md |
| User corrects you | Log to .learnings/LEARNINGS.md with category correction |
| User wants missing feature | Log to .learnings/FEATURE_REQUESTS.md |
| API/external tool fails | Log to .learnings/ERRORS.md with integration details |
| Self-healing Handoff block meets promotion rule (see Promotion Rule below) | Promote the Distilled Rule to CLAUDE.md / AGENTS.md / new skill |
| Knowledge was outdated | Log to .learnings/LEARNINGS.md with category knowledge_gap |
| Found better approach | Log to .learnings/LEARNINGS.md with category best_practice |
| Simplify/Harden recurring patterns | Log/update .learnings/LEARNINGS.md with Source: simplify-and-harden and a stable Pattern-Key |
| Similar to existing entry | Link with **See Also**, consider priority bump |
| Broadly applicable learning | Promote to CLAUDE.md, AGENTS.md, and/or .github/copilot-instructions.md |
| OpenClaw workspace targets (SOUL.md, TOOLS.md) | See references/openclaw-integration.md |
Setup
Create .learnings/ directory in project root if it doesn't exist:
mkdir -p .learningsCopy the file templates from assets/ (LEARNINGS.md, ERRORS.md, FEATURE_REQUESTS.md) or create files with headers.
Logging Format
Learning Entry
Append to .learnings/LEARNINGS.md:
## [LRN-YYYYMMDD-XXX] category
**Logged**: ISO-8601 timestamp
**Priority**: low | medium | high | critical
**Status**: pending
**Area**: frontend | backend | infra | tests | docs | config
### Summary
One-line description of what was learned
### Details
Full context: what happened, what was wrong, what's correct
### Suggested Action
Specific fix or improvement to make
### Metadata
- Source: conversation | error | user_feedback
- Related Files: path/to/file.ext
- Tags: tag1, tag2
- See Also: LRN-20250110-001 (if related to existing entry)
- Pattern-Key: simplify.dead_code | harden.input_validation (optional, for recurring-pattern tracking)
- Recurrence-Count: 1 (optional)
- First-Seen: 2025-01-15 (optional)
- Last-Seen: 2025-01-15 (optional)
---Error Entry
Append to .learnings/ERRORS.md:
## [ERR-YYYYMMDD-XXX] skill_or_command_name
**Logged**: ISO-8601 timestamp
**Priority**: high
**Status**: pending
**Area**: frontend | backend | infra | tests | docs | config
### Summary
Brief description of what failed
### ErrorActual error message or output
### Context
- Command/operation attempted
- Input or parameters used
- Environment details if relevant
### Suggested Fix
If identifiable, what might resolve this
### Metadata
- Reproducible: yes | no | unknown
- Related Files: path/to/file.ext
- See Also: ERR-20250110-001 (if recurring)
---Feature Request Entry
Append to .learnings/FEATURE_REQUESTS.md:
## [FEAT-YYYYMMDD-XXX] capability_name
**Logged**: ISO-8601 timestamp
**Priority**: medium
**Status**: pending
**Area**: frontend | backend | infra | tests | docs | config
### Requested Capability
What the user wanted to do
### User Context
Why they needed it, what problem they're solving
### Complexity Estimate
simple | medium | complex
### Suggested Implementation
How this could be built, what it might extend
### Metadata
- Frequency: first_time | recurring
- Related Features: existing_feature_name
---ID Generation
Format: TYPE-YYYYMMDD-XXX
- TYPE:
LRN(learning),ERR(error),FEAT(feature) - YYYYMMDD: Current date
- XXX: Sequential number or random 3 chars (e.g.,
001,A7B)
Examples: LRN-20250115-001, ERR-20250115-A3F, FEAT-20250115-002
Resolving Entries
When an issue is fixed, update the entry:
1. Change **Status**: pending → **Status**: resolved 2. Add resolution block after Metadata:
### Resolution
- **Resolved**: 2025-01-16T09:00:00Z
- **Commit/PR**: abc123 or #42
- **Notes**: Brief description of what was doneOther status values:
in_progress- Actively being worked onwont_fix- Decided not to address (add reason in Resolution notes)promoted- Elevated to CLAUDE.md, AGENTS.md, or .github/copilot-instructions.mdpromoted_to_skill- Extracted as a reusable skill (see Automatic Skill Extraction)
Promoting to Project Memory
When a learning is broadly applicable (not a one-off fix), promote it to permanent project memory.
When to Promote
- Learning applies across multiple files/features
- Knowledge any contributor (human or AI) should know
- Prevents recurring mistakes
- Documents project-specific conventions
Promotion Targets
| Target | What Belongs There |
|---|---|
CLAUDE.md | Project facts, conventions, gotchas for all Claude interactions |
AGENTS.md | Agent-specific workflows, tool usage patterns, automation rules |
.github/copilot-instructions.md | Project context and conventions for GitHub Copilot |
OpenClaw workspace targets (SOUL.md, TOOLS.md) are covered in references/openclaw-integration.md.
How to Promote
1. Distill the learning into a concise rule or fact 2. Add to appropriate section in target file (create file if needed) 3. Update original entry:
- Change
**Status**: pending→**Status**: promoted - Add
**Promoted**: CLAUDE.md,AGENTS.md, or.github/copilot-instructions.md
Promotion Examples
Learning (verbose):
Project uses pnpm workspaces. Attempted npm install but failed.Lock file ispnpm-lock.yaml. Must usepnpm install.
In CLAUDE.md (concise):
## Build & Dependencies
- Package manager: pnpm (not npm) - use `pnpm install`Learning (verbose):
When modifying API endpoints, must regenerate TypeScript client.
Forgetting this causes type mismatches at runtime.
In AGENTS.md (actionable):
## After API Changes
1. Regenerate client: `pnpm run generate:api`
2. Check for type errors: `pnpm tsc --noEmit`Recurring Pattern Detection
If logging something similar to an existing entry:
1. Search first: grep -r "keyword" .learnings/ 2. Link entries: Add **See Also**: ERR-20250110-001 in Metadata 3. Bump priority if issue keeps recurring 4. Consider systemic fix: Recurring issues often indicate:
- Missing documentation (→ promote to CLAUDE.md or .github/copilot-instructions.md)
- Missing automation (→ add to AGENTS.md)
- Architectural problem (→ create tech debt ticket)
Simplify & Harden Feed
Use this workflow to ingest recurring patterns from the simplify-and-harden skill and turn them into durable prompt guidance.
Ingestion Workflow
1. Read simplify_and_harden.learning_loop.candidates from the task summary. 2. For each candidate, use pattern_key as the stable dedupe key. 3. Search .learnings/LEARNINGS.md for an existing entry with that key:
grep -n "Pattern-Key: <pattern_key>" .learnings/LEARNINGS.md
4. If found:
- Increment
Recurrence-Count - Update
Last-Seen - Add
See Alsolinks to related entries/tasks
5. If not found:
- Create a new
LRN-...entry - Set
Source: simplify-and-harden - Set
Pattern-Key,Recurrence-Count: 1, andFirst-Seen/Last-Seen
Promotion Rule (System Prompt Feedback)
Promote recurring patterns into agent context/system prompt files when all are true:
Recurrence-Count >= 3- Seen across at least 2 distinct tasks
- Occurred within a 30-day window
Promotion targets:
CLAUDE.mdAGENTS.md.github/copilot-instructions.md- OpenClaw workspace files when applicable — see
references/openclaw-integration.md
This three-condition rule is the single promotion threshold for this skill. The Quick Reference row for self-healing Handoff blocks and the aggregator skills (learning-aggregator, learning-aggregator-ci) all use this same rule.
Write promoted rules as short prevention rules (what to do before/while coding), not long incident write-ups.
Periodic Review
Review .learnings/ at natural breakpoints:
When to Review
- Before starting a new major task
- After completing a feature
- When working in an area with past learnings
- Weekly during active development
Quick Status Check
# Count pending items
grep -h "Status\*\*: pending" .learnings/*.md | wc -l
# List pending high-priority items
grep -B5 "Priority\*\*: high" .learnings/*.md | grep "^## \["
# Find learnings for a specific area
grep -l "Area\*\*: backend" .learnings/*.mdReview Actions
- Resolve fixed items
- Promote applicable learnings
- Link related entries
- Escalate recurring issues
Detection Triggers
Automatically log when you notice:
Corrections (→ learning with correction category):
- "No, that's not right..."
- "Actually, it should be..."
- "You're wrong about..."
- "That's outdated..."
Feature Requests (→ feature request):
- "Can you also..."
- "I wish you could..."
- "Is there a way to..."
- "Why can't you..."
Knowledge Gaps (→ learning with knowledge_gap category):
- User provides information you didn't know
- Documentation you referenced is outdated
- API behavior differs from your understanding
Errors (→ error entry):
- Command returns non-zero exit code
- Exception or stack trace
- Unexpected output or behavior
- Timeout or connection failure
Priority Guidelines
| Priority | When to Use |
|---|---|
critical | Blocks core functionality, data loss risk, security issue |
high | Significant impact, affects common workflows, recurring issue |
medium | Moderate impact, workaround exists |
low | Minor inconvenience, edge case, nice-to-have |
Area Tags
Use to filter learnings by codebase region:
| Area | Scope |
|---|---|
frontend | UI, components, client-side code |
backend | API, services, server-side code |
infra | CI/CD, deployment, Docker, cloud |
tests | Test files, testing utilities, coverage |
docs | Documentation, comments, READMEs |
config | Configuration files, environment, settings |
Best Practices
1. Log immediately - context is freshest right after the issue 2. Be specific - future agents need to understand quickly 3. Include reproduction steps - especially for errors 4. Link related files - makes fixes easier 5. Suggest concrete fixes - not just "investigate" 6. Use consistent categories - enables filtering 7. Promote aggressively - if in doubt, add to CLAUDE.md or .github/copilot-instructions.md 8. Review regularly - stale learnings lose value
Gitignore Options
Keep learnings local (per-developer):
.learnings/Track learnings in repo (team-wide): Don't add to .gitignore - learnings become shared knowledge.
Hybrid (track templates, ignore entries):
.learnings/*.md
!.learnings/.gitkeepHook Integration
Enable automatic reminders through agent hooks. This is opt-in - you must explicitly configure hooks. The same two scripts work across Claude Code and Codex CLI (both deliver JSON on stdin and accept the same additionalContext output shape); Copilot hooks can log but not inject context, so Copilot uses the instructions-file channel. Full per-agent setup including Codex and Copilot: references/hooks-setup.md.
Quick Setup (Claude Code)
Create .claude/settings.json in your project. The command path must point to where the skill is actually installed: .claude/skills/self-improvement/ for gh skill install / npx skills add, or skills/self-improvement/ if this repo is vendored into the project. Relative paths resolve from the project root.
{
"hooks": {
"UserPromptSubmit": [{
"hooks": [{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/skills/self-improvement/scripts/activator.sh"
}]
}]
}
}This injects a learning evaluation reminder after each prompt (~50-100 tokens overhead).
Full Setup (With Error Detection)
{
"hooks": {
"UserPromptSubmit": [{
"hooks": [{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/skills/self-improvement/scripts/activator.sh"
}]
}],
"PostToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/skills/self-improvement/scripts/error-detector.sh"
}]
}]
}
}Hooks receive the event payload as JSON on stdin. The error detector parses tool_response from that JSON and returns its reminder as additionalContext JSON output, which is required for PostToolUse output to reach the model.
Available Hook Scripts
| Script | Hook Type | Purpose |
|---|---|---|
scripts/activator.sh | UserPromptSubmit (Claude Code, Codex) | Reminds to evaluate learnings after tasks (plain stdout is added to context for this event on both agents) |
scripts/error-detector.sh | PostToolUse (Claude Code, Codex), postToolUse (Copilot, logging only) | Parses the stdin JSON payload for error patterns across all three agents' payload shapes; emits an additionalContext reminder |
See references/hooks-setup.md for detailed configuration and troubleshooting.
Automatic Skill Extraction
When a learning is valuable enough to become a reusable skill, extract it using the provided helper.
Skill Extraction Criteria
A learning qualifies for skill extraction when ANY of these apply:
| Criterion | Description |
|---|---|
| Recurring | Has See Also links to 2+ similar issues |
| Verified | Status is resolved with working fix |
| Non-obvious | Required actual debugging/investigation to discover |
| Broadly applicable | Not project-specific; useful across codebases |
| User-flagged | User says "save this as a skill" or similar |
Extraction Workflow
1. Identify candidate: Learning meets extraction criteria 2. Run helper (or create manually):
./skills/self-improvement/scripts/extract-skill.sh skill-name --dry-run
./skills/self-improvement/scripts/extract-skill.sh skill-name3. Customize SKILL.md: Fill in template with learning content 4. Update learning: Set status to promoted_to_skill, add Skill-Path 5. Verify: Read skill in fresh session to ensure it's self-contained
Manual Extraction
If you prefer manual creation:
1. Create skills/<skill-name>/SKILL.md 2. Use template from assets/SKILL-TEMPLATE.md 3. Follow Agent Skills spec:
- YAML frontmatter with
nameanddescription - Name must match folder name
- No README.md inside skill folder
Extraction Detection Triggers
Watch for these signals that a learning should become a skill:
In conversation:
- "Save this as a skill"
- "I keep running into this"
- "This would be useful for other projects"
- "Remember this pattern"
In learning entries:
- Multiple
See Alsolinks (recurring issue) - High priority + resolved status
- Category:
best_practicewith broad applicability - User feedback praising the solution
Skill Quality Gates
Before extraction, verify:
- [ ] Solution is tested and working
- [ ] Description is clear without original context
- [ ] Code examples are self-contained
- [ ] No project-specific hardcoded values
- [ ] Follows skill naming conventions (lowercase, hyphens)
Multi-Agent Support
This skill works across different AI coding agents with agent-specific activation.
Claude Code
Activation: Hooks (UserPromptSubmit, PostToolUse) Setup: .claude/settings.json with hook configuration Detection: Automatic via hook scripts
Codex CLI
Activation: Hooks (UserPromptSubmit, PostToolUse) — experimental, behind codex_hooks = true in config.toml Setup: <repo>/.codex/hooks.json or ~/.codex/hooks.json; same scripts, same payload/output shapes as Claude Code Detection: Automatic via hook scripts; see references/hooks-setup.md for the config Fallback: Add the self-improvement guidance to AGENTS.md if hooks are unavailable
GitHub Copilot
Activation: Instructions file (Copilot hooks exist in .github/hooks/*.json but their output is ignored for prompt/tool events — they can log, not inject context) Setup: Add to .github/copilot-instructions.md:
## Self-Improvement
After solving non-obvious issues, consider logging to `.learnings/`:
1. Use format from self-improvement skill
2. Link related entries with See Also
3. Promote high-value learnings to skills
Ask in chat: "Should I log this as a learning?"Detection: Manual review at session end
OpenClaw (Optional)
OpenClaw-specific setup, promotion targets, and hybrid usage details are kept in references/openclaw-integration.md so this main skill stays focused on the core self-improvement workflow for coding agents.
Agent-Agnostic Guidance
Regardless of agent, apply self-improvement when you:
1. Discover something non-obvious - solution wasn't immediate 2. Correct yourself - initial approach was wrong 3. Learn project conventions - discovered undocumented patterns 4. Hit unexpected errors - especially if diagnosis was difficult 5. Find better approaches - improved on your original solution
Copilot Chat Integration
For Copilot users, add this to your prompts when relevant:
After completing this task, evaluate if any learnings should be logged to .learnings/ using the self-improvement skill format.Or use quick prompts:
- "Log this to learnings"
- "Create a skill from this solution"
- "Check .learnings/ for related issues"
Errors
Command failures, API errors, and unexpected behavior captured during development.
Areas: frontend | backend | infra | tests | docs | config Statuses: pending | in_progress | resolved | wont_fix | promoted | promoted_to_skill
Status Definitions
| Status | Meaning |
|---|---|
pending | Not yet addressed |
in_progress | Actively being worked on |
resolved | Issue fixed (add Resolution block) |
wont_fix | Decided not to address (reason in Resolution) |
promoted | Elevated to CLAUDE.md, AGENTS.md, or copilot-instructions.md |
promoted_to_skill | Extracted as a reusable skill |
Entry format: see the self-improvement skill's "Error Entry" section. IDs use ERR-YYYYMMDD-XXX.
---
Feature Requests
Missing capabilities requested by users, captured during development.
Areas: frontend | backend | infra | tests | docs | config Statuses: pending | in_progress | resolved | wont_fix Complexity: simple | medium | complex
Status Definitions
| Status | Meaning |
|---|---|
pending | Not yet addressed |
in_progress | Actively being built |
resolved | Capability implemented (add Resolution block) |
wont_fix | Decided not to build (reason in Resolution) |
Entry format: see the self-improvement skill's "Feature Request Entry" section. IDs use FEAT-YYYYMMDD-XXX.
---
Learnings
Corrections, insights, and knowledge gaps captured during development.
Categories: correction | knowledge_gap | best_practice Areas: frontend | backend | infra | tests | docs | config Statuses: pending | in_progress | resolved | wont_fix | promoted | promoted_to_skill
Status Definitions
| Status | Meaning |
|---|---|
pending | Not yet addressed |
in_progress | Actively being worked on |
resolved | Issue fixed or knowledge integrated |
wont_fix | Decided not to address (reason in Resolution) |
promoted | Elevated to CLAUDE.md, AGENTS.md, or copilot-instructions.md |
promoted_to_skill | Extracted as a reusable skill |
Skill Extraction Fields
When a learning is promoted to a skill, add these fields:
**Status**: promoted_to_skill
**Skill-Path**: skills/skill-nameExample:
## [LRN-20250115-001] best_practice
**Logged**: 2025-01-15T10:00:00Z
**Priority**: high
**Status**: promoted_to_skill
**Skill-Path**: skills/docker-m1-fixes
**Area**: infra
### Summary
Docker build fails on Apple Silicon due to platform mismatch
...---
Skill Template
Template for creating skills extracted from learnings. Copy and customize.
---
SKILL.md Template
---
name: skill-name-here
description: "Concise description of when and why to use this skill. Include trigger conditions."
---
# Skill Name
Brief introduction explaining the problem this skill solves and its origin.
## Quick Reference
| Situation | Action |
|-----------|--------|
| [Trigger 1] | [Action 1] |
| [Trigger 2] | [Action 2] |
## Background
Why this knowledge matters. What problems it prevents. Context from the original learning.
## Solution
### Step-by-Step
1. First step with code or command
2. Second step
3. Verification step
### Code Example
\`\`\`language
// Example code demonstrating the solution
\`\`\`
## Common Variations
- **Variation A**: Description and how to handle
- **Variation B**: Description and how to handle
## Gotchas
- Warning or common mistake #1
- Warning or common mistake #2
## Related
- Link to related documentation
- Link to related skill
## Source
Extracted from learning entry.
- **Learning ID**: LRN-YYYYMMDD-XXX
- **Original Category**: correction | insight | knowledge_gap | best_practice
- **Extraction Date**: YYYY-MM-DD---
Minimal Template
For simple skills that don't need all sections:
---
name: skill-name-here
description: "What this skill does and when to use it."
---
# Skill Name
[Problem statement in one sentence]
## Solution
[Direct solution with code/commands]
## Source
- Learning ID: LRN-YYYYMMDD-XXX---
Template with Scripts
For skills that include executable helpers:
---
name: skill-name-here
description: "What this skill does and when to use it."
---
# Skill Name
[Introduction]
## Quick Reference
| Command | Purpose |
|---------|---------|
| `./scripts/helper.sh` | [What it does] |
| `./scripts/validate.sh` | [What it does] |
## Usage
### Automated (Recommended)
\`\`\`bash
./skills/skill-name/scripts/helper.sh [args]
\`\`\`
### Manual Steps
1. Step one
2. Step two
## Scripts
| Script | Description |
|--------|-------------|
| `scripts/helper.sh` | Main utility |
| `scripts/validate.sh` | Validation checker |
## Source
- Learning ID: LRN-YYYYMMDD-XXX---
Naming Conventions
- Skill name: lowercase, hyphens for spaces
- Good:
docker-m1-fixes,api-timeout-patterns - Bad:
Docker_M1_Fixes,APITimeoutPatterns
- Description: Start with action verb, mention trigger
- Good: "Handles Docker build failures on Apple Silicon. Use when builds fail with platform mismatch."
- Bad: "Docker stuff"
- Files:
SKILL.md- Required, main documentationscripts/- Optional, executable codereferences/- Optional, detailed docsassets/- Optional, templates
---
Extraction Checklist
Before creating a skill from a learning:
- [ ] Learning is verified (status: resolved)
- [ ] Solution is broadly applicable (not one-off)
- [ ] Content is complete (has all needed context)
- [ ] Name follows conventions
- [ ] Description is concise but informative
- [ ] Quick Reference table is actionable
- [ ] Code examples are tested
- [ ] Source learning ID is recorded
After creating:
- [ ] Update original learning with
promoted_to_skillstatus - [ ] Add
Skill-Path: skills/skill-nameto learning metadata - [ ] Test skill by reading it in a fresh session
/**
* Self-Improvement Hook for OpenClaw
*
* Injects a reminder to evaluate learnings during agent bootstrap.
* Fires on agent:bootstrap event before workspace files are injected.
*/
import type { HookHandler } from 'openclaw/hooks';
const REMINDER_CONTENT = `
## Self-Improvement Reminder
After completing tasks, evaluate if any learnings should be captured:
**Log when:**
- User corrects you → \`.learnings/LEARNINGS.md\`
- Command/operation fails → \`.learnings/ERRORS.md\`
- User wants missing capability → \`.learnings/FEATURE_REQUESTS.md\`
- You discover your knowledge was wrong → \`.learnings/LEARNINGS.md\`
- You find a better approach → \`.learnings/LEARNINGS.md\`
**Promote when pattern is proven:**
- Behavioral patterns → \`SOUL.md\`
- Workflow improvements → \`AGENTS.md\`
- Tool gotchas → \`TOOLS.md\`
Keep entries simple: date, title, what happened, what to do differently.
`;
const handler: HookHandler = async (event) => {
// Only handle agent:bootstrap events
if (event.type !== 'agent' || event.action !== 'bootstrap') {
return;
}
// Inject the reminder as a virtual bootstrap file.
// Some bootstrap events may not initialize bootstrapFiles.
event.context.bootstrapFiles ??= [];
event.context.bootstrapFiles.push({
name: 'SELF_IMPROVEMENT_REMINDER.md',
content: REMINDER_CONTENT,
virtual: true,
});
};
export default handler;
Self-Improvement Hook
Injects a reminder to evaluate learnings during agent bootstrap.
What It Does
- Fires on
agent:bootstrap(before workspace files are injected) - Adds a reminder block to check
.learnings/for relevant entries - Prompts the agent to log corrections, errors, and discoveries
Configuration
No configuration needed. Enable with:
openclaw hooks enable self-improvementEntry Examples
Concrete examples of well-formatted entries with all fields.
Learning: Correction
## [LRN-20250115-001] correction
**Logged**: 2025-01-15T10:30:00Z
**Priority**: high
**Status**: pending
**Area**: tests
### Summary
Incorrectly assumed pytest fixtures are scoped to function by default
### Details
When writing test fixtures, I assumed all fixtures were function-scoped.
User corrected that while function scope is the default, the codebase
convention uses module-scoped fixtures for database connections to
improve test performance.
### Suggested Action
When creating fixtures that involve expensive setup (DB, network),
check existing fixtures for scope patterns before defaulting to function scope.
### Metadata
- Source: user_feedback
- Related Files: tests/conftest.py
- Tags: pytest, testing, fixtures
---Learning: Knowledge Gap (Resolved)
## [LRN-20250115-002] knowledge_gap
**Logged**: 2025-01-15T14:22:00Z
**Priority**: medium
**Status**: resolved
**Area**: config
### Summary
Project uses pnpm not npm for package management
### Details
Attempted to run `npm install` but project uses pnpm workspaces.
Lock file is `pnpm-lock.yaml`, not `package-lock.json`.
### Suggested Action
Check for `pnpm-lock.yaml` or `pnpm-workspace.yaml` before assuming npm.
Use `pnpm install` for this project.
### Metadata
- Source: error
- Related Files: pnpm-lock.yaml, pnpm-workspace.yaml
- Tags: package-manager, pnpm, setup
### Resolution
- **Resolved**: 2025-01-15T14:30:00Z
- **Commit/PR**: N/A - knowledge update
- **Notes**: Added to CLAUDE.md for future reference
---Learning: Promoted to CLAUDE.md
## [LRN-20250115-003] best_practice
**Logged**: 2025-01-15T16:00:00Z
**Priority**: high
**Status**: promoted
**Promoted**: CLAUDE.md
**Area**: backend
### Summary
API responses must include correlation ID from request headers
### Details
All API responses should echo back the X-Correlation-ID header from
the request. This is required for distributed tracing. Responses
without this header break the observability pipeline.
### Suggested Action
Always include correlation ID passthrough in API handlers.
### Metadata
- Source: user_feedback
- Related Files: src/middleware/correlation.ts
- Tags: api, observability, tracing
---Learning: Promoted to AGENTS.md
## [LRN-20250116-001] best_practice
**Logged**: 2025-01-16T09:00:00Z
**Priority**: high
**Status**: promoted
**Promoted**: AGENTS.md
**Area**: backend
### Summary
Must regenerate API client after OpenAPI spec changes
### Details
When modifying API endpoints, the TypeScript client must be regenerated.
Forgetting this causes type mismatches that only appear at runtime.
The generate script also runs validation.
### Suggested Action
Add to agent workflow: after any API changes, run `pnpm run generate:api`.
### Metadata
- Source: error
- Related Files: openapi.yaml, src/client/api.ts
- Tags: api, codegen, typescript
---Error Entry
## [ERR-20250115-A3F] docker_build
**Logged**: 2025-01-15T09:15:00Z
**Priority**: high
**Status**: pending
**Area**: infra
### Summary
Docker build fails on M1 Mac due to platform mismatch
### Errorerror: failed to solve: python:3.11-slim: no match for platform linux/arm64
### Context
- Command: `docker build -t myapp .`
- Dockerfile uses `FROM python:3.11-slim`
- Running on Apple Silicon (M1/M2)
### Suggested Fix
Add platform flag: `docker build --platform linux/amd64 -t myapp .`
Or update Dockerfile: `FROM --platform=linux/amd64 python:3.11-slim`
### Metadata
- Reproducible: yes
- Related Files: Dockerfile
---Error Entry: Recurring Issue
## [ERR-20250120-B2C] api_timeout
**Logged**: 2025-01-20T11:30:00Z
**Priority**: critical
**Status**: pending
**Area**: backend
### Summary
Third-party payment API timeout during checkout
### ErrorTimeoutError: Request to payments.example.com timed out after 30000ms
### Context
- Command: POST /api/checkout
- Timeout set to 30s
- Occurs during peak hours (lunch, evening)
### Suggested Fix
Implement retry with exponential backoff. Consider circuit breaker pattern.
### Metadata
- Reproducible: yes (during peak hours)
- Related Files: src/services/payment.ts
- See Also: ERR-20250115-X1Y, ERR-20250118-Z3W
---Feature Request
## [FEAT-20250115-001] export_to_csv
**Logged**: 2025-01-15T16:45:00Z
**Priority**: medium
**Status**: pending
**Area**: backend
### Requested Capability
Export analysis results to CSV format
### User Context
User runs weekly reports and needs to share results with non-technical
stakeholders in Excel. Currently copies output manually.
### Complexity Estimate
simple
### Suggested Implementation
Add `--output csv` flag to the analyze command. Use standard csv module.
Could extend existing `--output json` pattern.
### Metadata
- Frequency: recurring
- Related Features: analyze command, json output
---Feature Request: Resolved
## [FEAT-20250110-002] dark_mode
**Logged**: 2025-01-10T14:00:00Z
**Priority**: low
**Status**: resolved
**Area**: frontend
### Requested Capability
Dark mode support for the dashboard
### User Context
User works late hours and finds the bright interface straining.
Several other users have mentioned this informally.
### Complexity Estimate
medium
### Suggested Implementation
Use CSS variables for colors. Add toggle in user settings.
Consider system preference detection.
### Metadata
- Frequency: recurring
- Related Features: user settings, theme system
### Resolution
- **Resolved**: 2025-01-18T16:00:00Z
- **Commit/PR**: #142
- **Notes**: Implemented with system preference detection and manual toggle
---Learning: Promoted to Skill
## [LRN-20250118-001] best_practice
**Logged**: 2025-01-18T11:00:00Z
**Priority**: high
**Status**: promoted_to_skill
**Skill-Path**: skills/docker-m1-fixes
**Area**: infra
### Summary
Docker build fails on Apple Silicon due to platform mismatch
### Details
When building Docker images on M1/M2 Macs, the build fails because
the base image doesn't have an ARM64 variant. This is a common issue
that affects many developers.
### Suggested Action
Add `--platform linux/amd64` to docker build command, or use
`FROM --platform=linux/amd64` in Dockerfile.
### Metadata
- Source: error
- Related Files: Dockerfile
- Tags: docker, arm64, m1, apple-silicon
- See Also: ERR-20250115-A3F, ERR-20250117-B2D
---Extracted Skill Example
When the above learning is extracted as a skill, it becomes:
File: skills/docker-m1-fixes/SKILL.md
---
name: docker-m1-fixes
description: "Fixes Docker build failures on Apple Silicon (M1/M2). Use when docker build fails with platform mismatch errors."
---
# Docker M1 Fixes
Solutions for Docker build issues on Apple Silicon Macs.
## Quick Reference
| Error | Fix |
|-------|-----|
| `no match for platform linux/arm64` | Add `--platform linux/amd64` to build |
| Image runs but crashes | Use emulation or find ARM-compatible base |
## The Problem
Many Docker base images don't have ARM64 variants. When building on
Apple Silicon (M1/M2/M3), Docker attempts to pull ARM64 images by
default, causing platform mismatch errors.
## Solutions
### Option 1: Build Flag (Recommended)
Add platform flag to your build command:
\`\`\`bash
docker build --platform linux/amd64 -t myapp .
\`\`\`
### Option 2: Dockerfile Modification
Specify platform in the FROM instruction:
\`\`\`dockerfile
FROM --platform=linux/amd64 python:3.11-slim
\`\`\`
### Option 3: Docker Compose
Add platform to your service:
\`\`\`yaml
services:
app:
platform: linux/amd64
build: .
\`\`\`
## Trade-offs
| Approach | Pros | Cons |
|----------|------|------|
| Build flag | No file changes | Must remember flag |
| Dockerfile | Explicit, versioned | Affects all builds |
| Compose | Convenient for dev | Requires compose |
## Performance Note
Running AMD64 images on ARM64 uses Rosetta 2 emulation. This works
for development but may be slower. For production, find ARM-native
alternatives when possible.
## Source
- Learning ID: LRN-20250118-001
- Category: best_practice
- Extraction Date: 2025-01-18Hook Setup Guide (Multi-Agent)
Configure automatic self-improvement triggers across AI coding agents. The same two scripts serve all supported agents:
scripts/activator.sh— prompt-submit reminder to evaluate learningsscripts/error-detector.sh— post-tool error detection on shell commands
All supported agents deliver the hook payload as JSON on stdin (there is no CLAUDE_TOOL_OUTPUT environment variable anywhere). What differs per agent is the config file location, the event names, and whether hook output can inject context for the model:
| Agent | Config location | Prompt-submit event | Post-tool event | Can inject context? |
|---|---|---|---|---|
| Claude Code | .claude/settings.json (project) or ~/.claude/settings.json | UserPromptSubmit (plain stdout → context) | PostToolUse, matcher Bash (requires additionalContext JSON) | Yes |
| Codex CLI | <repo>/.codex/hooks.json or ~/.codex/hooks.json, behind [features] codex_hooks = true in config.toml | UserPromptSubmit (plain stdout → developer context) | PostToolUse, matcher Bash (requires additionalContext JSON) | Yes |
| Copilot CLI / coding agent | .github/hooks/*.json (repo) or ~/.copilot/hooks/*.json (personal) | userPromptSubmitted (output ignored) | postToolUse, no matcher (output ignored) | No — hooks are logging/policy only; use .github/copilot-instructions.md for the reminder |
error-detector.sh handles the payload differences itself: it reads tool_response (Claude Code / Codex) or toolResult.textResultForLlm plus resultType (Copilot), filters to shell tools in-script for agents without matchers, and emits the reminder as hookSpecificOutput.additionalContext JSON — a shape Claude Code and Codex both accept, and Copilot safely ignores.
Install Location and Paths
The hook command must point at where the skill is actually installed:
| Install method | Script location |
|---|---|
gh skill install / npx skills add | .claude/skills/self-improvement/scripts/ |
| Plugin bundle (Claude Code) | ${CLAUDE_PLUGIN_ROOT}/skills/self-improvement/scripts/ (plugin hooks only) |
| Repo vendored into project | skills/self-improvement/scripts/ |
For Claude Code, anchor project-relative paths with ${CLAUDE_PROJECT_DIR} — it expands to the project root regardless of working directory. Codex runs hook commands from the session cwd, which may be a subdirectory; resolve from the git root ($(git rev-parse --show-toplevel)/...) or use home-anchored paths.
Claude Code Setup
Create .claude/settings.json in your project root (path shown for a gh skill install layout — adjust per the table above):
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/skills/self-improvement/scripts/activator.sh"
}
]
}
],
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/skills/self-improvement/scripts/error-detector.sh"
}
]
}
]
}
}Notes:
matcherfilters by tool name and applies to tool events likePostToolUse.UserPromptSubmitdoes not support matchers — it fires on every prompt.- For user-level activation, put the same structure in
~/.claude/settings.jsonwith~/.claude/skills/...paths. - For lower overhead, register only the UserPromptSubmit hook.
Codex CLI Setup
Codex supports lifecycle hooks (experimental, currently not on Windows). Enable the feature flag in ~/.codex/config.toml:
[features]
codex_hooks = trueThen create <repo>/.codex/hooks.json (loads when the project .codex/ layer is trusted) or ~/.codex/hooks.json:
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "\"$(git rev-parse --show-toplevel)/.claude/skills/self-improvement/scripts/activator.sh\""
}
]
}
],
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "\"$(git rev-parse --show-toplevel)/.claude/skills/self-improvement/scripts/error-detector.sh\"",
"statusMessage": "Checking for command errors"
}
]
}
]
}
}Notes:
- Codex's
UserPromptSubmitadds plain stdout as developer context, soactivator.shworks unchanged. - Codex's
PostToolUseignores plain stdout but accepts the samehookSpecificOutput.additionalContextJSON shape as Claude Code, whicherror-detector.shemits. - Adjust the script path to your install layout (the example assumes the skill is installed under
.claude/skills/).
GitHub Copilot Setup
Copilot supports hooks in .github/hooks/*.json (repo-wide) or ~/.copilot/hooks/*.json (Copilot CLI personal), but hook output is ignored for userPromptSubmitted and postToolUse — hooks can log and enforce policy, not inject context. So for Copilot:
1. Keep the reminder in .github/copilot-instructions.md (this is the only channel that reaches the model):
## Self-Improvement
After completing tasks that involved:
- Debugging non-obvious issues
- Discovering workarounds
- Learning project-specific patterns
- Resolving unexpected errors
Consider logging the learning to `.learnings/` using the format from the self-improvement skill.
For high-value learnings that would benefit other sessions, consider skill extraction.2. Optionally register the detector for audit logging (its JSON output is discarded, which is harmless):
{
"version": 1,
"hooks": {
"postToolUse": [
{ "type": "command", "bash": "./.claude/skills/self-improvement/scripts/error-detector.sh" }
]
}
}Verification
Test Activator Hook (Claude Code / Codex)
1. Enable the hook configuration 2. Start a new session 3. Send any prompt 4. Verify you see <self-improvement-reminder> in the context
Test Error Detector Hook
Standalone test with a fake Claude Code / Codex payload:
echo '{"tool_name":"Bash","tool_response":"ls: /nonexistent/path: No such file or directory"}' \
| ./scripts/error-detector.shAnd with a fake Copilot payload (tool filter + failure path):
echo '{"toolName":"bash","toolResult":{"resultType":"failure","textResultForLlm":"npm ERR! missing script"}}' \
| ./scripts/error-detector.shExpected: a JSON object containing additionalContext in both cases. In a live Claude Code or Codex session the reminder reaches the model on the next turn as injected context, not as visible transcript output.
Dry Run Extract Script
./scripts/extract-skill.sh test-skill --dry-runExpected output shows the skill scaffold that would be created.
Troubleshooting
Hook Not Triggering
1. Check script permissions: chmod +x scripts/*.sh 2. Verify path: confirm the path matches your install method (see Install Location and Paths) and is anchored (${CLAUDE_PROJECT_DIR}, git root, or absolute) 3. Codex only: confirm codex_hooks = true is set and the project .codex/ layer is trusted 4. Check settings location: project vs user-level 5. Restart session: hooks are loaded at session start
Permission Denied
chmod +x scripts/activator.sh scripts/error-detector.sh scripts/extract-skill.shToo Much Overhead
Use the minimal setup (prompt-submit hook only), or edit activator.sh to output less text. Prompt-content filtering is not possible on any of the three agents: none of them support matchers on the prompt-submit event.
Hook Output Budget
The activator is designed to be lightweight:
- Target: ~50-100 tokens per activation
- Content: Structured reminder, not verbose instructions
- Format: XML tags for easy parsing
Security Considerations
- Hook scripts run with the agent's permissions
- The scripts only read the stdin payload and write text/JSON to stdout; they don't modify files or run project commands
- All hooks are opt-in (you must configure them explicitly)
- Codex project-local hooks only load when the project
.codex/layer is trusted
Disabling Hooks
Remove the relevant event key from the hooks config file, or delete the file. JSON does not support comments, so "commenting out" a section will break parsing of the whole file.
OpenClaw Integration Guide
Complete setup and usage guide for integrating the self-improvement skill with OpenClaw's distributed learning model.
Overview
OpenClaw is a terminal-based AI coding assistant that uses workspace-based prompt injection. Unlike Claude Code's hook system, OpenClaw injects context from workspace files at session start and supports inter-agent communication.
Architecture Comparison
| Feature | Claude Code | OpenClaw |
|---|---|---|
| Learning storage | .learnings/ in project | Workspace files (~/clawd/) |
| Activation | Hooks (UserPromptSubmit) | Workspace injection at start |
| Promotion targets | CLAUDE.md, AGENTS.md | SOUL.md, TOOLS.md, AGENTS.md |
| Inter-agent comms | Not built-in | sessions_* tools |
| Skill registry | Manual / agentskills.io | ClawdHub integration |
Workspace Setup
Default Structure
~/clawd/ # Configurable via ~/.openclaw/openclaw.json
├── AGENTS.md # Multi-agent coordination patterns
├── SOUL.md # Behavioral guidelines and personality
├── TOOLS.md # Tool capabilities and MCP gotchas
├── skills/ # ClawdHub skills cache
│ └── <skill-name>/
│ └── SKILL.md
└── sessions/ # Auto-managed session transcripts
└── <session-id>.jsonlConfiguration
Edit ~/.openclaw/openclaw.json:
{
"workspace": "~/clawd",
"model": "claude-sonnet-4-20250514",
"inject_files": ["AGENTS.md", "SOUL.md", "TOOLS.md"],
"session_history": true
}Injected Prompt Files
AGENTS.md
Purpose: Multi-agent workflows and delegation patterns.
# Agent Coordination
## Delegation Rules
- Use explore agent for open-ended codebase questions
- Use research-agent for external documentation lookup
- Use Plan agent before complex implementations
## Session Handoff
When delegating to another session:
1. Provide full context in the handoff message
2. Include relevant file paths
3. Specify expected output formatSOUL.md
Purpose: Behavioral guidelines and communication style.
# Behavioral Guidelines
## Communication Style
- Be direct and concise
- Avoid unnecessary caveats and disclaimers
- Use technical language appropriate to context
## Decision Making
- Prefer simple solutions over clever ones
- Ask clarifying questions early
- Explain trade-offs when presenting options
## Error Handling
- Admit mistakes promptly
- Provide corrected information immediately
- Log significant errors to learningsTOOLS.md
Purpose: Tool capabilities, MCP server knowledge, integration gotchas.
# Tool Knowledge
## MCP Servers
### atlassian
- Use `search` for general queries across Jira/Confluence
- Only use `searchJiraIssuesUsingJql` when JQL syntax is explicitly needed
- CloudId can be extracted from URLs (tool handles conversion)
- Page IDs are in URL path: `/pages/123456789/`
### leanix
- Use external_id (not internal id) for lookups
- expand_teams/expand_apps for nested data
## Built-in Tools
### Bash
- Prefer specialized tools over bash (Read over cat, Glob over find)
- Use for git operations, npm/pnpm, docker commands
### Task
- Use explore agent for codebase questions
- Use research-agent for external docsLearning Workflow
Capturing Learnings
1. In-session: Log to .learnings/ as usual (project-specific) 2. Cross-project: Promote to workspace files (openclaw)
Promotion Decision Tree
Is the learning project-specific?
├── Yes → Promote to CLAUDE.md or .learnings/
└── No → Is it behavioral/style-related?
├── Yes → Promote to SOUL.md
└── No → Is it tool/MCP-related?
├── Yes → Promote to TOOLS.md
└── No → Promote to AGENTS.md (workflow)Promotion Format Examples
From learning:
MCP atlassian server: search tool is for general queries. Only use JQL/CQL tools when user explicitly mentions JQL or CQL syntax.
To TOOLS.md:
### atlassian
- `search`: Use for general queries (default)
- `searchJiraIssuesUsingJql`: Only when JQL explicitly requested
- `searchConfluenceUsingCql`: Only when CQL explicitly requestedInter-Agent Communication
OpenClaw provides tools for cross-session communication:
sessions_list
View active and recent sessions:
sessions_list --active
sessions_list --recent 10sessions_history
Read transcript from another session:
sessions_history --session <session-id> --last 50sessions_send
Send message to another session:
sessions_send --to <session-id> --message "Learning: API requires X-Custom-Header"Learning Sharing Pattern
When discovering something valuable in session A:
1. Check if other sessions are working on related code:
sessions_list --active2. Share the learning:
sessions_send --to session-b --message "FYI: Discovered that the auth API requires refresh tokens every 30min"3. Log to workspace file if broadly applicable:
- Edit
~/clawd/TOOLS.mdor appropriate file
ClawdHub Integration
ClawdHub is OpenClaw's skill registry (similar to agentskills.io).
Installing Skills
clawd skill install <skill-name>Skills are cached in ~/clawd/skills/.
Publishing Skills
1. Create skill following agentskills.io spec 2. Register with ClawdHub 3. Skills become available to all OpenClaw users
Skill Compatibility
Skills from this repo are compatible with:
- Claude Code (via hooks)
- Codex CLI (via hooks)
- OpenClaw (via ClawdHub)
- GitHub Copilot (via manual setup)
Hybrid Setup: Claude Code + OpenClaw
When using both tools on the same codebase:
Recommended Division
| Concern | Where to Store |
|---|---|
| Project conventions | CLAUDE.md (in repo) |
| Project learnings | .learnings/ (in repo) |
| Personal preferences | SOUL.md (openclaw workspace) |
| Tool knowledge | TOOLS.md (openclaw workspace) |
| Cross-project workflows | AGENTS.md (openclaw workspace) |
Sync Strategy
High-value learnings should exist in both:
1. Log to .learnings/ first (project context) 2. If broadly applicable, also add to openclaw workspace 3. Use consistent formatting for easy grep
Example Dual Promotion
Learning: "Playwright tests require --headed flag for debugging"
In `.learnings/LEARNINGS.md`:
## [LRN-20250126-001] correction
**Status**: promoted
**Promoted**: CLAUDE.md, TOOLS.md (openclaw)
### Summary
Playwright tests require --headed flag for visual debugging
### Details
...In `CLAUDE.md`:
## Testing
- Playwright debugging: use `--headed` flagIn `~/clawd/TOOLS.md`:
## Playwright
- Debug mode: `npx playwright test --headed`
- Trace viewer: `npx playwright show-trace trace.zip`Detection Triggers for OpenClaw
Standard Triggers (same as Claude Code)
- User corrections
- Command failures
- API errors
- Knowledge gaps
OpenClaw-Specific Triggers
| Trigger | Action |
|---|---|
| MCP server error | Log to TOOLS.md with server name |
| Session handoff confusion | Log to AGENTS.md with delegation pattern |
| Model behavior surprise | Log to SOUL.md with expected vs actual |
| ClawdHub skill issue | Log to TOOLS.md or report upstream |
Troubleshooting
Workspace files not injected
Check ~/.openclaw/openclaw.json:
- Verify
workspacepath exists - Verify
inject_filesincludes desired files
Session communication fails
- Verify target session is active:
sessions_list --active - Check session ID is correct
- Session may have ended
Learning not persisting
OpenClaw doesn't auto-persist learnings. You must: 1. Explicitly write to workspace files 2. Or use .learnings/ for project-specific storage
#!/bin/bash
# Self-Improvement Activator Hook
# Triggers on UserPromptSubmit to remind Claude about learning capture
# Keep output minimal (~50-100 tokens) to minimize overhead
set -e
# Output reminder as system context
cat << 'EOF'
<self-improvement-reminder>
After completing this task, evaluate if extractable knowledge emerged:
- Non-obvious solution discovered through investigation?
- Workaround for unexpected behavior?
- Project-specific pattern learned?
- Error required debugging to resolve?
If yes: Log to .learnings/ using the self-improvement skill format.
If high-value (recurring, broadly applicable): Consider skill extraction.
</self-improvement-reminder>
EOF
#!/bin/bash
# Self-Improvement Error Detector Hook (agent-agnostic)
#
# Post-tool-use hook for Bash/shell commands. Supported agents:
# - Claude Code (PostToolUse, matcher "Bash"): payload field `tool_response`
# - Codex CLI (PostToolUse, matcher "Bash"): payload field `tool_response`
# - Copilot CLI (postToolUse, no matcher): payload field `toolResult.textResultForLlm`
#
# All three agents send the hook payload as JSON on stdin. There is no
# CLAUDE_TOOL_OUTPUT environment variable.
#
# Output channel differs by agent:
# - Claude Code and Codex CLI: plain stdout from a post-tool hook is NOT
# shown to the model; the reminder must be returned as JSON
# `hookSpecificOutput.additionalContext`. Both agents accept the same shape.
# - Copilot CLI: hook output is ignored entirely (context injection is not
# supported); error-capture guidance must live in
# `.github/copilot-instructions.md` instead. This script is still safe to
# register there: the JSON output is silently discarded.
set -e
INPUT=$(cat)
json_extract() {
# $1 = jq expression, $2 = python fallback statement (uses dict `d`)
if command -v jq >/dev/null 2>&1; then
printf '%s' "$INPUT" | jq -r "$1" 2>/dev/null || true
elif command -v python3 >/dev/null 2>&1; then
printf '%s' "$INPUT" | python3 -c '
import sys, json
try:
d = json.load(sys.stdin)
exec(sys.argv[1])
except Exception:
pass
' "$2" 2>/dev/null || true
fi
}
# Copilot's postToolUse has no matcher and fires for every tool; filter to
# shell commands in-script. Claude Code / Codex are already filtered by the
# "Bash" matcher, so this check just passes through.
TOOL_NAME=$(json_extract '.tool_name // .toolName // ""' 'print(d.get("tool_name") or d.get("toolName") or "")')
if [ -n "$TOOL_NAME" ] && ! printf '%s' "$TOOL_NAME" | grep -qiE '^bash$|^shell$'; then
exit 0
fi
# Extract the tool output text across payload shapes.
OUTPUT=$(json_extract '(.tool_response // .toolResult.textResultForLlm // "") | tostring' 'print(json.dumps(d.get("tool_response") or (d.get("toolResult") or {}).get("textResultForLlm") or ""))')
[ -n "$OUTPUT" ] || OUTPUT="$INPUT"
# Copilot reports failures explicitly; treat that as a direct signal.
RESULT_TYPE=$(json_extract '.toolResult.resultType // ""' 'print((d.get("toolResult") or {}).get("resultType") or "")')
# Patterns indicating errors
ERROR_PATTERNS=(
"error:"
"Error:"
"ERROR:"
"failed"
"FAILED"
"command not found"
"No such file"
"Permission denied"
"fatal:"
"Exception"
"Traceback"
"npm ERR!"
"ModuleNotFoundError"
"SyntaxError"
"TypeError"
"exit code"
"non-zero"
)
contains_error=false
if [ "$RESULT_TYPE" = "failure" ]; then
contains_error=true
else
for pattern in "${ERROR_PATTERNS[@]}"; do
if [[ "$OUTPUT" == *"$pattern"* ]]; then
contains_error=true
break
fi
done
fi
# Emit the reminder as additionalContext JSON. Claude Code and Codex CLI both
# accept this exact shape for post-tool hooks; Copilot ignores it.
if [ "$contains_error" = true ]; then
cat << 'EOF'
{
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "<error-detected>\nA command error was detected. Consider logging this to .learnings/ERRORS.md if:\n- The error was unexpected or non-obvious\n- It required investigation to resolve\n- It might recur in similar contexts\n- The solution could benefit future sessions\n\nUse the self-improvement skill format: [ERR-YYYYMMDD-XXX]\n</error-detected>"
}
}
EOF
fi
#!/bin/bash
# Skill Extraction Helper
# Creates a new skill from a learning entry
# Usage: ./extract-skill.sh <skill-name> [--dry-run]
set -e
# Configuration
SKILLS_DIR="${SKILLS_DIR:-./skills}"
TEMPLATE_DIR="$(dirname "$0")/../assets"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
usage() {
cat << EOF
Usage: $(basename "$0") <skill-name> [options]
Create a new skill from a learning entry.
Arguments:
skill-name Name of the skill (lowercase, hyphens for spaces)
Options:
--dry-run Show what would be created without creating files
--output-dir Override skills directory (default: ./skills)
-h, --help Show this help message
Examples:
$(basename "$0") docker-m1-fixes
$(basename "$0") api-timeout-patterns --dry-run
$(basename "$0") pnpm-setup --output-dir /path/to/skills
The skill will be created in: \$SKILLS_DIR/<skill-name>/
EOF
}
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1" >&2
}
# Parse arguments
SKILL_NAME=""
DRY_RUN=false
while [[ $# -gt 0 ]]; do
case $1 in
--dry-run)
DRY_RUN=true
shift
;;
--output-dir)
SKILLS_DIR="$2"
shift 2
;;
-h|--help)
usage
exit 0
;;
-*)
log_error "Unknown option: $1"
usage
exit 1
;;
*)
if [ -z "$SKILL_NAME" ]; then
SKILL_NAME="$1"
else
log_error "Unexpected argument: $1"
usage
exit 1
fi
shift
;;
esac
done
# Validate skill name
if [ -z "$SKILL_NAME" ]; then
log_error "Skill name is required"
usage
exit 1
fi
# Validate skill name format (lowercase, hyphens, no spaces)
if ! [[ "$SKILL_NAME" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then
log_error "Invalid skill name format. Use lowercase letters, numbers, and hyphens only."
log_error "Examples: 'docker-fixes', 'api-patterns', 'pnpm-setup'"
exit 1
fi
SKILL_PATH="$SKILLS_DIR/$SKILL_NAME"
# Check if skill already exists
if [ -d "$SKILL_PATH" ] && [ "$DRY_RUN" = false ]; then
log_error "Skill already exists: $SKILL_PATH"
log_error "Use a different name or remove the existing skill first."
exit 1
fi
# Dry run output
if [ "$DRY_RUN" = true ]; then
log_info "Dry run - would create:"
echo " $SKILL_PATH/"
echo " $SKILL_PATH/SKILL.md"
echo ""
echo "Template content would be:"
echo "---"
cat << TEMPLATE
name: $SKILL_NAME
description: "[TODO: Add a concise description of what this skill does and when to use it]"
---
# $(echo "$SKILL_NAME" | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2))}1')
[TODO: Brief introduction explaining the skill's purpose]
## Quick Reference
| Situation | Action |
|-----------|--------|
| [Trigger condition] | [What to do] |
## Usage
[TODO: Detailed usage instructions]
## Examples
[TODO: Add concrete examples]
## Source Learning
This skill was extracted from a learning entry.
- Learning ID: [TODO: Add original learning ID]
- Original File: .learnings/LEARNINGS.md
TEMPLATE
echo "---"
exit 0
fi
# Create skill directory structure
log_info "Creating skill: $SKILL_NAME"
mkdir -p "$SKILL_PATH"
# Create SKILL.md from template
cat > "$SKILL_PATH/SKILL.md" << TEMPLATE
---
name: $SKILL_NAME
description: "[TODO: Add a concise description of what this skill does and when to use it]"
---
# $(echo "$SKILL_NAME" | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2))}1')
[TODO: Brief introduction explaining the skill's purpose]
## Quick Reference
| Situation | Action |
|-----------|--------|
| [Trigger condition] | [What to do] |
## Usage
[TODO: Detailed usage instructions]
## Examples
[TODO: Add concrete examples]
## Source Learning
This skill was extracted from a learning entry.
- Learning ID: [TODO: Add original learning ID]
- Original File: .learnings/LEARNINGS.md
TEMPLATE
log_info "Created: $SKILL_PATH/SKILL.md"
# Suggest next steps
echo ""
log_info "Skill scaffold created successfully!"
echo ""
echo "Next steps:"
echo " 1. Edit $SKILL_PATH/SKILL.md"
echo " 2. Fill in the TODO sections with content from your learning"
echo " 3. Add references/ folder if you have detailed documentation"
echo " 4. Add scripts/ folder if you have executable code"
echo " 5. Update the original learning entry with:"
echo " **Status**: promoted_to_skill"
echo " **Skill-Path**: skills/$SKILL_NAME"