Skip to main content

skillgram

CI Release Site Python 3.9+ No dependencies

skillgram

Skill management for AI agents: one skill library, linked into every coding agent.
No copies, no drift, no "which folder does this harness read?".

skillgram is a skill hub — a registry of SKILL.md files that actually lives in one place on disk — plus the admin layer that keeps every agent pointing at it. Claude Code, Codex, Cursor, Hermes, Reasonix, Gemini CLI, OpenCode, Kiro, Qwen Code, Aider, Copilot and anything else that reads skills all see the same library.

~/.agents/skills/<category>/<skill>/SKILL.md   the hub (the only real copy)
~/.claude/skills/<skill>                       -> junction to the hub (symlink off Windows)
~/.codex/skills/<skill>                        -> junction to the hub
%APPDATA%/Reasonix/skills/<skill>              -> junction to the hub

No work skills are bundled — it is the plumbing, not the content. The only skill in this repo is skills/skillgram-report, which teaches an agent how to report a bug or a gap.

What this is, in other words

If you were looking for a way to manage skills for AI agents — an admin layer over the skills your coding agents load, a skill registry / skill library / skill manager, or a way to share one set of SKILL.md files between Claude Code, Codex, Cursor and the rest without copying anything — this is that tool. Per-project scope, an MCP server so the agent can ask the hub, links instead of copies, and no LLM in the loop unless you ask for one.

It is not a prompt manager, a memory store, or an embeddings index. Those are different things and there are good tools for them (Engram, for one, is credited below).

Why

Linking by hand once is easy; keeping fifty agents in sync is not. Agents re-create their own copies, rename folders, and a new hub skill never shows up by itself. skillgram turns that into one idempotent command — and with watch, into no command at all.

Install

The whole machine in one idempotent command, plus a copy-paste brief you can hand to a fresh agent session: INSTALL.md.

python skillgram.py install --dry-run   # what it would do, nothing written
python skillgram.py install             # harness -> hub -> MCP (delegated) -> propagate

From source — this is not on PyPI yet, so pip install skillgram would fail:

git clone https://github.com/Xhuk/skillgram
cd skillgram
python skillgram.py --help
# or install it as a command:  pip install .

Stdlib only (Python 3.9+), no dependencies. Junctions on Windows, symlinks on macOS/Linux. CI runs the suite on Linux for Python 3.9, 3.11 and 3.13.

Quick start

skillgram doctor            # what harnesses and native skills exist here (read-only)
skillgram sync              # make the disk match the hub: links only, idempotent
skillgram status            # drift, right now
skillgram install --dry-run # the whole machine: hub + MCP + project scope

How it works

sync only adds links. It never copies, moves, adopts or deletes a skill an agent already has: a native skill with the same name as a hub skill is skipped and reported as a collision, never overwritten. doctor tells you how many native skills each harness has before you touch anything.

For harnesses that scan a single level, each agent also gets one link per category (skills/<category> → hub/<category>), so the hub stays browsable.

precedence is the cooperative alternative: it declares the hub first in each harness' own config (skills.paths for Reasonix, skills.external_dirs for Hermes) with a *.skillgram-bak-<timestamp> backup next to the file. Delete skillgram and every harness keeps exactly what it had.

The hard-mount model — one junction for the whole skills/ directory — is deliberately not the default: a rimraf skills or a harness uninstall would wipe the library of every agent.

Project scope (engram-style)

The hub is the library; a project is what an agent actually needs while working in it.

skillgram init my-api                 # <project>/.agents/config.json
skillgram use archify ad3 --project . # link + manifest entry, idempotent
skillgram mount --apply               # materialize that set where each harness looks
skillgram project-status              # healthy / stale / broken / missing links
<project>/.agents/config.json   {"project_name": "my-api"}
<project>/.agents/skills/<name> link to the hub
<project>/.agents/skills.json   manifest: category, source, hash, promoted_at, last_used

Resolution order, same as engram: --project → SKILLGRAM_PROJECT → nearest .agents/config.json up to the git root → cwd. If it cannot resolve, it says so; it never guesses. mount writes the project's set into every harness layout that reads project-level skills (.agents/skills, .claude/skills, .codex/skills, .cursor/skills, .gemini/skills, .github/skills, .hermes/skills, .kiro, .qwen, .aider, .opencode), and --prune-global goes strict: the harness homes stop seeing the hub at all (only links that resolve into the hub are removed; native skills stay).

project-status also flags a skill that lives both in the hub and as a real copy inside the project.

The MCP server: let the agent ask

skillgram mcp               # stdio server, 5 tools
skillgram mcp --read-only   # the agent can query, not use/propose

skillgram_search, skillgram_missing, skillgram_use, skillgram_status, skillgram_propose. missing answering {"found": false} is the contract that says do not invent a skill, tell the user. install registers this server through each harness' own CLI and reads the config back afterwards — an exit code is not proof.

The LLM, only where it earns its place

A connected OpenAI-compatible model is used in exactly three places, always proposing a JSON plan that skillgram validates and you approve: bootstrap (choose a project's initial set from the repo's signals), propose (draft a skill that does not exist) and port (translate a skill wired to another agent into agents/<harness>.md). Every decision is stamped by: llm:<model> in the manifest and logged to ~/.agents/skillgram-llm.log. --no-llm and SKILLGRAM_LLM=off turn it off.

SKILLGRAM_LLM_BASE_URL   default https://api.deepseek.com/v1
SKILLGRAM_LLM_MODEL      default deepseek-flash
SKILLGRAM_LLM_API_KEY    or DEEPSEEK_API_KEY / OPENAI_API_KEY

A project with a scope needs no LLM at all: that is régime, where skillgram only serves the set and answers "do we have something for this?".

Finding, judging and retiring skills

skillgram index                                   # FTS5 index of the hub
skillgram search "docker deploy vps" --limit 5
skillgram missing "quote a mortgage"              # found | not found, with candidates
skillgram review --days 90                        # never used / stale
skillgram review --days 30 --fail-if-stale        # CI gate: exit 1 when the set is stale
skillgram pin <skill>...                          # never reported as stale
skillgram retire <skill>                          # -> <hub>/_retired/ + tombstone, never deleted

use stamps last_used, use_count and last_used_by. _retired/ keeps the content plus _retired.json (who, when, why, hash) and is never treated as a category.

Moving a hub around

skillgram export hub.tar.gz     # every skill + hub.json of hashes
skillgram import hub.tar.gz     # verifies the hashes; --apply to materialize
skillgram diff <skill> --against <path>   # divergence between two copies
skillgram git init --apply      # the hub as a repo (adds a .gitignore for the index)
skillgram git pull --apply      # ff-only: git resolves conflicts, skillgram never guesses

The hub is the asset. With git under it, "sync between machines" is git's job.

What it does NOT do (on purpose)

  • It never copies, moves or deletes a native skill. Collisions are reported, not resolved.
  • It never edits a harness config by hand: MCP registration goes through that harness' CLI.
  • It never guesses which harness is asking (SKILLGRAM_HARNESS → --harness → process tree → unknown, and it says so).
  • It never publishes a skill nobody approved.
  • It is not a memory store, a prompt library, or an embeddings index.

Safety

  • Links only. Dead-link cleanup only touches links that resolve inside the hub — never content, never a real directory.
  • onboard copies and verifies the hash before reporting success; the original only moves to ~/.agents/skillgram-quarantine/<harness>/<skill> with --replace-natives, and never to the bin.
  • Nothing in your repos changes unless you run init, use, mount or install --root.
  • Preview anything: install --dry-run, sync --dry-run, onboard --json --plan plan.json.

Report a bug or a gap

Two different things, two different channels — mixing them is how a roadmap turns into noise. A gap (the hub has nothing for a capability) is a request: skillgram_missing answers found:false, the agent offers propose, and the query is recorded in the demand log (skillgram demand ranks what nobody could answer). A bug (skillgram itself failed) is one JSON line with ok:false and a non-zero exit — never dressed up as a skill.

The repo ships both forms in .github/ISSUE_TEMPLATE/ (bug_report.yml, skill_request.yml) and the skill that walks an agent through them: skills/skillgram-report.

Commands

Command What it does
doctor harnesses, native skills, collisions, dead/missing links. Read-only.
status / sync drift now / apply the desired state. --verify, --dry-run.
install / propagate the whole machine / the repo sweep, with a ledger.
onboard / adopt consolidate what harnesses already have (LLM optional) / cooperative adoption.
init / use / unuse / mount / project-status the project scope.
index / search / missing / demand find, or learn what is missing.
review / pin / retire lifecycle.
export / import / diff / git move a hub around.
mcp stdio MCP server (--read-only).
lint quality gate: frontmatter, name, description, size.
watch / daemon / install-autostart keep it in sync by itself.

skillgram --help lists all of them (33); skillgram <command> --help is the contract for one. Every command prints exactly one JSON line on stdout (--json for the human ones too). Exit code 0 healthy, 1 drift/error, 2 bad invocation.

{"ok":true,"op":"status","version":"1.2.0","hub":"C:\\Users\\me\\.agents\\skills","skills":842,"categories":18,"nested":12,"agents":50,"drift":0,"watching":false,"missing":0,"mispointed":0,"dead":0,"skipped":2}

Known gaps (documented, not implemented)

Compared with Engram (Gentleman-Programming), which is a service with a full lifecycle, these remain open by decision. When one closes, the line goes away.

  1. No cross-machine sync. export/import is manual; there is no transport and no conflict resolution between two hubs. (git under the hub is the workaround.)
  2. No merge of divergent skills. Same name + different content fails; the merge is a human (or LLM) decision, then diff tells you exactly what differs.
  3. No real usage telemetry. use_count counts explicit promotions and MCP use calls; skillgram does not observe which skills an agent actually reads.
  4. Lexical search only. FTS5 has no embeddings, so cross-language synonyms miss (measured: "cotizar credito hipotecario" → one weak hit).
  5. No permissions/profiles. No agent/admin split: anyone with a shell can publish or retire. mcp --read-only removes the write tools from a session, but it is a per-server switch, not a role.
  6. No taste gate. lint checks shape and is a hard gate in propose, but nothing judges whether a skill is useful: no eval, no grading, no dry run of the skill itself.
  7. No scheduled review. review is manual; put review --fail-if-stale in your cron/CI.
  8. MCP is tools-only. No resources, no prompts, no sampling.

Language

Everything user-facing is English: CLI output, error messages and every JSON key (promoted, already_present, missing_links, native, collisions, signals, selection, ...). That is the API other tools read. Internal code comments and docstrings are still partly Spanish; translating them is tracked as cleanup, not as behaviour.

Prior art and credits

skillgram is original code (MIT, stdlib only), but the ideas are not mine and pretending otherwise would be dishonest. These shaped it — if one of them is what you actually need, use it directly:

  • Engram — the project-scope resolution order (--project → env → nearest .agents/config.json up to the git root → cwd), the "one store, a per-project view" model, and the CLI-plus-MCP split this repo copied the shape of.
  • Agent Skills / SKILL.md (Claude Code, then everyone else) — the SKILL.md + YAML frontmatter format and the .claude/skills convention every other harness imitated. skillgram does not invent a format: it links yours.
  • Codex, Cursor, Gemini CLI, Kiro, Qwen Code, Aider, OpenCode, Copilot — their project-level skills/ layouts are the reason mount knows eleven of them.
  • ECC — a 291-skill pack that lives next to this hub, and the reason every feature here is tested against "does this still hold at ~850 skills?".
  • Unix, in the only sense that matters: one directory is the truth, every agent a client.

No code was copied from any of them. Where a behaviour was learned from another tool, the section that documents it says so. If your project belongs in this list, open an issue — credit is cheap, respect is not.

Where the detail lives

You want Read
to install on a machine, or hand it to an agent INSTALL.md
what changed, version by version CHANGELOG.md
the install flow as a diagram docs/diagrams/skillgram-install.html
the rules this repo holds itself to AGENTS.md
how to report something skills/skillgram-report

Tests

python -m unittest discover -s tests -v

License

MIT.

Metadata

Release files for skillgram 1.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for skillgram 1.2.0
File Size Uploaded
skillgram-1.2.0.tar.gz 61.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for skillgram 1.2.0
File Interpreter ABI Platform
skillgram-1.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 114.0 kB

Release files / skillgram-1.2.0.tar.gz

Download URL skillgram-1.2.0.tar.gz
Size 61.1 kB
Tags Source
SHA-256 checksum
How to use checksums
165fd38e32f2b67d458780e333af1704815fcf4e3398f9da756c5ab8870dd5fd
BLAKE2b-256 checksum
How to use checksums
80d3eeff65e49f9f5138143d8d2fd3d7eac2e1a1c47e865673a5f8130c3f1e09
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Release files / skillgram-1.2.0-py3-none-any.whl

Download URL skillgram-1.2.0-py3-none-any.whl
Size 52.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
72494c13cf72409d3c5b96217d37b1949f9204d3be4ba490f4cb1ba08e968bb8
BLAKE2b-256 checksum
How to use checksums
89dcfcdcb3c06b81cc8745d77cc027096c650c9a59f0fe3caa4d7fe90fef1909
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Release history Release notifications | RSS feed

1.4.0

2 release files

1.3.0

2 release files

1.2.2

2 release files

1.2.1

2 release files

This release

1.2.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page