{
  "markdown": "# lesson-skill-loop\n\nTurn your development lessons into reusable skills — automatically.\n\n**[日本語版 README](README.ja.md)**\n\n## What It Does\n\nDevelopers accumulate lessons from bugs, incidents, and mistakes. These lessons sit in markdown files and are rarely revisited. This tool closes the loop:\n\n```\nLessons (past mistakes) → Analysis → Skill proposals → Skills (checklists)\n                                                            ↓\n                                                       Skills used\n                                                            ↓\n                                                       New lessons\n                                                            ↓\n                                                   Skill improvements\n```\n\n## Quick Start\n\n```bash\n# Run directly with npx (no install needed)\nnpx claude-skill-loop examples/lessons\n\n# Or install globally\nnpm install -g claude-skill-loop\nclaude-skill-loop /path/to/your/lessons\n```\n\n## Modes\n\n### Analysis (CLI)\n\n| Mode | Command | What it does |\n|------|---------|-------------|\n| **Analyze** | `claude-skill-loop [dir]` | Count tags, propose skills for patterns appearing 3+ times |\n| **Sync** | `claude-skill-loop --sync [dir]` | Compare existing skills with lessons, find unreflected entries |\n| **Health** | `claude-skill-loop --health [dir]` | Check skill freshness and evidence strength |\n| **Map** | `claude-skill-loop --map [dir]` | Full traceability: which lessons back which skills (with full text) |\n| **All** | `claude-skill-loop --all [dir]` | Run all modes |\n\n### Recording (Skill — works in Cowork)\n\n| Command | What it does |\n|---------|-------------|\n| `/lesson [tag] description` | Record a lesson with tags |\n| `/lesson list` | Show all recorded lessons |\n| `/lesson tags` | Show tag frequency summary |\n| `/lesson search keyword` | Search lessons by keyword |\n\nRecord lessons during work, then analyze with `/skill-loop` to close the feedback loop.\n\n## Options\n\n| Option | Description |\n|--------|-------------|\n| `--json` | Output in JSON format (for scripting / CI integration) |\n| `--dir <path>` | Specify lessons directory (alternative to positional arg) |\n| `--skills-dir <path>` | Specify skills directory |\n| `--for <path>` | **(v2.3.0+)** Filter lessons by stack detected in `<path>`. See \"Stack-aware filtering\" below. |\n| `--merge-twice` | **(v2.4.0+)** Detect duplicate-theme lesson candidates that should be merged. See \"Merge-twice detection\" below. |\n| `--days <n>` | **(v2.4.0+)** New-lesson window for `--merge-twice` mode, default: `30` (days, by mtime). |\n| `--threshold <n>` | Skill proposal threshold, default: `3` |\n\n## Stack-aware filtering (`--for`, v2.3.0+)\n\n`--for <project-path>` detects the technology stack in the target project and shows only lessons relevant to the detected stack. This lets you surface \"past failures that matter for *this* project\" — complementary to tools like `autoskills` that push *generic* skills.\n\n```bash\n# Show only lessons tagged with technologies detected in ./my-next-app\nclaude-skill-loop --for ./my-next-app ~/.claude/lessons\n\n# Combine with any mode\nclaude-skill-loop --all --for ./my-rust-service ~/.claude/lessons\n```\n\n**Supported manifests (v2.3.0)**: `package.json`, `requirements.txt`, `pyproject.toml`, `Pipfile`, `Cargo.toml`, `go.mod`, `Gemfile`, `composer.json`. Top-level only; monorepos are not supported in v2.3.0.\n\n**Path semantics**: Relative paths are resolved from the current working directory. The target must be a directory — passing a file will exit with an error.\n\n**Framework hierarchy**: Parent frameworks are automatically included. For example, a Next.js project also matches `[react]` lessons; a Nuxt project also matches `[vue]` lessons.\n\n**Output**: In `--json` mode, a `stack` field is added at top level **only when `--for` is specified**:\n\n```json\n{\n  \"mode\": \"analyze\",\n  \"tags\": [...],\n  \"stack\": {\n    \"projectDir\": \"/abs/path/to/project\",\n    \"languages\": [\"javascript\"],\n    \"technologies\": [\"react\", \"next\", \"typescript\"],\n    \"sources\": [\"package.json\"],\n    \"hardTags\": [\"[react]\", \"[next]\", \"[nextjs]\", \"[typescript]\", \"[javascript]\"],\n    \"softTags\": [\"[hooks]\", \"[ssr]\", \"[frontend]\", \"[types]\"],\n    \"errors\": []\n  }\n}\n```\n\nWhen `--for` is not specified, the JSON output is byte-for-byte identical to v2.2.x.\n\n## Merge-twice detection (`--merge-twice`, v2.4.0+)\n\n`--merge-twice` detects pairs of lessons that cover the same theme and should be merged into a single lesson file. Inspired by the \"twice-fire merge\" concept from [`claude-smart`](https://github.com/ReflexioAI/claude-smart) — when a lesson is recorded twice on the same theme, it's a signal to consolidate.\n\n```bash\n# Detect merge candidates in the lessons directory\nclaude-skill-loop --merge-twice ~/.claude/lessons\n\n# Tighten the new-lesson window to the last 7 days\nclaude-skill-loop --merge-twice --days 7 ~/.claude/lessons\n\n# Machine-readable JSON output\nclaude-skill-loop --merge-twice --json ~/.claude/lessons\n```\n\n**Detection rule**: A pair is flagged as same-theme if **both** conditions hold:\n1. **Shared primary tag**: at least 1 category tag matches (category tags are derived dynamically from `dev-lessons.md`, with fallback to the union of all `[tag]` entries).\n2. **Keyword Jaccard ≥ 0.20**: keyword sets are extracted from title + first H2 section body, using ASCII-alphanumeric tokens + contiguous CJK spans.\n\n**Scope**: All `(new × new) ∪ (new × existing)` pairs, where \"new\" = mtime within the last `--days` window (default 30).\n\n**Output (text mode)**:\n```\n🔗 統合候補検出 (--merge-twice、直近 30 日 vs 既存)\n================================================\nカテゴリタグ集合: 69 件\n新規 lesson: 21 件 / 全 lesson: 25 件\n\n✅ 統合候補なし\n   閾値: 主タグ一致 >= 1 AND キーワード Jaccard >= 0.2\n```\n\n**Dry-run only**: This release surfaces candidates but does not modify any files. Use the output to decide which lessons to merge manually. `--execute` mode for real merge is **available since v2.4.5** (see the Phase 2 section below).\n\n**v2.4.1 improvements** (current release): keyword extraction now also picks up contiguous **katakana spans** (2+ chars), so Japanese short-text lesson pairs reach the 0.20 threshold more reliably. **Shared category tags** are also included in the Jaccard numerator and denominator (with a `tag:` prefix to avoid keyword collisions).\n\n**Known limitations (still open)**:\n- `--merge-twice` and `--for <project>` are **independent**: when used together, `--for` filtering applies to the other modes (`--analyze` / `--sync` / `--health` / `--map`) but **not** to `--merge-twice`'s pair detection. `--merge-twice` always scans the full `LESSON_FILES` set, regardless of `--for`.\n\n## Apply merge-plan.json (`--apply-plan`, v2.4.4+, Phase 1)\n\n`--apply-plan <path>` reads a `merge-plan.json` (written by `--merge-twice --execute`) and outputs a **dry-run summary** of how each candidate would be processed. Each `candidate.action` field (`merge` / `skip` / `ignore`) is counted and listed.\n\n**Phase 1 (this section)**: validation and summary only — **no files are modified**. Actual merge execution and rollback are implemented in **v2.4.5+ (Phase 2)** — see the next section.\n\n```bash\n# 1) Generate merge-plan.json from candidates\nclaude-skill-loop --merge-twice --execute --no-version-check\n\n# 2) Edit each candidate's \"action\" field manually (TBD → merge / skip / ignore)\n$EDITOR merge-plan.json\n\n# 3) Dry-run the plan to see what would happen\nclaude-skill-loop --apply-plan ./merge-plan.json\n\n# JSON output for CI\nclaude-skill-loop --apply-plan ./merge-plan.json --json\n```\n\nExample output:\n\n```\n📋 merge-plan.json を読み込みました (./merge-plan.json)\n   version: 2.4.3\n   generated_at: 2026-05-24T08:00:00.000Z\n   totalCandidates: 3\n\n📊 サマリ:\n   merge: 1 件\n   skip: 1 件\n   ignore: 1 件\n\n📝 merge 対象 (1 件):\n   1. lessons/recent.md ⇐ lessons/old.md (jaccard: 0.42)\n\n⚠️  これは dry-run です。実マージは --execute で実行可能 (v2.4.5+)。\n```\n\n**Validation rules**:\n- `candidates[].action` must be one of `merge` / `skip` / `ignore`. **`TBD` is rejected** (forces manual review).\n- Missing required fields (`version`, `candidates`, `newFile`, `existingFile`, `action`) → exit code 1.\n- Malformed JSON or missing file → exit code 1.\n\n**Why phased**: actual merge involves destructive file operations (append / delete / git commit). Phase 1 locks the JSON schema and validation so Phase 2 can safely build on top without re-architecting.\n\n## Execute and Rollback merge-plan.json (`--apply-plan --execute` / `--rollback-plan`, v2.4.5+, Phase 2)\n\n`v2.4.5` adds **actual merge execution** and **rollback** support on top of Phase 1's dry-run.\n\n### Execute (`--apply-plan --execute`)\n\n```bash\n# 1) Generate merge-plan.json and edit each candidate's \"action\" (same as Phase 1)\nclaude-skill-loop --merge-twice --execute --no-version-check\n$EDITOR merge-plan.json\n\n# 2) Execute the merge (destructive!)\nclaude-skill-loop --apply-plan ./merge-plan.json --execute\n```\n\nFor each `candidate.action === 'merge'`:\n- `existingFile` is backed up to `./.apply-plan-backup/{stamp}/backup/{uuid}.md`\n- `newFile` is moved to `./.apply-plan-backup/{stamp}/moved/{uuid}.md`\n- `newFile` content is appended to `existingFile` with separator `\\n\\n---\\n\\n`\n- A `restore-manifest.json` is written into the same backup directory\n\n`skip` / `ignore` actions are logged but no files are modified.\n\n### Rollback (`--rollback-plan`)\n\n```bash\n# Restore the state before --execute (uses the backup directory created above)\nclaude-skill-loop --rollback-plan ./.apply-plan-backup/20260524_220530_847_12345\n```\n\nRollback restores every `existingFile` and `newFile` to its original content using the backup. The manifest's `rolled_back_at` field is updated, and **the same backup directory cannot be rolled back twice** (exit 1 on retry).\n\n### Recommended `.gitignore`\n\nThe backup directory contains lessons content snapshots; do not commit it.\n\n```gitignore\n.apply-plan-backup/\n```\n\n### Safety\n\n- `--apply-plan` and `--rollback-plan` cannot be combined with each other or with `--sync` / `--health` / `--map` / `--all` / `--merge-twice` (exit 1).\n- Manifest `version: \"1.0\"` allows future migration.\n- Paths in `merge-plan.json` are normalised to absolute paths at execute time, so rollback works regardless of CWD.\n\n## Lesson File Format\n\nLessons are markdown files with tagged headings:\n\n```markdown\n### Rate Limiting `[api]` `[auth]`\n- **Always check rate limit headers**: X-RateLimit-Remaining tells you...\n- **Implement exponential backoff**: Start at 1s, double each retry...\n```\n\nTags in `[brackets]` are the key. When the same tag appears in 3+ headings, the tool proposes creating a skill (checklist) for that pattern.\n\n## Skill Format\n\nSkills are Claude Code compatible checklists:\n\n```markdown\n---\nname: api-checklist\ndescription: API integration checklist based on past lessons.\n---\n\n# API Integration Checklist\n\n- [ ] **Rate limit handling**: Check X-RateLimit-Remaining\n- [ ] **API keys in env vars**: No hardcoded secrets\n```\n\nSkills named `*-checklist` are automatically detected by `--sync` and `--health`.\n\n## Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `LESSON_SKILL_LESSONS_DIR` | `./examples/lessons` | Path to lesson files (single directory) |\n| `LESSON_SKILL_SCAN_PATHS` | (uses `LESSONS_DIR`) | Comma-separated paths to scan (files and/or directories) |\n| `LESSON_SKILL_SKILLS_DIR` | `~/.claude/skills` | Path to skill directories |\n| `CLAUDE_SKILLS_DIR` | `~/.claude/skills` | Fallback for skills directory |\n\n### Multiple Scan Paths\n\nIf your lessons are spread across multiple files/directories, use `LESSON_SKILL_SCAN_PATHS`:\n\n```bash\n# Scan both a directory and a standalone file\nLESSON_SKILL_SCAN_PATHS=\"memory/lessons/,memory/dev-lessons.md\" claude-skill-loop\n\n# Scan multiple directories\nLESSON_SKILL_SCAN_PATHS=\"lessons/,retrospectives/,postmortems/\" claude-skill-loop\n```\n\nEach path can be a directory (scans `*.md` files) or a single `.md` file.\n\n## JSON Output\n\nUse `--json` for scripting or CI integration:\n\n```bash\nclaude-skill-loop --json --all examples/lessons | jq '.analyze.candidates'\n```\n\n## How It Works with Claude Code\n\n1. **You work** — bugs happen, lessons are recorded in `lessons/*.md` with tags\n2. **Run the tool** — `claude-skill-loop --all` shows what patterns repeat\n3. **Create skills** — use `/skill-creator` in Claude Code to turn proposals into skills\n4. **Skills improve** — `--sync` detects new lessons that should update existing skills\n5. **Skills retire** — `--health` flags skills with weak evidence or stale content\n\n### Register as a Slash Command\n\nCreate `~/.claude/commands/skill-loop.md` to use `/skill-loop` directly in Claude Code:\n\n```markdown\n# Lesson-Skill Feedback Loop\n\nRun the following command:\n\n\\`\\`\\`bash\nnpx claude-skill-loop --all --dir /path/to/your/lessons --skills-dir ~/.claude/skills\n\\`\\`\\`\n```\n\nThen in Claude Code:\n\n```\n/skill-loop          # Run all modes\n/skill-loop analyze  # Tag analysis only\n/skill-loop health   # Health check only\n```\n\n### Plugin Structure (commands/)\n\nThe `commands/` directory contains ready-to-use Claude Code slash command definitions:\n\n| File | Slash command | Description |\n|------|---------------|-------------|\n| `commands/skill-loop.md` | `/skill-loop` | Run all modes (analyze + sync + health + map) |\n| `commands/skill-loop-health.md` | `/skill-loop-health` | Health check only |\n| `commands/skill-loop-sync.md` | `/skill-loop-sync` | Sync check only |\n\nCopy any of these to `~/.claude/commands/` and customize the paths for your setup.\n\n## Claude Cowork Support\n\nThis tool also works in **Claude Cowork** (browser-based collaboration) where Bash is not available.\n\nThe `skills/skill-loop/SKILL.md` contains instructions for Claude to perform the same analysis using built-in tools (Read, Glob, Grep) instead of running Node.js. All four modes (analyze, sync, health, map) are supported.\n\n### Important limitation\n\nCowork can only access files within the current project. The skill works **only when lesson files (`lessons/*.md`) exist inside the project repository**. If your lessons are stored locally (e.g., `~/.claude/memory/lessons/`), use the CLI version (`npx claude-skill-loop`) instead.\n\n### Setup for Cowork\n\n#### 1. Clone or download\n\n```bash\ngit clone https://github.com/aliksir/lesson-skill-loop.git\n```\n\nOr download the ZIP from the [Releases](https://github.com/aliksir/lesson-skill-loop/releases) page.\n\n#### 2. Copy the skills to your Claude skills directory\n\n```bash\ncp -r lesson-skill-loop/skills/skill-loop ~/.claude/skills/\ncp -r lesson-skill-loop/skills/lesson ~/.claude/skills/\n```\n\nThis installs two skills:\n- `~/.claude/skills/skill-loop/SKILL.md` — analyze lessons and propose skills\n- `~/.claude/skills/lesson/SKILL.md` — record lessons with tags\n\n#### 3. Verify installation\n\nIn a Claude Cowork session, type:\n\n```\n/lesson [test] This is a test lesson\n/lesson list\n/skill-loop\n```\n\n#### 4. The full loop in Cowork\n\n```\n/lesson [api] Rate limit headers must be checked     ← Record\n/lesson [api] Always use exponential backoff          ← Record more\n/lesson tags                                          ← Check tag frequency\n/skill-loop                                           ← Analyze → skill candidates\n```\n\nNo lesson files needed upfront — `/lesson` creates `lessons/dev-lessons.md` automatically.\n\n### Cowork vs CLI comparison\n\n| Feature | CLI (`npx claude-skill-loop`) | Cowork (`/skill-loop`) |\n|---------|-------------------------------|------------------------|\n| Analyze mode | ✅ | ✅ |\n| Sync mode | ✅ | ✅ |\n| Health mode | ✅ | ✅ (file dates may show \"unknown\") |\n| Map mode | ✅ | ✅ |\n| JSON output | ✅ `--json` | ❌ (not needed in Cowork) |\n| Self-update | ✅ `--self-update` | ❌ (re-copy SKILL.md to update) |\n| Custom threshold | ✅ `--threshold N` | ❌ (fixed at 3) |\n| Speed | Fast (native Node.js) | Slower (Claude reads files one by one) |\n\n## Migrating from Bash version\n\nThe Bash version (`lesson-skill-check.sh`) was removed in v2.2.0. If you were using it, switch to the Node.js version — the commands are identical:\n\n```bash\n# Before (Bash)\nbash lesson-skill-check.sh --all\n\n# After (Node.js)\nclaude-skill-loop --all\n```\n\nAll flags (`--sync`, `--health`, `--map`, `--all`) work the same way. The Node.js version adds `--json`, `--threshold`, `--dir`, `--skills-dir`, and `--self-update`.\n\n## Requirements\n\n- Node.js 18+\n\n## Inspired By\n\n- [EvoSkill](https://arxiv.org/abs/2603.02766) — Automated skill discovery for multi-agent systems\n- [Neko Gundan](https://github.com/aliksir/neko-gundan) — Multi-agent orchestration for Claude Code\n\n## License\n\nMIT\n",
  "bytes": 16600,
  "sha": "4922a6bfff6bad9cf902f768414f23f0b16bc4e15f1759533fba79ee51c8a380",
  "repo_slug": "aliksir/lesson-skill-loop",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_aliksir_lesson_skill_loop_lesson_skill_l_b9f765c1/readme"
}