{"id":50529687,"url":"https://github.com/funsaized/docs-to-claude-skills","last_synced_at":"2026-06-03T12:01:17.033Z","repository":{"id":356089414,"uuid":"1230988991","full_name":"funsaized/docs-to-claude-skills","owner":"funsaized","description":"Author your project's agent skills as plain markdown in docs/, and have them materialize as both Claude Code skills and OpenAI Codex skills kept in sync automatically via symlinks.","archived":false,"fork":false,"pushed_at":"2026-05-28T09:32:57.000Z","size":33,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-28T11:11:26.853Z","etag":null,"topics":["agent-skills","ai-agents","anthropic","claude-code","claude-skills","cli","codex","llm-tools","nodejs","npx","openai-codex","prompt-engineering","zero-dependencies"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/funsaized.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-06T14:13:00.000Z","updated_at":"2026-05-28T09:33:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/funsaized/docs-to-claude-skills","commit_stats":null,"previous_names":["funsaized/docs-to-claude-skills"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/funsaized/docs-to-claude-skills","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/funsaized%2Fdocs-to-claude-skills","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/funsaized%2Fdocs-to-claude-skills/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/funsaized%2Fdocs-to-claude-skills/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/funsaized%2Fdocs-to-claude-skills/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/funsaized","download_url":"https://codeload.github.com/funsaized/docs-to-claude-skills/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/funsaized%2Fdocs-to-claude-skills/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33863264,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-03T02:00:06.370Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-skills","ai-agents","anthropic","claude-code","claude-skills","cli","codex","llm-tools","nodejs","npx","openai-codex","prompt-engineering","zero-dependencies"],"created_at":"2026-06-03T12:01:16.214Z","updated_at":"2026-06-03T12:01:17.018Z","avatar_url":"https://github.com/funsaized.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# docs-to-claude-skills\n\n[![npm version](https://img.shields.io/npm/v/docs-to-claude-skills.svg)](https://www.npmjs.com/package/docs-to-claude-skills)\n[![npm downloads](https://img.shields.io/npm/dm/docs-to-claude-skills.svg)](https://www.npmjs.com/package/docs-to-claude-skills)\n[![license](https://img.shields.io/npm/l/docs-to-claude-skills.svg)](./LICENSE)\n[![node](https://img.shields.io/node/v/docs-to-claude-skills.svg)](https://nodejs.org)\n\n\u003e One markdown file. Two AI agents. Zero dependencies. Zero duplication.\n\nAuthor your team's agent skills as plain markdown anywhere under `docs/`, and have them\nmaterialize as both [Claude Code skills](https://docs.claude.com/en/docs/claude-code/skills)\nand [OpenAI Codex skills](https://developers.openai.com/codex/skills) — kept\nin sync automatically via symlinks.\n\n```\ndocs/database.md  ──┬──▶  .claude/skills/database/SKILL.md   (Claude Code)\n                    └──▶  .agents/skills/database/SKILL.md   (OpenAI Codex)\n```\n\nEdit the doc once, both agents see the change. No duplicate copies, no\n\"which version is current\" confusion.\n\nSecurity-conscious by default:\n\n- **Zero runtime dependencies** — no dependency tree to audit, pin, or patch.\n- **Local-only execution** — reads markdown from your repo and writes symlinks\n  or copies under `.claude/skills/` and `.agents/skills/`.\n- **No network calls, telemetry, or remote services** in the generator itself.\n\n---\n\n## Why this exists\n\nClaude Code and OpenAI Codex agree on the SKILL.md contract:\n\n| Field             | Claude Code                          | OpenAI Codex                         |\n| ----------------- | ------------------------------------ | ------------------------------------ |\n| File              | `SKILL.md`                           | `SKILL.md`                           |\n| Required metadata | `name`, `description` (frontmatter)  | `name`, `description` (frontmatter)  |\n| Repo location     | `.claude/skills/\u003cname\u003e/`             | `.agents/skills/\u003cname\u003e/`             |\n\nSame file, two locations. Rather than maintain duplicates, keep the canonical\ncontent in `docs/` and let this tool wire up the symlinks. Your existing repo\ndocumentation *becomes* your skill library.\n\n---\n\n## Install\n\nPublished on npm: [`docs-to-claude-skills`](https://www.npmjs.com/package/docs-to-claude-skills).\nZero runtime dependencies.\n\n```bash\n# project-local (recommended)\nnpm install --save-dev docs-to-claude-skills\n\n# or with your package manager of choice\npnpm add -D docs-to-claude-skills\nyarn add -D docs-to-claude-skills\nbun add -d docs-to-claude-skills\n\n# or one-shot, no install\nnpx docs-to-claude-skills\n\n# or globally\nnpm install -g docs-to-claude-skills\n```\n\nRequires Node.js ≥ 18.\n\n## Quick start\n\n```bash\n# 1. install (or use npx)\nnpm install --save-dev docs-to-claude-skills\n\n# 2. scaffold a starter doc\nnpx docs-to-skills init\n\n# 3. generate skills for both Claude Code and Codex\nnpx docs-to-skills\n```\n\nThat's it. Re-run `npx docs-to-skills` anytime you add or edit a doc.\n\n## Running from source\n\nYou don't need to install from npm — the tool has zero runtime dependencies,\nso a clone or a direct `npx` from GitHub is enough.\n\n### Option A: one-shot via npx (no clone)\n\n```bash\nnpx github:funsaized/docs-to-claude-skills --cwd .\n```\n\n`npx` fetches the repo, runs the bin, and cleans up. Good for trying it out\nor wiring into CI without committing a dependency.\n\n### Option B: clone + run\n\n```bash\ngit clone https://github.com/funsaized/docs-to-claude-skills.git\ncd docs-to-claude-skills\nnode bin/docs-to-skills.mjs --help\n```\n\nUse the `--cwd` flag to target any other project from the clone:\n\n```bash\nnode /path/to/docs-to-claude-skills/bin/docs-to-skills.mjs --cwd ~/my-project\n```\n\nThis is handy when you're hacking on the tool itself and want to try changes\nagainst a real repo without publishing.\n\n### Option C: clone + npm link (global `docs-to-skills`)\n\n```bash\ngit clone https://github.com/funsaized/docs-to-claude-skills.git\ncd docs-to-claude-skills\nnpm link\n\n# now available globally, pointing at your clone\ncd ~/my-project\ndocs-to-skills\n```\n\nEdits inside the clone are picked up immediately on the next invocation —\nno rebuild step (the source is plain ESM `.mjs`, no compile).\n\n### Running tests\n\n```bash\nnpm test\n```\n\n15 tests under `test/`, all using Node's built-in test runner. No deps to\ninstall.\n\n## Authoring a skill\n\nDrop a markdown file in `docs/` with YAML frontmatter:\n\n```markdown\n---\nname: postgres-migrations\ndescription: Use when the user asks to add, run, or rollback a database migration. Triggers on \"migration\", \"drizzle\", \"db:migrate\", schema changes.\n---\n\n# Postgres migrations\n\nWorkflow:\n\n1. Edit `src/database/schema.ts`\n2. Run `bun db:add-migration \u003cname\u003e`\n3. Run `bun db:migrate`\n\n...\n```\n\nRun `docs-to-skills` and it shows up at:\n- `.claude/skills/postgres-migrations/SKILL.md`\n- `.agents/skills/postgres-migrations/SKILL.md`\n\nThe `description` is what each runtime uses to decide *when* to activate the\nskill. Be concrete with keywords your team actually says.\n\n---\n\n## Adopting in an existing project\n\nGot a repo with a `docs/` folder full of architecture notes, runbooks, and\nhow-tos? Most of them already make great agent skills — they just need\nfrontmatter.\n\n**Step 1.** Add a single dev dependency:\n\n```bash\nnpm install --save-dev docs-to-claude-skills\n```\n\n**Step 2.** Pick the docs you want exposed as skills and add frontmatter to\nthe top of each one:\n\n```diff\n+---\n+name: deploy-staging\n+description: Use when deploying to staging, debugging deploys, or asked about the staging release process.\n+---\n # Deploying to staging\n ...\n```\n\nFiles without frontmatter are quietly skipped, so you can roll this out\nincrementally. Start with two or three high-value docs; add more as you go.\n\n**Step 3.** Add a script to `package.json`:\n\n```json\n{\n  \"scripts\": {\n    \"skills\": \"docs-to-skills\"\n  }\n}\n```\n\n**Step 4.** Ignore the generated directories (they're symlinks, regeneratable):\n\n```gitignore\n.claude/skills/\n.agents/skills/\n```\n\nOr commit them — your call. Symlinks are version-controlled fine on macOS and\nLinux. On Windows, prefer `--mode copy` and commit the result.\n\n**Step 5.** Run it locally and in CI:\n\n```bash\nnpm run skills\n```\n\nWire it into a `postinstall` or pre-commit hook if you want it always fresh:\n\n```json\n{\n  \"scripts\": {\n    \"postinstall\": \"docs-to-skills --quiet\"\n  }\n}\n```\n\nThat's the whole adoption path. Existing docs keep working as docs; the ones\nwith frontmatter additionally become skills.\n\n---\n\n## CLI\n\n```\ndocs-to-skills [command] [options]\n\ncommands\n  generate              generate skills (default)\n  init                  scaffold docs/example.md\n\noptions\n  --docs \u003cdir\u003e          source docs directory (default: ./docs)\n  --target \u003ct\u003e          claude | codex | both (default: both)\n  --mode \u003cm\u003e            symlink | copy (default: symlink)\n  --clean               remove all managed skills before regenerating\n  --dry-run             preview actions without modifying anything\n  --quiet               suppress per-file output\n  --cwd \u003cdir\u003e           project root (default: process.cwd())\n  -h, --help\n```\n\n### Targeting one runtime\n\n```bash\ndocs-to-skills --target claude       # only .claude/skills/\ndocs-to-skills --target codex        # only .agents/skills/\ndocs-to-skills --target claude,codex # both (same as --target both)\n```\n\n### Copy instead of symlink\n\nUseful on Windows without developer mode, on filesystems that disallow\nsymlinks, or when you want to commit the resulting `SKILL.md` files\nverbatim:\n\n```bash\ndocs-to-skills --mode copy\n```\n\nSymlink mode is the default and falls back to copy automatically if symlink\ncreation is denied (`EPERM`/`EACCES`).\n\n### Cleaning up\n\n```bash\ndocs-to-skills --clean    # nuke and rebuild\n```\n\n`--clean` only touches skills whose `SKILL.md` is a symlink pointing into\nyour `docs/` directory — hand-written or third-party skills under\n`.claude/skills/` and `.agents/skills/` are left alone.\n\n---\n\n## Programmatic API\n\n```js\nimport { generateSkills } from 'docs-to-claude-skills'\n\nconst stats = await generateSkills({\n  cwd: process.cwd(),\n  docsDir: 'docs',\n  targets: ['claude', 'codex'],\n  mode: 'symlink',\n  clean: false,\n  dryRun: false,\n})\n\nconsole.log(stats)\n// { created: 4, updated: 0, unchanged: 0, skipped: 1, removed: 0, actions: [...] }\n```\n\nOther exports:\n\n- `parseFrontmatter(content)` → `{ data, body, raw } | null`\n- `isValidSkillFrontmatter(data)` → `boolean`\n- `TARGETS` → metadata for the supported runtimes\n- `resolveTargets(input)` → normalize a target arg\n- `targetSkillsDir(cwd, targetId)` → resolve the output directory\n\n---\n\n## How it works\n\n1. Scan `docs/*.md`.\n2. Parse YAML frontmatter; require `name` and `description`.\n3. For each target runtime, ensure `\u003ctarget-dir\u003e/\u003cname\u003e/SKILL.md` is a symlink\n   pointing to the source doc. If one exists with the right target, leave it\n   (no churn). If wrong, replace it.\n4. Prune stale entries — but **only** entries whose `SKILL.md` symlink resolves\n   into your `docs/` directory. Anything else is left alone.\n\nThe symlink-only-prune rule is what makes this safe to run alongside\nhand-authored skills. Your `agent-creator` skill from another plugin won't get\nnuked because its `SKILL.md` doesn't link into `docs/`.\n\n---\n\n## FAQ\n\n**Why symlinks?** A copy means you have two sources of truth and one will go\nstale. A symlink means edits to `docs/database.md` are instantly visible to\nthe agent the next time it loads the skill. Use `--mode copy` if your\nfilesystem or VCS workflow needs literal files.\n\n**Will the agent auto-detect new skills?** Both Claude Code and Codex scan\ntheir skills directories on session start; some pick up changes without a\nrestart, some don't. If a new skill doesn't show up, restart the session.\n\n**Can the same doc be a skill in one runtime but not the other?** Not via\nthis tool. The contract is identical between Claude Code and Codex; if you\nwant runtime-specific instructions, write two docs.\n\n**Does it support nested skill assets (`scripts/`, `references/`)?** Not yet.\nToday each skill is a single `SKILL.md`. The directory structure is in place,\nso adding sibling files is a small extension.\n\n**Why not just publish a package and `import` skills?** Skills are filesystem\nartifacts — agents discover them by scanning conventional paths. This tool\njust maintains those paths from a single source.\n\n---\n\n## Prior art / acknowledgments\n\nThe single-source-of-truth pattern with symlink-into-docs is taken from the\nTamagui Takeout starter kit's `tko\nskills generate` command. This is a generalized, dependency-free\nre-implementation that also targets OpenAI Codex.\n\n## License\n\nMIT © funsaized\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffunsaized%2Fdocs-to-claude-skills","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffunsaized%2Fdocs-to-claude-skills","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffunsaized%2Fdocs-to-claude-skills/lists"}