gem-skill 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -0
- data/README.md +55 -14
- data/docs/cache.md +82 -5
- data/docs/commands/bundle-skill.md +10 -3
- data/docs/commands/gem-skill.md +83 -6
- data/docs/configuration.md +37 -0
- data/docs/how-it-works.md +58 -9
- data/docs/index.md +15 -11
- data/docs/skill-files.md +73 -10
- data/lib/gem/skill/cache.rb +24 -0
- data/lib/gem/skill/cli/bundle_command.rb +46 -18
- data/lib/gem/skill/cli/gem_command.rb +158 -8
- data/lib/gem/skill/fetcher.rb +52 -0
- data/lib/gem/skill/frontmatter.rb +64 -0
- data/lib/gem/skill/generator.rb +1 -0
- data/lib/gem/skill/linker.rb +17 -3
- data/lib/gem/skill/runner.rb +69 -9
- data/lib/gem/skill/verifier.rb +136 -0
- data/lib/gem/skill/version.rb +1 -1
- data/lib/gem/skill.rb +12 -0
- data/ruby-gem-skills/SKILL.md +53 -0
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c425b88d925bd6ef993c1ea04581ffd0e457bebc9137cccf68cf3aacd6e00fde
|
|
4
|
+
data.tar.gz: ba39b45df96bc6f76c6b2ffa950a3a2cafbba4b7c0b2bfd94ecbd9cd4b38cd06
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7b4558c9312730d8d7218951591985d868db5bea5f4282f52702ad01feb5ec381c3cfe5af56cb9b50cfa5c45b58e5dbf54bbefee99d6c36d033598383977c35e
|
|
7
|
+
data.tar.gz: 7464f9cd590e6899ad7a4d2b5a464c42c054ce4287502625349f5cb438e3c66e53e4b56ab7291f8730404f9f9f9f4636a7412cf736a40f40e6dce9a94a5ff048
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,33 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
### Added
|
|
9
|
+
- Bundled `ruby-gem-skills` "router" skill (shipped at the gem root) that teaches assistants how to find cached gem skills in `~/.gem/skills` — a directory neither Claude Code nor Codex scans by default. `gem skill setup` now also copies this skill into each detected assistant's default root (`~/.claude/skills`, `~/.codex/skills`, `~/.agents/skills`), creating none that don't already exist. `Gem::Skill::ROUTER_SKILL_NAME` / `ROUTER_SKILL_DIR` locate the bundled template.
|
|
10
|
+
|
|
11
|
+
## [0.2.0] - 2026-06-19
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- `--verify` flag for `gem skill install` and `bundle skill install`/`refresh` — runs a second LLM pass that checks the generated skill's code against the gem's **actual source code** (the source of truth) and corrects mismatched method signatures, default argument values, visibility, return values, and behavioral claims. READMEs and docstrings are frequently stale; this catches it.
|
|
15
|
+
- `gem skill verify GEM_NAME [GEM_NAME ...]` subcommand — verify an already-cached skill in place (never generates; errors if the gem isn't installed or the skill isn't cached).
|
|
16
|
+
- `gem skill list` flags verified versions with a green checkmark (`✓`); unverified versions show no mark. The checkmark is colored only for interactive terminals.
|
|
17
|
+
- `GEMSKILL_PROJECT_DIR` env var (default `.claude/skills`) — controls the project-relative directory `bundle skill` writes symlinks into. Codex users can set it to `.agents` or `.codex` to link skills into a Codex project root.
|
|
18
|
+
- `Gem::Skill::Verifier` — the verification pass. Whether the skill changed is decided by a deterministic diff (not the model's self-report), so the result is trustworthy.
|
|
19
|
+
- `Gem::Skill::Frontmatter` — deterministic, idempotent frontmatter builder shared by the generator and verifier, so a skill always carries valid frontmatter even if the model omits it.
|
|
20
|
+
- `Fetcher#source_code` — concatenates the gem's `lib/**/*.rb` (size-capped) as the ground truth the verifier checks against.
|
|
21
|
+
- `Cache.read_metadata`, `Cache.write_skill`, `Cache.merge_metadata` — support verifying/rewriting a cached skill without clobbering `generated_at`/`model`/`sources`.
|
|
22
|
+
- Verified skills gain a `verification` block in `metadata.json` recording that the skill was checked against the gem's actual source: `verified`, `verified_at`, `model`, and `fixed` (whether the check changed anything). When no installed source is available to check against, it records `verified: false` with a `skipped_reason`.
|
|
23
|
+
- Exit status `2` (`Gem::Skill::EXIT_VERIFY_FIXED`) when `--verify` found and corrected problems, so CI can detect README/source drift. `0` = clean, `1` = error.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- `Runner.install_skill` now accepts `verify:` and returns a `Runner::Result` (`error`, `verify_fixed`) instead of a nil/error-string.
|
|
27
|
+
- Documentation reworded to be assistant-neutral: `SKILL.md` is a shared format read by Claude Code, OpenAI Codex, and other AI coding assistants. Added guidance for pointing non-Claude assistants (e.g. Codex's `~/.codex/skills`, the vendor-neutral `~/.agents/skills`) at the shared cache. `bundle skill` still links into `.claude/skills/` (Claude Code's convention).
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
- Generated `SKILL.md` files now include the required YAML frontmatter (`name` + `description`). Without it, the files were never registered/triggered as skills by Claude Code or OpenAI Codex — they were just markdown in a skills folder. `name` is the gem name normalized to hyphen-case (e.g. `ruby_llm` → `ruby-llm`); `description` is a trigger-oriented one-liner derived from the Overview (sanitized for both assistants: single line, no angle brackets). Verified against Claude Code's skill validator and OpenAI's Codex skill spec.
|
|
31
|
+
|
|
32
|
+
### Note
|
|
33
|
+
- Skills cached before this change lack frontmatter; regenerate them with `gem skill install GEM --force` (or `bundle skill refresh --force`) to add it.
|
|
34
|
+
|
|
8
35
|
## [0.1.3] - 2026-06-17
|
|
9
36
|
|
|
10
37
|
### Added
|
data/README.md
CHANGED
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
<tr>
|
|
6
6
|
<td width="40%"><img src="docs/assets/images/gem-skill.jpg" alt="gem-skill logo" width="100%"></td>
|
|
7
7
|
<td width="60%">
|
|
8
|
-
Generate
|
|
9
|
-
|
|
10
|
-
can share the
|
|
8
|
+
Generate <code>SKILL.md</code> files for AI coding assistants
|
|
9
|
+
(Claude Code, OpenAI Codex, and others) from Ruby gem documentation,
|
|
10
|
+
and cache them globally so every project that uses a gem can share the
|
|
11
|
+
same pre-built knowledge.<br><br>
|
|
11
12
|
<strong><a href="https://madbomber.github.io/gem-skill">Full documentation →</a></strong>
|
|
12
13
|
</td>
|
|
13
14
|
</tr>
|
|
@@ -16,14 +17,15 @@
|
|
|
16
17
|
|
|
17
18
|
## The problem it solves
|
|
18
19
|
|
|
19
|
-
Every time
|
|
20
|
-
re-reads the README, scans examples, and figures out the API. That
|
|
21
|
-
and time — and the result evaporates when the conversation ends.
|
|
20
|
+
Every time an AI coding assistant encounters a gem it hasn't seen in the current
|
|
21
|
+
context, it re-reads the README, scans examples, and figures out the API. That
|
|
22
|
+
costs tokens and time — and the result evaporates when the conversation ends.
|
|
22
23
|
|
|
23
24
|
`gem-skill` runs that pipeline once, offline, and stores the output as a
|
|
24
|
-
`SKILL.md` in `~/.gem/skills`. Projects symlink to the cached version, so
|
|
25
|
-
has accurate, version-specific knowledge about each gem without
|
|
26
|
-
ingestion work.
|
|
25
|
+
`SKILL.md` in `~/.gem/skills`. Projects symlink to the cached version, so your
|
|
26
|
+
assistant has accurate, version-specific knowledge about each gem without
|
|
27
|
+
repeating the ingestion work. `SKILL.md` is a shared format — Claude Code,
|
|
28
|
+
OpenAI Codex, and other assistants all read it.
|
|
27
29
|
|
|
28
30
|
## How the cache is laid out
|
|
29
31
|
|
|
@@ -38,7 +40,8 @@ ingestion work.
|
|
|
38
40
|
└── metadata.json
|
|
39
41
|
```
|
|
40
42
|
|
|
41
|
-
Each project's `.claude/skills/`
|
|
43
|
+
Each project's `.claude/skills/` directory (Claude Code's convention) holds
|
|
44
|
+
symlinks that point into this cache:
|
|
42
45
|
|
|
43
46
|
```
|
|
44
47
|
your-app/.claude/skills/
|
|
@@ -48,6 +51,29 @@ your-app/.claude/skills/
|
|
|
48
51
|
Two projects that pin different versions of the same gem each get the right
|
|
49
52
|
skill; the underlying content is generated once and shared.
|
|
50
53
|
|
|
54
|
+
### Using the cache with other assistants
|
|
55
|
+
|
|
56
|
+
The `~/.gem/skills` cache is assistant-neutral — `SKILL.md` is a shared format.
|
|
57
|
+
By default `bundle skill` links skills into `.claude/skills/`, which Claude Code
|
|
58
|
+
reads automatically. Other assistants discover skills in their own roots; for
|
|
59
|
+
example, OpenAI Codex looks in `~/.codex/skills` and the vendor-neutral
|
|
60
|
+
`~/.agents/skills` (and project-local `.agents/` / `.codex/`).
|
|
61
|
+
|
|
62
|
+
To make `bundle skill` link into a different project directory, set
|
|
63
|
+
`GEMSKILL_PROJECT_DIR`:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
export GEMSKILL_PROJECT_DIR=".agents" # Codex project root
|
|
67
|
+
bundle skill install # symlinks now land in .agents/
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
> **Availability ≠ activation.** Claude Code treats every `SKILL.md` under
|
|
71
|
+
> `.claude/skills/` as active automatically. Some assistants (e.g. Codex) only
|
|
72
|
+
> activate a skill if it's in the session's available-skills list or you point
|
|
73
|
+
> at it explicitly — so linking makes a skill *available*, not necessarily
|
|
74
|
+
> *active*. See
|
|
75
|
+
> [Using with other assistants](https://madbomber.github.io/gem-skill/skill-files/#using-with-other-assistants).
|
|
76
|
+
|
|
51
77
|
## Installation
|
|
52
78
|
|
|
53
79
|
```bash
|
|
@@ -82,7 +108,8 @@ Two environment variables control `gem-skill`'s behaviour:
|
|
|
82
108
|
|
|
83
109
|
| Variable | Default | Description |
|
|
84
110
|
|---|---|---|
|
|
85
|
-
| `GEMSKILL_DIR` | `~/.gem/skills` | Root directory for the skill cache |
|
|
111
|
+
| `GEMSKILL_DIR` | `~/.gem/skills` | Root directory for the global skill cache |
|
|
112
|
+
| `GEMSKILL_PROJECT_DIR` | `.claude/skills` | Project-relative directory where `bundle skill` writes symlinks |
|
|
86
113
|
| `GEMSKILL_MODEL` | `gpt-5.5` | LLM model used when generating skills |
|
|
87
114
|
|
|
88
115
|
```bash
|
|
@@ -91,6 +118,9 @@ export GEMSKILL_DIR="/Volumes/shared/gem-skills"
|
|
|
91
118
|
|
|
92
119
|
# Switch the default model to Claude
|
|
93
120
|
export GEMSKILL_MODEL="claude-sonnet-4-6"
|
|
121
|
+
|
|
122
|
+
# Codex users: link skills into a Codex project root instead of .claude/skills
|
|
123
|
+
export GEMSKILL_PROJECT_DIR=".agents" # or ".codex"
|
|
94
124
|
```
|
|
95
125
|
|
|
96
126
|
The `--model` flag on any command overrides `GEMSKILL_MODEL` for that
|
|
@@ -113,7 +143,10 @@ gem skill install chunker-ruby --force
|
|
|
113
143
|
# Use a different model
|
|
114
144
|
gem skill install chunker-ruby --model claude-haiku-4-5
|
|
115
145
|
|
|
116
|
-
#
|
|
146
|
+
# Verify an already-cached skill against the gem's source (fixes mismatches)
|
|
147
|
+
gem skill verify chunker-ruby
|
|
148
|
+
|
|
149
|
+
# Show everything in the cache (verified versions are flagged with a ✓)
|
|
117
150
|
gem skill list
|
|
118
151
|
|
|
119
152
|
# Remove a specific cached version
|
|
@@ -130,13 +163,21 @@ If a gem isn't installed locally, `gem skill install` will install it first.
|
|
|
130
163
|
|
|
131
164
|
### `gem skill setup`
|
|
132
165
|
|
|
133
|
-
Run once after `gem install gem-skill
|
|
166
|
+
Run once after `gem install gem-skill`:
|
|
134
167
|
|
|
135
168
|
```bash
|
|
136
169
|
gem skill setup
|
|
137
170
|
```
|
|
138
171
|
|
|
139
|
-
This
|
|
172
|
+
This does two things:
|
|
173
|
+
|
|
174
|
+
1. Registers gem-skill as a Bundler plugin so `bundle skill` works in every project.
|
|
175
|
+
2. Installs the **`ruby-gem-skills`** router skill into the default skill root of
|
|
176
|
+
each detected assistant (`~/.claude/skills`, `~/.codex/skills`,
|
|
177
|
+
`~/.agents/skills`). Cached gem skills live in `~/.gem/skills`, which
|
|
178
|
+
assistants don't scan by default — this small always-on skill teaches Claude
|
|
179
|
+
Code and Codex how to find and load a gem's `SKILL.md` on demand. Re-run
|
|
180
|
+
`gem skill setup` after upgrading gem-skill to refresh it.
|
|
140
181
|
|
|
141
182
|
### `gem install --with-skill`
|
|
142
183
|
|
data/docs/cache.md
CHANGED
|
@@ -36,8 +36,9 @@ projects pinning different versions of the same gem each get the correct skill.
|
|
|
36
36
|
|
|
37
37
|
### `SKILL.md`
|
|
38
38
|
|
|
39
|
-
The generated skill file. Contains structured documentation
|
|
40
|
-
Claude Code
|
|
39
|
+
The generated skill file. Contains structured documentation for AI coding
|
|
40
|
+
assistants (Claude Code, OpenAI Codex, and others). See
|
|
41
|
+
[Skill Files](skill-files.md) for the format.
|
|
41
42
|
|
|
42
43
|
### `metadata.json`
|
|
43
44
|
|
|
@@ -53,6 +54,52 @@ Stores provenance information:
|
|
|
53
54
|
}
|
|
54
55
|
```
|
|
55
56
|
|
|
57
|
+
When a skill is generated with `--verify`, a `verification` block is added that
|
|
58
|
+
records that the gem's actual source code was consulted, exactly which files were
|
|
59
|
+
examined, and the issue-ready corrections that resulted:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"gem_name": "tty-spinner",
|
|
64
|
+
"version": "0.9.3",
|
|
65
|
+
"model": "gpt-5.5",
|
|
66
|
+
"generated_at": "2026-06-17T10:23:45Z",
|
|
67
|
+
"sources": ["metadata", "readme", "changelog"],
|
|
68
|
+
"verification": {
|
|
69
|
+
"verified": true,
|
|
70
|
+
"verified_at": "2026-06-19T14:02:11Z",
|
|
71
|
+
"model": "gpt-5.5",
|
|
72
|
+
"used_source_code": true,
|
|
73
|
+
"source": {
|
|
74
|
+
"files": ["lib/tty/spinner.rb", "lib/tty/spinner/multi.rb", "lib/tty/spinner/formats.rb"],
|
|
75
|
+
"file_count": 3,
|
|
76
|
+
"chars": 26452,
|
|
77
|
+
"truncated": false
|
|
78
|
+
},
|
|
79
|
+
"fixed": true,
|
|
80
|
+
"change_count": 1,
|
|
81
|
+
"changes": [
|
|
82
|
+
{
|
|
83
|
+
"category": "default_value",
|
|
84
|
+
"symbol": "TTY::Spinner#stop",
|
|
85
|
+
"skill_section": "Core API",
|
|
86
|
+
"source_location": "lib/tty/spinner.rb:387",
|
|
87
|
+
"was": "stop(message = nil)",
|
|
88
|
+
"now": "stop(message = '')",
|
|
89
|
+
"detail": "Default argument is an empty string, not nil; the README implied nil.",
|
|
90
|
+
"source_evidence": "def stop(stop_message = '')"
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Each entry in `changes` is detailed enough to open a documentation issue against
|
|
98
|
+
the gem: it names the affected symbol, where the skill was wrong, what it claimed
|
|
99
|
+
versus the truth, and the source snippet that proves it. When source isn't
|
|
100
|
+
available locally, `verification` instead records `"verified": false`,
|
|
101
|
+
`"used_source_code": false`, and a `"skipped_reason"`.
|
|
102
|
+
|
|
56
103
|
## Cache commands
|
|
57
104
|
|
|
58
105
|
```bash
|
|
@@ -81,7 +128,10 @@ Skills generated on one machine are immediately available on others.
|
|
|
81
128
|
|
|
82
129
|
## Project symlinks
|
|
83
130
|
|
|
84
|
-
Projects don't store skills locally — they hold symlinks into the global cache
|
|
131
|
+
Projects don't store skills locally — they hold symlinks into the global cache.
|
|
132
|
+
`bundle skill` writes these into the directory named by
|
|
133
|
+
[`GEMSKILL_PROJECT_DIR`](configuration.md#gemskill_project_dir), which defaults
|
|
134
|
+
to `.claude/skills/` (Claude Code's convention):
|
|
85
135
|
|
|
86
136
|
```
|
|
87
137
|
your-project/.claude/skills/
|
|
@@ -89,12 +139,39 @@ your-project/.claude/skills/
|
|
|
89
139
|
└── zeitwerk → ~/.gem/skills/zeitwerk/2.8.2/
|
|
90
140
|
```
|
|
91
141
|
|
|
92
|
-
Each symlink points to the **version directory
|
|
93
|
-
from inside the linked directory.
|
|
142
|
+
Each symlink points to the **version directory**, and the assistant reads
|
|
143
|
+
`SKILL.md` from inside the linked directory.
|
|
94
144
|
|
|
95
145
|
`bundle skill refresh` updates symlinks when versions change after `bundle update`.
|
|
96
146
|
`bundle skill list` shows the status of all current symlinks.
|
|
97
147
|
|
|
148
|
+
### Other assistants
|
|
149
|
+
|
|
150
|
+
`SKILL.md` is a shared format and the cache is assistant-neutral. Assistants
|
|
151
|
+
other than Claude Code look in their own skill roots — for example, OpenAI Codex
|
|
152
|
+
uses `~/.codex/skills` and the vendor-neutral `~/.agents/skills` globally, or
|
|
153
|
+
project-local `.agents/` / `.codex/`.
|
|
154
|
+
|
|
155
|
+
For project links, set `GEMSKILL_PROJECT_DIR` so `bundle skill` writes straight
|
|
156
|
+
into the right directory:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
export GEMSKILL_PROJECT_DIR=".agents"
|
|
160
|
+
bundle skill install
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
For a global, cross-project link, symlink a cached version directory into the
|
|
164
|
+
assistant's global root:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
ln -s ~/.gem/skills/faraday/2.14.3 ~/.agents/skills/faraday
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Note that linking only makes a skill *available*; some assistants (e.g. Codex)
|
|
171
|
+
won't *activate* it unless it's in the session's available-skills list or you
|
|
172
|
+
reference it explicitly. See
|
|
173
|
+
[Using with other assistants](skill-files.md#using-with-other-assistants).
|
|
174
|
+
|
|
98
175
|
## Regenerating skills
|
|
99
176
|
|
|
100
177
|
Skills do not auto-expire. Regenerate explicitly when you want updated content:
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
The `bundle skill` command is project-aware: it reads `Gemfile.lock` to
|
|
4
4
|
determine which gems and versions are in use, generates skills for all of them,
|
|
5
|
-
and links the results into `.claude/skills/`
|
|
5
|
+
and links the results into `.claude/skills/` (Claude Code's skill directory) in
|
|
6
|
+
the project root. The generated `SKILL.md` files are a shared format that other
|
|
7
|
+
assistants read too — see [Using with other assistants](../skill-files.md#using-with-other-assistants).
|
|
6
8
|
|
|
7
9
|
## Global options
|
|
8
10
|
|
|
@@ -42,6 +44,7 @@ bundle skill install [OPTIONS]
|
|
|
42
44
|
| Flag | Description |
|
|
43
45
|
|------|-------------|
|
|
44
46
|
| `--force` | Regenerate even if skills are already cached |
|
|
47
|
+
| `--verify` | Verify generated skills against each gem's source and fix mismatches (exit `2` if any fixes applied) |
|
|
45
48
|
| `--model MODEL` | LLM model to use (overrides `GEMSKILL_MODEL`) |
|
|
46
49
|
| `--version`, `-v` | Print the installed gem-skill version and exit |
|
|
47
50
|
|
|
@@ -66,7 +69,10 @@ All gems are processed concurrently:
|
|
|
66
69
|
✓ ruby_llm 1.16.0 done
|
|
67
70
|
```
|
|
68
71
|
|
|
69
|
-
After completion, each skill is symlinked into
|
|
72
|
+
After completion, each skill is symlinked into the project skill directory
|
|
73
|
+
(`.claude/skills/` by default; set
|
|
74
|
+
[`GEMSKILL_PROJECT_DIR`](../configuration.md#gemskill_project_dir) to change it,
|
|
75
|
+
e.g. `.agents` for Codex):
|
|
70
76
|
|
|
71
77
|
```
|
|
72
78
|
your-project/.claude/skills/
|
|
@@ -75,7 +81,8 @@ your-project/.claude/skills/
|
|
|
75
81
|
└── zeitwerk → ~/.gem/skills/zeitwerk/2.8.2/
|
|
76
82
|
```
|
|
77
83
|
|
|
78
|
-
|
|
84
|
+
The assistant automatically reads `SKILL.md` from each linked directory (Claude
|
|
85
|
+
Code reads `.claude/skills/`; other assistants use their own roots).
|
|
79
86
|
|
|
80
87
|
---
|
|
81
88
|
|
data/docs/commands/gem-skill.md
CHANGED
|
@@ -18,6 +18,7 @@ gem skill install GEM_NAME [GEM_NAME ...]
|
|
|
18
18
|
| Flag | Description |
|
|
19
19
|
|------|-------------|
|
|
20
20
|
| `--force`, `-f` | Regenerate even if a skill is already cached |
|
|
21
|
+
| `--verify` | After generating, verify the skill's code against the gem's actual source and fix mismatches |
|
|
21
22
|
| `--model MODEL`, `-m MODEL` | LLM model to use (overrides `GEMSKILL_MODEL`) |
|
|
22
23
|
| `--version`, `-v` | Print the installed gem-skill version and exit |
|
|
23
24
|
|
|
@@ -32,11 +33,66 @@ gem skill install faraday zeitwerk dry-validation
|
|
|
32
33
|
|
|
33
34
|
# Force regeneration with a specific model
|
|
34
35
|
gem skill install rails --force --model claude-opus-4-8
|
|
36
|
+
|
|
37
|
+
# Generate, then verify the result against the gem's source code
|
|
38
|
+
gem skill install tty-spinner --verify
|
|
35
39
|
```
|
|
36
40
|
|
|
37
41
|
If a gem is not installed locally, gem-skill will install it automatically
|
|
38
42
|
before generating the skill.
|
|
39
43
|
|
|
44
|
+
### Verifying against source (`--verify`)
|
|
45
|
+
|
|
46
|
+
The generation pass synthesizes a skill from a gem's README, changelog, and
|
|
47
|
+
examples. That prose is sometimes stale or wrong about exact method signatures,
|
|
48
|
+
default argument values, and behavior. `--verify` adds a second pass that checks
|
|
49
|
+
the generated skill against the gem's **actual installed source code** (the only
|
|
50
|
+
source of truth) and rewrites anything the source contradicts.
|
|
51
|
+
|
|
52
|
+
Verification requires the gem to be installed locally (it reads `lib/**/*.rb`).
|
|
53
|
+
If no source is available, the skill is left untouched.
|
|
54
|
+
|
|
55
|
+
**Exit status** (so CI can detect README/source drift):
|
|
56
|
+
|
|
57
|
+
| Code | Meaning |
|
|
58
|
+
|------|---------|
|
|
59
|
+
| `0` | Success — skill was clean, or `--verify` not used |
|
|
60
|
+
| `1` | Error |
|
|
61
|
+
| `2` | `--verify` found and corrected problems |
|
|
62
|
+
|
|
63
|
+
Either way, `metadata.json` gains a `verification` block recording that the gem's
|
|
64
|
+
actual source was consulted, which files were examined, and — when fixes were
|
|
65
|
+
applied — an array of structured, issue-ready corrections (affected symbol,
|
|
66
|
+
source location, what the skill said vs. the truth, and the proving source
|
|
67
|
+
snippet). See [Cache layout](cache.md#metadatajson) for the full schema.
|
|
68
|
+
|
|
69
|
+
A verified skill is flagged with a green checkmark in
|
|
70
|
+
[`gem skill list`](#gem-skill-list).
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### `gem skill verify`
|
|
75
|
+
|
|
76
|
+
Verify an **already-cached** skill against the gem's source, in place, without
|
|
77
|
+
regenerating it.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
gem skill verify GEM_NAME [GEM_NAME ...]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
This runs the same source-truth check as `--verify`, but never generates: the
|
|
84
|
+
gem must be installed (verification reads its source) and the skill must already
|
|
85
|
+
be cached. It errors if either is missing rather than generating a new skill.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Verify the cached tty-spinner skill against its installed source
|
|
89
|
+
gem skill verify tty-spinner
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Exit status matches `--verify`: `0` clean, `1` error, `2` when corrections were
|
|
93
|
+
applied. Verified versions are flagged with a green checkmark in
|
|
94
|
+
[`gem skill list`](#gem-skill-list).
|
|
95
|
+
|
|
40
96
|
---
|
|
41
97
|
|
|
42
98
|
### `gem skill --version`
|
|
@@ -63,20 +119,35 @@ All gems are processed concurrently — you'll see a live spinner per gem:
|
|
|
63
119
|
|
|
64
120
|
### `gem skill setup`
|
|
65
121
|
|
|
66
|
-
|
|
122
|
+
Run once after `gem install gem-skill`.
|
|
67
123
|
|
|
68
124
|
```bash
|
|
69
125
|
gem skill setup
|
|
70
126
|
```
|
|
71
127
|
|
|
72
|
-
|
|
73
|
-
|
|
128
|
+
It does two things:
|
|
129
|
+
|
|
130
|
+
1. **Registers gem-skill as a Bundler plugin** so `bundle skill` works in any
|
|
131
|
+
project on the machine.
|
|
132
|
+
2. **Installs the `ruby-gem-skills` router skill** into the default skill root of
|
|
133
|
+
each detected assistant — `~/.claude/skills` (Claude Code), `~/.codex/skills`
|
|
134
|
+
and `~/.agents/skills` (Codex). A root is only written if its assistant home
|
|
135
|
+
(`~/.claude`, `~/.codex`, `~/.agents`) already exists.
|
|
136
|
+
|
|
137
|
+
The router skill matters because cached gem skills live in `~/.gem/skills`, a
|
|
138
|
+
directory assistants don't scan by default. This small always-on skill triggers
|
|
139
|
+
when you work with a Ruby gem and tells the assistant how to find and read that
|
|
140
|
+
gem's cached `SKILL.md` (resolving the version from `Gemfile.lock` or the
|
|
141
|
+
installed gem). Re-run `gem skill setup` after upgrading gem-skill to refresh the
|
|
142
|
+
copy. See [Installation](../installation.md) for details.
|
|
74
143
|
|
|
75
144
|
---
|
|
76
145
|
|
|
77
146
|
### `gem skill list`
|
|
78
147
|
|
|
79
|
-
Show all skills currently in the global cache.
|
|
148
|
+
Show all skills currently in the global cache. A green checkmark (`✓`) appears
|
|
149
|
+
next to any version whose skill has been verified against the gem's source (via
|
|
150
|
+
`--verify` or `gem skill verify`); unverified versions show no mark.
|
|
80
151
|
|
|
81
152
|
```bash
|
|
82
153
|
gem skill list
|
|
@@ -88,12 +159,18 @@ gem skill list
|
|
|
88
159
|
Cached skills in /Users/you/.gem/skills:
|
|
89
160
|
|
|
90
161
|
debug_me 1.1.0
|
|
91
|
-
faraday 2.12.0, 2.14.3
|
|
92
|
-
zeitwerk 2.8.2
|
|
162
|
+
faraday 2.12.0, 2.14.3 ✓
|
|
163
|
+
zeitwerk 2.8.2 ✓
|
|
93
164
|
|
|
94
165
|
3 gem(s), 4 version(s) total.
|
|
95
166
|
```
|
|
96
167
|
|
|
168
|
+
Here `faraday 2.14.3` and `zeitwerk 2.8.2` have verified skills, while
|
|
169
|
+
`faraday 2.12.0` and `debug_me 1.1.0` have not been verified. The checkmark is
|
|
170
|
+
shown in green when the output is an interactive terminal, and as a plain `✓`
|
|
171
|
+
when piped or redirected. "Verified" means the skill was checked against the
|
|
172
|
+
gem's actual source — see [`gem skill verify`](#gem-skill-verify).
|
|
173
|
+
|
|
97
174
|
---
|
|
98
175
|
|
|
99
176
|
### `gem skill purge`
|
data/docs/configuration.md
CHANGED
|
@@ -37,6 +37,43 @@ Controls where generated skills are cached.
|
|
|
37
37
|
Useful for sharing a skill cache across machines via a network drive, or for
|
|
38
38
|
keeping skills in a non-standard location.
|
|
39
39
|
|
|
40
|
+
### `GEMSKILL_PROJECT_DIR`
|
|
41
|
+
|
|
42
|
+
The project-relative directory where `bundle skill` writes its symlinks into the
|
|
43
|
+
cache. Change it to match whichever assistant you use.
|
|
44
|
+
|
|
45
|
+
| | |
|
|
46
|
+
|---|---|
|
|
47
|
+
| **Default** | `.claude/skills` (Claude Code) |
|
|
48
|
+
| **Example** | `export GEMSKILL_PROJECT_DIR=".agents"` |
|
|
49
|
+
|
|
50
|
+
`SKILL.md` is a shared format, but each assistant looks for skills in its own
|
|
51
|
+
project directory:
|
|
52
|
+
|
|
53
|
+
| Assistant | Suggested `GEMSKILL_PROJECT_DIR` |
|
|
54
|
+
|--------------|----------------------------------|
|
|
55
|
+
| Claude Code | `.claude/skills` (default) |
|
|
56
|
+
| OpenAI Codex | `.agents` or `.codex` |
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Claude Code (default — no need to set anything)
|
|
60
|
+
bundle skill install
|
|
61
|
+
|
|
62
|
+
# OpenAI Codex — link into a Codex project root instead
|
|
63
|
+
export GEMSKILL_PROJECT_DIR=".agents"
|
|
64
|
+
bundle skill install # symlinks now land in .agents/
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
A blank or unset value falls back to the `.claude/skills` default.
|
|
68
|
+
|
|
69
|
+
!!! note "Availability is not activation"
|
|
70
|
+
Setting `GEMSKILL_PROJECT_DIR` controls *where the symlinks are written*. It
|
|
71
|
+
does not change how an assistant decides a skill is active. Claude Code
|
|
72
|
+
activates every `SKILL.md` under `.claude/skills/` automatically; other
|
|
73
|
+
assistants (e.g. Codex) may require the skill to be in the session's
|
|
74
|
+
available-skills list or referenced explicitly. See
|
|
75
|
+
[Using with other assistants](skill-files.md#using-with-other-assistants).
|
|
76
|
+
|
|
40
77
|
### `GEMSKILL_MODEL`
|
|
41
78
|
|
|
42
79
|
Controls which LLM model is used when generating skills.
|
data/docs/how-it-works.md
CHANGED
|
@@ -16,6 +16,9 @@ Gemfile.lock / gem name
|
|
|
16
16
|
↓
|
|
17
17
|
Cache write to ~/.gem/skills/<gem>/<version>/
|
|
18
18
|
↓
|
|
19
|
+
Verifier (optional, --verify) check the skill's code against the
|
|
20
|
+
gem's actual source; correct mismatches in place
|
|
21
|
+
↓
|
|
19
22
|
Linker symlink .claude/skills/<gem> → cache dir
|
|
20
23
|
```
|
|
21
24
|
|
|
@@ -78,27 +81,71 @@ Manages the global skill cache. Structure:
|
|
|
78
81
|
└── <gem_name>/
|
|
79
82
|
└── <version>/
|
|
80
83
|
├── SKILL.md
|
|
81
|
-
└── metadata.json (gem, version, model, generated_at, sources
|
|
84
|
+
└── metadata.json (gem, version, model, generated_at, sources,
|
|
85
|
+
and after --verify: a "verification" block with
|
|
86
|
+
source provenance + structured changes)
|
|
82
87
|
```
|
|
83
88
|
|
|
84
89
|
`Cache::ROOT` is set once at load time from `GEMSKILL_DIR` (default: `~/.gem/skills`).
|
|
85
90
|
|
|
91
|
+
`read_metadata` / `write_skill` / `merge_metadata` let the verifier rewrite a
|
|
92
|
+
cached skill and annotate its metadata without clobbering the original
|
|
93
|
+
`generated_at`, `model`, or `sources`.
|
|
94
|
+
|
|
95
|
+
### Verifier
|
|
96
|
+
|
|
97
|
+
`lib/gem/skill/verifier.rb`
|
|
98
|
+
|
|
99
|
+
Optional second pass, enabled by `--verify`. Generation synthesizes prose
|
|
100
|
+
sources (README, changelog, examples) which are frequently stale or wrong about
|
|
101
|
+
exact signatures. The verifier re-checks the generated skill against the gem's
|
|
102
|
+
**actual source code** — the only source of truth — and corrects mismatched
|
|
103
|
+
method signatures, default argument values, visibility, return values, and
|
|
104
|
+
behavioral claims.
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
Verifier.new(gem_name, version, model:).verify(skill_content)
|
|
108
|
+
# => Result(content:, changes:, changed:, verifiable:, source:, model:)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Ground truth comes from `Fetcher#source_code` (the gem's `lib/**/*.rb`), and
|
|
112
|
+
`Fetcher#source_manifest` records which files were examined. Whether the skill
|
|
113
|
+
actually changed is decided by a **deterministic diff** of the content before and
|
|
114
|
+
after — not by trusting the model's self-report — so the exit code is reliable.
|
|
115
|
+
If no installed source is available, `verifiable` is false and the skill is left
|
|
116
|
+
untouched.
|
|
117
|
+
|
|
118
|
+
Each correction in `changes` is a structured, issue-ready Hash
|
|
119
|
+
(`category`, `symbol`, `skill_section`, `source_location`, `was`, `now`,
|
|
120
|
+
`detail`, `source_evidence`) — detailed enough to file a documentation bug
|
|
121
|
+
against the gem. The Runner writes these, plus source provenance, into the
|
|
122
|
+
`verification` block of `metadata.json`.
|
|
123
|
+
|
|
86
124
|
### Linker
|
|
87
125
|
|
|
88
126
|
`lib/gem/skill/linker.rb`
|
|
89
127
|
|
|
90
|
-
Creates and manages directory symlinks in
|
|
128
|
+
Creates and manages directory symlinks in the project's skill directory
|
|
129
|
+
(default `.claude/skills/`, Claude Code's convention):
|
|
91
130
|
|
|
92
131
|
```
|
|
93
|
-
|
|
132
|
+
<project_dir>/<gem_name> → ~/.gem/skills/<gem_name>/<version>/
|
|
94
133
|
```
|
|
95
134
|
|
|
96
|
-
|
|
97
|
-
|
|
135
|
+
The directory is `Linker.project_dir`, read from `GEMSKILL_PROJECT_DIR` each call
|
|
136
|
+
(default `.claude/skills`). Codex users set it to `.agents` or `.codex` so
|
|
137
|
+
`bundle skill` links into a Codex root instead. Symlinks point to the **version
|
|
138
|
+
directory**, not directly to `SKILL.md`; the assistant discovers `SKILL.md` by
|
|
139
|
+
reading inside the linked directory.
|
|
98
140
|
|
|
99
141
|
`Linker.prune_dead_links` removes any symlink whose target no longer exists
|
|
100
142
|
in the cache (e.g. after `gem skill purge`).
|
|
101
143
|
|
|
144
|
+
The cache itself is assistant-neutral. `SKILL.md` is a shared format; other
|
|
145
|
+
assistants read it from their own roots. Note that linking only makes a skill
|
|
146
|
+
*available* — some assistants (e.g. Codex) require it to be in the available-skills
|
|
147
|
+
list or referenced explicitly before it's *active*.
|
|
148
|
+
|
|
102
149
|
### Runner
|
|
103
150
|
|
|
104
151
|
`lib/gem/skill/runner.rb`
|
|
@@ -107,12 +154,14 @@ Shared core used by both CLI commands. Drives one gem through the
|
|
|
107
154
|
cache-check → generate → link sequence:
|
|
108
155
|
|
|
109
156
|
```ruby
|
|
110
|
-
Runner.install_skill(gem_name, version, spinner, force:, model:)
|
|
111
|
-
#
|
|
157
|
+
Runner.install_skill(gem_name, version, spinner, force:, model:, verify:)
|
|
158
|
+
# => Runner::Result(error:, verify_fixed:, change_count:)
|
|
112
159
|
```
|
|
113
160
|
|
|
114
|
-
|
|
115
|
-
fiber) can record
|
|
161
|
+
Captures errors into the result rather than raising, so the caller (the
|
|
162
|
+
concurrent fiber) can record them without killing other in-flight fibers. When
|
|
163
|
+
`verify:` is set, the result's `verify_fixed` lets the CLI aggregate across all
|
|
164
|
+
gems and exit `2` (`EXIT_VERIFY_FIXED`) if any skill was corrected.
|
|
116
165
|
|
|
117
166
|
---
|
|
118
167
|
|