gem-skill 0.1.3 → 0.2.2
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 +43 -0
- data/CLAUDE.md +63 -0
- data/README.md +68 -15
- data/docs/cache.md +82 -5
- data/docs/commands/bundle-skill.md +12 -3
- data/docs/commands/gem-skill.md +91 -6
- data/docs/configuration.md +61 -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 +57 -22
- data/lib/gem/skill/cli/gem_command.rb +171 -9
- data/lib/gem/skill/fetcher.rb +52 -0
- data/lib/gem/skill/frontmatter.rb +64 -0
- data/lib/gem/skill/generator.rb +46 -13
- data/lib/gem/skill/linker.rb +17 -3
- data/lib/gem/skill/runner.rb +75 -9
- data/lib/gem/skill/verifier.rb +139 -0
- data/lib/gem/skill/version.rb +1 -1
- data/lib/gem/skill.rb +36 -1
- data/ruby-gem-skills/SKILL.md +53 -0
- metadata +37 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3cc3ecc8f770110cc9f8605e149ff2d78c44a388a76add0046c595b01ecbf882
|
|
4
|
+
data.tar.gz: 21ac18bb7bcc6de52ac9987561da30821be843cca322f0b45b8e04ed1a9af3a1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4f6fecb42f713486c2abddd7041c6a7294ed4e0cf07affd97457739fe0bd59c8fb080ee80b672817e9a182ff8359896235f2c2c56f16a54eca9528290a3fd07d
|
|
7
|
+
data.tar.gz: acd79346e7b20fcead6bfff93f4f21aa58f81ac203b3fec5616f2f5f55b6d4337c0919cd01a1790159c7e256ec579c14d8e25c2aaa4cd5d85479fea826c4e3fa
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,49 @@ 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
|
+
- `GEMSKIL_MAX_TOKENS` environment variable (default `32767`) — caps the number of output tokens the LLM may generate per skill file. Raise this if generated `SKILL.md` files are being truncated.
|
|
11
|
+
- `--max-tokens TOKENS` CLI flag on `gem skill install`, `bundle skill install`, and `bundle skill refresh` — overrides `GEMSKIL_MAX_TOKENS` for a single invocation. Provider-correct parameter name is selected automatically (`max_completion_tokens` for OpenAI models, `max_tokens` for all others).
|
|
12
|
+
- `GEMSKILL_TEMPERATURE` environment variable (default `0.2`) — sampling temperature for generation. Lower values produce more consistent, less variable output, appropriate for factual reference docs. Applied only to models that support a temperature parameter; reasoning models (e.g. `gpt-5.5`) report `temperature: false` in their RubyLLM metadata and the value is silently skipped for them.
|
|
13
|
+
- `--temperature TEMP` CLI flag on `gem skill install` — overrides `GEMSKILL_TEMPERATURE` for a single invocation.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- `strip_wrapper_fence` no longer deletes the closing ``` of a skill that legitimately ends with a code block. The trailing wrapper fence is now stripped only when a matching opening wrapper fence (```` ```markdown ```` / ```` ``` ```` at the very start) was present. Previously the final ``` was removed unconditionally, leaving the last code block open at end-of-file — which looked like the LLM truncating its output but was entirely a post-processing bug. Regenerate affected skills with `gem skill install GEM --force`.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
- `Generator::MAX_TOKENS` constant reads from `GEMSKIL_MAX_TOKENS` and is passed via `with_params` to every `RubyLLM.chat` call, covering both streaming and non-streaming paths.
|
|
20
|
+
- `Generator#initialize` now accepts `max_tokens:` and `temperature:` keywords so callers can override the token cap and sampling temperature per-instance without touching the environment.
|
|
21
|
+
- `Generator` sets `with_temperature` only when the model's RubyLLM metadata does not mark temperature unsupported, avoiding API errors on reasoning models.
|
|
22
|
+
- `Runner.install_skill` accepts and forwards `max_tokens:` and `temperature:` to `Generator.new`.
|
|
23
|
+
- `README.md` Configuration section now lists all environment variables (gem-skill-specific and provider API keys) in a single reference table.
|
|
24
|
+
- `docs/configuration.md` documents the new `GEMSKIL_MAX_TOKENS` and `GEMSKILL_TEMPERATURE` variables alongside the existing `GEMSKILL_MODEL` entry.
|
|
25
|
+
- `docs/commands/gem-skill.md` and `docs/commands/bundle-skill.md` option tables updated with `--max-tokens` and `--temperature`.
|
|
26
|
+
|
|
27
|
+
## [0.2.0] - 2026-06-19
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
- `--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.
|
|
31
|
+
- `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).
|
|
32
|
+
- `gem skill list` flags verified versions with a green checkmark (`✓`); unverified versions show no mark. The checkmark is colored only for interactive terminals.
|
|
33
|
+
- `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.
|
|
34
|
+
- `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.
|
|
35
|
+
- `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.
|
|
36
|
+
- `Fetcher#source_code` — concatenates the gem's `lib/**/*.rb` (size-capped) as the ground truth the verifier checks against.
|
|
37
|
+
- `Cache.read_metadata`, `Cache.write_skill`, `Cache.merge_metadata` — support verifying/rewriting a cached skill without clobbering `generated_at`/`model`/`sources`.
|
|
38
|
+
- 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`.
|
|
39
|
+
- 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.
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
- `Runner.install_skill` now accepts `verify:` and returns a `Runner::Result` (`error`, `verify_fixed`) instead of a nil/error-string.
|
|
43
|
+
- 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).
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
- 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.
|
|
47
|
+
|
|
48
|
+
### Note
|
|
49
|
+
- Skills cached before this change lack frontmatter; regenerate them with `gem skill install GEM --force` (or `bundle skill refresh --force`) to add it.
|
|
50
|
+
|
|
8
51
|
## [0.1.3] - 2026-06-17
|
|
9
52
|
|
|
10
53
|
### Added
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## What this gem does
|
|
6
|
+
|
|
7
|
+
`gem-skill` generates `SKILL.md` files from Ruby gem documentation using an LLM (via RubyLLM), caches them globally at `~/.gem/skills/<gem_name>/<version>/SKILL.md`, and symlinks them into projects as directory links: `.claude/skills/<gem_name>/ → ~/.gem/skills/<gem_name>/<version>/`. It registers two CLI entry points: `gem skill` (global cache management) and `bundle skill` (project-aware, driven by `Gemfile.lock`), plus a `gem install --with-skill` flag.
|
|
8
|
+
|
|
9
|
+
## Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bundle install
|
|
13
|
+
bundle exec rake test # run all tests (default task)
|
|
14
|
+
ruby -Ilib:test test/gem/skill/cache_test.rb # run a single test file
|
|
15
|
+
bundle exec ruby scripts/e2e_test [GEM VERSION MODEL] # live LLM end-to-end test (needs a provider API key)
|
|
16
|
+
bin/dev_install # point Bundler's plugin indexes at this source tree so
|
|
17
|
+
# `bundle skill` runs local code (no build/release needed)
|
|
18
|
+
bin/dev_install --reset # restore to the released gem install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Docs site is MkDocs (`mkdocs.yml`, `docs/`), deployed by `.github/workflows/deploy-github-pages.yml`.
|
|
22
|
+
|
|
23
|
+
## Architecture
|
|
24
|
+
|
|
25
|
+
### Entry points
|
|
26
|
+
|
|
27
|
+
- `lib/rubygems_plugin.rb` — loaded automatically by RubyGems; registers `gem skill` (`Gem::Commands::SkillCommand`) AND prepends `--with-skill` onto `gem install`, queuing installed gems and generating their skills in threads via a `Gem.post_install` hook + `at_exit`
|
|
28
|
+
- `plugins.rb` — Bundler plugin entry point; registers `bundle skill` via `Gem::Skill::BundlerPlugin` → `Gem::Skill::BundlerCommand`
|
|
29
|
+
|
|
30
|
+
### Core pipeline (in call order)
|
|
31
|
+
|
|
32
|
+
1. **`Lockfile`** (`lib/gem/skill/lockfile.rb`) — parses `Gemfile.lock`; extracts direct-dependency name→version pairs by cross-referencing the `DEPENDENCIES` and `specs:` sections
|
|
33
|
+
2. **`Fetcher`** (`lib/gem/skill/fetcher.rb`) — collects raw docs for a single gem/version in priority order: (1) local `Gem::Specification` gem_dir, (2) RubyGems API JSON, (3) GitHub raw README. Returns `{metadata:, readme:, changelog:}` with only populated keys
|
|
34
|
+
3. **`Generator`** (`lib/gem/skill/generator.rb`) — formats fetched sources into a prompt, calls RubyLLM, strips any wrapping code fence, runs `Frontmatter.build`, stores result via `Cache`. Supports streaming via block
|
|
35
|
+
4. **`Frontmatter`** (`lib/gem/skill/frontmatter.rb`) — deterministically (no LLM) builds/replaces the YAML frontmatter (`name` + `description`) that makes a SKILL.md discoverable by both Claude Code and Codex; enforces both assistants' name/description constraints
|
|
36
|
+
5. **`Cache`** (`lib/gem/skill/cache.rb`) — reads/writes `~/.gem/skills/<name>/<version>/SKILL.md` and `metadata.json`; `merge_metadata` string-normalizes keys
|
|
37
|
+
6. **`Verifier`** (`lib/gem/skill/verifier.rb`) — optional second LLM pass (`--verify` or `gem skill verify`) that re-checks a generated skill against the gem's actual installed source and corrects wrong signatures/claims. `changed?` is decided by a deterministic content diff, never the model's self-report; unverifiable (no local source) is recorded in metadata, not an error
|
|
38
|
+
7. **`Linker`** (`lib/gem/skill/linker.rb`) — creates/updates directory symlinks in the project skills dir pointing into the cache; `prune_dead_links` removes broken symlinks after a refresh
|
|
39
|
+
|
|
40
|
+
**`Runner`** (`lib/gem/skill/runner.rb`) is the shared generate+cache+link+verify orchestration used by both CLI commands; it returns a `Runner::Result` (`Data.define`) and drives a TTY spinner passed in by the caller.
|
|
41
|
+
|
|
42
|
+
### CLI layer
|
|
43
|
+
|
|
44
|
+
- `lib/gem/skill/cli/gem_command.rb` — `Gem::Commands::SkillCommand`; subcommands: `install`, `verify`, `list`, `purge`, `setup`. Multi-gem installs run concurrently with the `async` gem (`Async::Barrier`). `setup` registers the Bundler plugin and copies the bundled router skill (`ruby-gem-skills/SKILL.md` at repo root) into each detected assistant's global skill root
|
|
45
|
+
- `lib/gem/skill/cli/bundle_command.rb` — `Gem::Skill::BundlerCommand`; subcommands: `install`, `refresh`, `list`. `install` = generate + link all direct lockfile gems; `refresh` = skip gems already linked at the correct version. Parses its own flags (`--force`, `--verify`, `--model`, `--max-tokens`, `--temperature`, `--version`)
|
|
46
|
+
|
|
47
|
+
### LLM configuration
|
|
48
|
+
|
|
49
|
+
`Gem::Skill.configure_llm!` reads provider API keys from environment variables (see `ENV_KEY_MAP` in `lib/gem/skill.rb`) and configures RubyLLM. Called automatically by both CLI entry points. No-op if already configured.
|
|
50
|
+
|
|
51
|
+
## Key constants & environment variables
|
|
52
|
+
|
|
53
|
+
- `Cache::ROOT` = `~/.gem/skills` (override: `GEMSKILL_DIR`)
|
|
54
|
+
- `Linker::DEFAULT_PROJECT_DIR` = `.claude/skills` (override: `GEMSKILL_PROJECT_DIR`, re-read on every call — e.g. `.agents` for Codex)
|
|
55
|
+
- `Generator::DEFAULT_MODEL` = `"gpt-5.5"` (override: `GEMSKILL_MODEL` or `--model`)
|
|
56
|
+
- `Generator::MAX_TOKENS` = 32,767 (override: `GEMSKIL_MAX_TOKENS` — note the single-L spelling — or `--max-tokens`)
|
|
57
|
+
- `Generator::DEFAULT_TEMPERATURE` = 0.2 (override: `GEMSKILL_TEMPERATURE` or `--temperature`; skipped for models that reject temperature)
|
|
58
|
+
- `Generator::MAX_SOURCE_CHARS` = 60,000 (README truncation guard)
|
|
59
|
+
- `Gem::Skill::EXIT_VERIFY_FIXED` = 2 — grep-style exit status when `--verify` applied fixes (0 = clean, 1 = error)
|
|
60
|
+
|
|
61
|
+
## Testing
|
|
62
|
+
|
|
63
|
+
Uses Minitest (`Minitest::TestTask`). Unit tests live in `test/gem/skill/`; shared cache-sandboxing helpers in `test/support/cache_helpers.rb`. `scripts/e2e_test` runs a full live pipeline (fetch → generate → cache → link) against a real LLM and requires at least one provider API key.
|
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
|
|
@@ -78,12 +104,22 @@ export GEMINI_API_KEY="..." # or Gemini
|
|
|
78
104
|
|
|
79
105
|
## Configuration
|
|
80
106
|
|
|
81
|
-
|
|
107
|
+
All environment variables and their defaults:
|
|
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 |
|
|
114
|
+
| `GEMSKIL_MAX_TOKENS` | `32767` | Maximum output tokens per generated skill file |
|
|
115
|
+
| `GEMSKILL_TEMPERATURE` | `0.2` | Sampling temperature (skipped for reasoning models that reject it) |
|
|
116
|
+
| `ANTHROPIC_API_KEY` | _(none)_ | API key for Anthropic / Claude models |
|
|
117
|
+
| `OPENAI_API_KEY` | _(none)_ | API key for OpenAI / GPT models |
|
|
118
|
+
| `GEMINI_API_KEY` | _(none)_ | API key for Google Gemini models |
|
|
119
|
+
| `MISTRAL_API_KEY` | _(none)_ | API key for Mistral models |
|
|
120
|
+
| `DEEPSEEK_API_KEY` | _(none)_ | API key for DeepSeek models |
|
|
121
|
+
| `OPENROUTER_API_KEY` | _(none)_ | API key for OpenRouter |
|
|
122
|
+
| `XAI_API_KEY` | _(none)_ | API key for xAI (Grok) models |
|
|
87
123
|
|
|
88
124
|
```bash
|
|
89
125
|
# Store skills on a shared drive accessible to all projects
|
|
@@ -91,6 +127,12 @@ export GEMSKILL_DIR="/Volumes/shared/gem-skills"
|
|
|
91
127
|
|
|
92
128
|
# Switch the default model to Claude
|
|
93
129
|
export GEMSKILL_MODEL="claude-sonnet-4-6"
|
|
130
|
+
|
|
131
|
+
# Codex users: link skills into a Codex project root instead of .claude/skills
|
|
132
|
+
export GEMSKILL_PROJECT_DIR=".agents" # or ".codex"
|
|
133
|
+
|
|
134
|
+
# Raise the output token cap if generated skill files are being truncated
|
|
135
|
+
export GEMSKIL_MAX_TOKENS=65536
|
|
94
136
|
```
|
|
95
137
|
|
|
96
138
|
The `--model` flag on any command overrides `GEMSKILL_MODEL` for that
|
|
@@ -113,7 +155,10 @@ gem skill install chunker-ruby --force
|
|
|
113
155
|
# Use a different model
|
|
114
156
|
gem skill install chunker-ruby --model claude-haiku-4-5
|
|
115
157
|
|
|
116
|
-
#
|
|
158
|
+
# Verify an already-cached skill against the gem's source (fixes mismatches)
|
|
159
|
+
gem skill verify chunker-ruby
|
|
160
|
+
|
|
161
|
+
# Show everything in the cache (verified versions are flagged with a ✓)
|
|
117
162
|
gem skill list
|
|
118
163
|
|
|
119
164
|
# Remove a specific cached version
|
|
@@ -130,13 +175,21 @@ If a gem isn't installed locally, `gem skill install` will install it first.
|
|
|
130
175
|
|
|
131
176
|
### `gem skill setup`
|
|
132
177
|
|
|
133
|
-
Run once after `gem install gem-skill
|
|
178
|
+
Run once after `gem install gem-skill`:
|
|
134
179
|
|
|
135
180
|
```bash
|
|
136
181
|
gem skill setup
|
|
137
182
|
```
|
|
138
183
|
|
|
139
|
-
This
|
|
184
|
+
This does two things:
|
|
185
|
+
|
|
186
|
+
1. Registers gem-skill as a Bundler plugin so `bundle skill` works in every project.
|
|
187
|
+
2. Installs the **`ruby-gem-skills`** router skill into the default skill root of
|
|
188
|
+
each detected assistant (`~/.claude/skills`, `~/.codex/skills`,
|
|
189
|
+
`~/.agents/skills`). Cached gem skills live in `~/.gem/skills`, which
|
|
190
|
+
assistants don't scan by default — this small always-on skill teaches Claude
|
|
191
|
+
Code and Codex how to find and load a gem's `SKILL.md` on demand. Re-run
|
|
192
|
+
`gem skill setup` after upgrading gem-skill to refresh it.
|
|
140
193
|
|
|
141
194
|
### `gem install --with-skill`
|
|
142
195
|
|
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,7 +44,9 @@ 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`) |
|
|
49
|
+
| `--max-tokens TOKENS` | Max output tokens per skill (overrides `GEMSKIL_MAX_TOKENS`; default: 32767) |
|
|
46
50
|
| `--version`, `-v` | Print the installed gem-skill version and exit |
|
|
47
51
|
|
|
48
52
|
**Example:**
|
|
@@ -66,7 +70,10 @@ All gems are processed concurrently:
|
|
|
66
70
|
✓ ruby_llm 1.16.0 done
|
|
67
71
|
```
|
|
68
72
|
|
|
69
|
-
After completion, each skill is symlinked into
|
|
73
|
+
After completion, each skill is symlinked into the project skill directory
|
|
74
|
+
(`.claude/skills/` by default; set
|
|
75
|
+
[`GEMSKILL_PROJECT_DIR`](../configuration.md#gemskill_project_dir) to change it,
|
|
76
|
+
e.g. `.agents` for Codex):
|
|
70
77
|
|
|
71
78
|
```
|
|
72
79
|
your-project/.claude/skills/
|
|
@@ -75,7 +82,8 @@ your-project/.claude/skills/
|
|
|
75
82
|
└── zeitwerk → ~/.gem/skills/zeitwerk/2.8.2/
|
|
76
83
|
```
|
|
77
84
|
|
|
78
|
-
|
|
85
|
+
The assistant automatically reads `SKILL.md` from each linked directory (Claude
|
|
86
|
+
Code reads `.claude/skills/`; other assistants use their own roots).
|
|
79
87
|
|
|
80
88
|
---
|
|
81
89
|
|
|
@@ -91,6 +99,7 @@ bundle skill refresh [OPTIONS]
|
|
|
91
99
|
|------|-------------|
|
|
92
100
|
| `--force` | Regenerate all skills, even those already at the correct version |
|
|
93
101
|
| `--model MODEL` | LLM model to use |
|
|
102
|
+
| `--max-tokens TOKENS` | Max output tokens per skill (overrides `GEMSKIL_MAX_TOKENS`; default: 32767) |
|
|
94
103
|
|
|
95
104
|
`refresh` skips gems that are already linked at the correct version (shows
|
|
96
105
|
`up to date`), regenerates gems whose version changed, and removes dead symlinks
|
data/docs/commands/gem-skill.md
CHANGED
|
@@ -18,7 +18,10 @@ 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`) |
|
|
23
|
+
| `--max-tokens TOKENS` | Max output tokens for this run (overrides `GEMSKIL_MAX_TOKENS`; default: 32767) |
|
|
24
|
+
| `--temperature TEMP` | Sampling temperature, skipped by reasoning models (overrides `GEMSKILL_TEMPERATURE`; default: 0.2) |
|
|
22
25
|
| `--version`, `-v` | Print the installed gem-skill version and exit |
|
|
23
26
|
|
|
24
27
|
**Examples:**
|
|
@@ -32,11 +35,72 @@ gem skill install faraday zeitwerk dry-validation
|
|
|
32
35
|
|
|
33
36
|
# Force regeneration with a specific model
|
|
34
37
|
gem skill install rails --force --model claude-opus-4-8
|
|
38
|
+
|
|
39
|
+
# Generate, then verify the result against the gem's source code
|
|
40
|
+
gem skill install tty-spinner --verify
|
|
41
|
+
|
|
42
|
+
# Raise the token cap to avoid truncated output
|
|
43
|
+
gem skill install rails --max-tokens 65536
|
|
44
|
+
|
|
45
|
+
# Lower the temperature for more reproducible output (temperature-capable models)
|
|
46
|
+
gem skill install faraday --model claude-sonnet-4-6 --temperature 0.0
|
|
35
47
|
```
|
|
36
48
|
|
|
37
49
|
If a gem is not installed locally, gem-skill will install it automatically
|
|
38
50
|
before generating the skill.
|
|
39
51
|
|
|
52
|
+
### Verifying against source (`--verify`)
|
|
53
|
+
|
|
54
|
+
The generation pass synthesizes a skill from a gem's README, changelog, and
|
|
55
|
+
examples. That prose is sometimes stale or wrong about exact method signatures,
|
|
56
|
+
default argument values, and behavior. `--verify` adds a second pass that checks
|
|
57
|
+
the generated skill against the gem's **actual installed source code** (the only
|
|
58
|
+
source of truth) and rewrites anything the source contradicts.
|
|
59
|
+
|
|
60
|
+
Verification requires the gem to be installed locally (it reads `lib/**/*.rb`).
|
|
61
|
+
If no source is available, the skill is left untouched.
|
|
62
|
+
|
|
63
|
+
**Exit status** (so CI can detect README/source drift):
|
|
64
|
+
|
|
65
|
+
| Code | Meaning |
|
|
66
|
+
|------|---------|
|
|
67
|
+
| `0` | Success — skill was clean, or `--verify` not used |
|
|
68
|
+
| `1` | Error |
|
|
69
|
+
| `2` | `--verify` found and corrected problems |
|
|
70
|
+
|
|
71
|
+
Either way, `metadata.json` gains a `verification` block recording that the gem's
|
|
72
|
+
actual source was consulted, which files were examined, and — when fixes were
|
|
73
|
+
applied — an array of structured, issue-ready corrections (affected symbol,
|
|
74
|
+
source location, what the skill said vs. the truth, and the proving source
|
|
75
|
+
snippet). See [Cache layout](cache.md#metadatajson) for the full schema.
|
|
76
|
+
|
|
77
|
+
A verified skill is flagged with a green checkmark in
|
|
78
|
+
[`gem skill list`](#gem-skill-list).
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
### `gem skill verify`
|
|
83
|
+
|
|
84
|
+
Verify an **already-cached** skill against the gem's source, in place, without
|
|
85
|
+
regenerating it.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
gem skill verify GEM_NAME [GEM_NAME ...]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
This runs the same source-truth check as `--verify`, but never generates: the
|
|
92
|
+
gem must be installed (verification reads its source) and the skill must already
|
|
93
|
+
be cached. It errors if either is missing rather than generating a new skill.
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Verify the cached tty-spinner skill against its installed source
|
|
97
|
+
gem skill verify tty-spinner
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Exit status matches `--verify`: `0` clean, `1` error, `2` when corrections were
|
|
101
|
+
applied. Verified versions are flagged with a green checkmark in
|
|
102
|
+
[`gem skill list`](#gem-skill-list).
|
|
103
|
+
|
|
40
104
|
---
|
|
41
105
|
|
|
42
106
|
### `gem skill --version`
|
|
@@ -63,20 +127,35 @@ All gems are processed concurrently — you'll see a live spinner per gem:
|
|
|
63
127
|
|
|
64
128
|
### `gem skill setup`
|
|
65
129
|
|
|
66
|
-
|
|
130
|
+
Run once after `gem install gem-skill`.
|
|
67
131
|
|
|
68
132
|
```bash
|
|
69
133
|
gem skill setup
|
|
70
134
|
```
|
|
71
135
|
|
|
72
|
-
|
|
73
|
-
|
|
136
|
+
It does two things:
|
|
137
|
+
|
|
138
|
+
1. **Registers gem-skill as a Bundler plugin** so `bundle skill` works in any
|
|
139
|
+
project on the machine.
|
|
140
|
+
2. **Installs the `ruby-gem-skills` router skill** into the default skill root of
|
|
141
|
+
each detected assistant — `~/.claude/skills` (Claude Code), `~/.codex/skills`
|
|
142
|
+
and `~/.agents/skills` (Codex). A root is only written if its assistant home
|
|
143
|
+
(`~/.claude`, `~/.codex`, `~/.agents`) already exists.
|
|
144
|
+
|
|
145
|
+
The router skill matters because cached gem skills live in `~/.gem/skills`, a
|
|
146
|
+
directory assistants don't scan by default. This small always-on skill triggers
|
|
147
|
+
when you work with a Ruby gem and tells the assistant how to find and read that
|
|
148
|
+
gem's cached `SKILL.md` (resolving the version from `Gemfile.lock` or the
|
|
149
|
+
installed gem). Re-run `gem skill setup` after upgrading gem-skill to refresh the
|
|
150
|
+
copy. See [Installation](../installation.md) for details.
|
|
74
151
|
|
|
75
152
|
---
|
|
76
153
|
|
|
77
154
|
### `gem skill list`
|
|
78
155
|
|
|
79
|
-
Show all skills currently in the global cache.
|
|
156
|
+
Show all skills currently in the global cache. A green checkmark (`✓`) appears
|
|
157
|
+
next to any version whose skill has been verified against the gem's source (via
|
|
158
|
+
`--verify` or `gem skill verify`); unverified versions show no mark.
|
|
80
159
|
|
|
81
160
|
```bash
|
|
82
161
|
gem skill list
|
|
@@ -88,12 +167,18 @@ gem skill list
|
|
|
88
167
|
Cached skills in /Users/you/.gem/skills:
|
|
89
168
|
|
|
90
169
|
debug_me 1.1.0
|
|
91
|
-
faraday 2.12.0, 2.14.3
|
|
92
|
-
zeitwerk 2.8.2
|
|
170
|
+
faraday 2.12.0, 2.14.3 ✓
|
|
171
|
+
zeitwerk 2.8.2 ✓
|
|
93
172
|
|
|
94
173
|
3 gem(s), 4 version(s) total.
|
|
95
174
|
```
|
|
96
175
|
|
|
176
|
+
Here `faraday 2.14.3` and `zeitwerk 2.8.2` have verified skills, while
|
|
177
|
+
`faraday 2.12.0` and `debug_me 1.1.0` have not been verified. The checkmark is
|
|
178
|
+
shown in green when the output is an interactive terminal, and as a plain `✓`
|
|
179
|
+
when piped or redirected. "Verified" means the skill was checked against the
|
|
180
|
+
gem's actual source — see [`gem skill verify`](#gem-skill-verify).
|
|
181
|
+
|
|
97
182
|
---
|
|
98
183
|
|
|
99
184
|
### `gem skill purge`
|
data/docs/configuration.md
CHANGED
|
@@ -37,6 +37,67 @@ 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
|
+
|
|
77
|
+
### `GEMSKIL_MAX_TOKENS`
|
|
78
|
+
|
|
79
|
+
Controls the maximum number of output tokens the LLM may generate for each skill file.
|
|
80
|
+
Increase this if generated `SKILL.md` files are being truncated.
|
|
81
|
+
|
|
82
|
+
| | |
|
|
83
|
+
|---|---|
|
|
84
|
+
| **Default** | `32767` |
|
|
85
|
+
| **Example** | `export GEMSKIL_MAX_TOKENS=65536` |
|
|
86
|
+
|
|
87
|
+
### `GEMSKILL_TEMPERATURE`
|
|
88
|
+
|
|
89
|
+
Sampling temperature for generation. Lower values produce more consistent,
|
|
90
|
+
deterministic output — appropriate for factual reference documentation.
|
|
91
|
+
|
|
92
|
+
| | |
|
|
93
|
+
|---|---|
|
|
94
|
+
| **Default** | `0.2` |
|
|
95
|
+
| **Example** | `export GEMSKILL_TEMPERATURE=0.0` |
|
|
96
|
+
|
|
97
|
+
Only applied to models that support a temperature parameter. Reasoning models
|
|
98
|
+
(e.g. `gpt-5.5`) reject it, so the value is silently skipped for them — switch to
|
|
99
|
+
a temperature-supporting model (Claude, Gemini, older GPT) to benefit.
|
|
100
|
+
|
|
40
101
|
### `GEMSKILL_MODEL`
|
|
41
102
|
|
|
42
103
|
Controls which LLM model is used when generating skills.
|