@ghostpaw/grimoire 0.3.0
Your agent edits its SKILL.md. Who keeps the history?
grimoire keeps skills as plain SKILL.md folders, seals each proven improvement as a git commit and keeps the evidence notes in SQLite. A skill's rank is the number of sealed commits, so an edit counts only once it is sealed, and any earlier version can be restored.
As a library
As a local MCP server
Replay the run Read the source on GitHub
Free and MIT licensed for Node.js 24 or newer, with zero runtime dependencies. Spells are files on your disk, history is a git repository next to them, and metadata is SQLite.

0runtime dependencies
One spell, seven calls
The agent's edit waits, uncommitted, until somebody seals it.
This is the deploy-service spell from the README quick start, replayed from a real run: we made these calls against grimoire 0.3.0 on 2026-10-24 with the git date fixed to 10:00 UTC, so the commit hashes are the real ones. Run the steps in order.
Spell
- Spellnot inscribed
- Rank—
- Commits0
- Notes0
- Uncommitted0
- Step 1—
An empty grimoire after init(root, db).
-
01 Inscribe a file without frontmatter
A spell has to be a valid
SKILL.md.write.inscribe(root, db, { name: 'deploy-service', chapter: 'engineering', content: '# deploy-service\n\nRun the build, push, apply.\n', });// GrimoireValidationError // Invalid SKILL.md content: Missing opening frontmatter delimiter (---)Refused, and no folder was created. This is a format check, not a security scan.
-
02 Inscribe the README spell
Same call with frontmatter, as in the quick start.
write.inscribe(root, db, { name: 'deploy-service', chapter: 'engineering', content: '---\nname: deploy-service\ndescription: Deploy a service to production\n---\n\n' + '# deploy-service\n\n## Steps\n\n1. Run `npm run build`\n2. Push to registry\n3. Apply manifests\n', });// { spell: { path: 'engineering/deploy-service', rank: 1, tier: 'Apprentice', // description: 'Deploy a service to production', bodyLines: 9, ... }, warnings: [] }The folder
engineering/deploy-service/now holds aSKILL.md, and the first commit gives it rank 1. -
03 Drop a note from practice
Evidence comes first and waits.
write.dropNote(db, { source: 'practice', content: 'Build step fails if DOCKER_REGISTRY is not exported first.', });// { id: 1 }One note pending. The spell has not changed.
-
04 The agent edits the spell
It adds the missing step at the top.
write.updateSpell(root, 'engineering/deploy-service', newContent); read.pendingChanges({ root }, 'engineering/deploy-service');// [{ spellPath: 'engineering/deploy-service', // changes: [{ status: 'modified', filePath: 'engineering/deploy-service/SKILL.md' }] }]The edit is on disk and still uncommitted. Rank stays at 1.
-
05 Seal the improvement
Sealing is the moment someone says the edit is proven.
write.seal({ root }, db, ['engineering/deploy-service'], 'Fix: document required env var for build step');// { commitHash: '26141d857cead85fd67855a7f7574ab7ed454764', // sealedPaths: ['engineering/deploy-service'], // ranks: { 'engineering/deploy-service': 2 } }A real git commit, and rank 2.
-
06 Distill the note
The note is now part of the spell.
write.distill(db, 1, 'engineering/deploy-service');read.pendingNotes(db).length // 0No notes pending.
-
07 Read the history and roll back
Say the new first step turns out to be wrong.
const log = read.history({ root }, 'engineering/deploy-service'); write.rollback({ root }, 'engineering/deploy-service', log.at(-1).hash);// history // 26141d8 Fix: document required env var for build step // c40ce35 inscribe engineering/deploy-service // { success: true, restoredRef: 'c40ce353576648772363ce66a2568bcf72d67d7c' }The first version is back on disk as an uncommitted change, and rank stays at 2 until that change is sealed.
After the run, the inspect_grimoire_item tool reported “Inspected spell engineering/deploy-service (Apprentice, rank 2).” with one seal to the next tier.
Tier names come from the library at read time. The tier table in the README gives different rank boundaries from the code, so this page only shows what the run returned.
Eight words for one skills folder
Files for content, git for history and rank, SQLite for the rest.
- Spell
- A learned procedure stored as
SKILL.md, YAML frontmatter plus a markdown body. - Chapter
- A folder of related spells, such as
engineering/. - Seal
- A git commit that marks a proven improvement. Rank is the number of seals.
- Tier
- A name computed from rank on every read.
- Note
- Raw evidence, such as an observation, a failure path or a correction, waiting to be distilled.
- Resonance
- A read-time signal for which spell is most worth improving next.
- Draft
- A proposed new spell held for review before it is inscribed.
- Catalogue
- A health pass over the grimoire covering staleness, dormancy, oversized spells and note routing.
Each of the three stores is optional, and the package degrades without any of them, as the README says. Without git there are no seals, so rank and rollback go too.
If skills already feel like a supply-chain risk
Marketplace skills have shipped with vulnerabilities, and a SKILL.md can tell an agent to do things you never asked for. grimoire does not fix that, and does not claim to.
- It validates the format of a
SKILL.md. It does not judge what the instructions say. - Every change to a spell is either uncommitted or a commit you can read, diff and roll back.
scout_skillscan adopt spells from outside sources. Treat those like any other code you pull in.- Eleven tools with JSON Schemas, among them
update_spell,hone_spell,manage_spellandrun_catalogue. - Node.js 24 or newer, because it uses the built-in
node:sqlite, and git on the machine for seals.
What it costs to add
- Runtime dependencies
- 0
- Node.js
- 24 or newer (node:sqlite)
- Size of dist/index.js, gzip
- 46.4 KB
- Import time
- about 9.4 ms
- Tests
- 872 passing
- Line coverage
- 95.6%
- Agent tools
- 11
Measured 2026-10-24 on the maintainer's machine with Node.js 24.14.0 against grimoire 0.3.0: size of the published dist/index.js at gzip -9, median of 11 cold imports, tests and coverage from the v0.3.0 tag.
Start from the README
import { DatabaseSync } from 'node:sqlite';
import { init, read, write } from '@ghostpaw/grimoire';
const db = new DatabaseSync(':memory:');
const root = '/path/to/my-grimoire';
// filesystem + SQLite tables + bare git repo with initial commit
init(root, db);
const { spell } = write.inscribe(root, db, {
name: 'deploy-service',
chapter: 'engineering',
content: '---\nname: deploy-service\ndescription: Deploy a service to production\n---\n\n# deploy-service\n\n## Steps\n\n1. Run `npm run build`\n2. Push to registry\n3. Apply manifests\n',
});
write.dropNote(db, {
source: 'practice',
content: 'Build step fails if DOCKER_REGISTRY is not exported first.',
});
write.seal({ root }, db, [`engineering/${spell.name}`], 'Fix: document required env var for build step');
const detail = read.getSpell(root, 'engineering/deploy-service', db);
To run it as an MCP server, add npx -y @ghostpaw/grimoire mcp to your client.
Read the READMEOpen the live demogrimoire on npm
All seven GhostPaw librariescodex, for memoryquestlog, for tasksaffinity, for contactssouls, for identityemail, for mailtelegram, for chats