JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 45
  • Score
    100M100P100Q87620F

Package Exports

  • @botdocs/cli

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@botdocs/cli) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

botdocs

The official CLI for BotDocs — author, publish, install, and sync agent skills.

BotDocs is the registry teams use to share agent skills across the agents their developers run (Claude Code, Cursor, Codex, ChatGPT). This CLI is the fastest way to install a team's skills, stay in sync, and publish your own.

Install

Requires Node.js 20+. Don't have it? Install from nodejs.org →

# one-off
npx @botdocs/cli <command>

# global (preferred — gives you the `botdocs` command)
npm i -g @botdocs/cli
# or
pnpm add -g @botdocs/cli

After a global install the binary is just botdocs:

botdocs --help

Quick start

# log in (opens your browser, sign in with any provider, one time)
botdocs login

# install a team's shared skills
botdocs install @teamco/eng-skills

# stay in sync with your team
botdocs sync

# scaffold and publish your own skill
botdocs init my-skill
botdocs validate my-skill/
botdocs publish my-skill/

Commands

Command Purpose
init [name] Scaffold a new skill directory (canonical multi-ecosystem layout by default; --spec for the legacy SPEC scaffold).
compile <path> Generate per-ecosystem skill drafts from a canonical source (BYOK).
edit <ref> LLM-assisted revision of a published skill ecosystem file (BYOK).
validate <source> Pre-publish structural check on a directory or file.
search <query> Search the public registry.
publish <source> Publish from a file, directory, or zip archive — or pass @user/slug to mark an existing draft live.
unpublish <ref> Hide a published BotDoc from /explore (sets the draft flag back).
delete <ref> Delete a BotDoc. Drafts are hard-deleted (row + all children); published BotDocs are soft-deleted (hidden, version history preserved).
install <ref> Install a skill or bundle (auto-detects destinations).
sync [ref] Check installed skills/bundles for updates and apply.
uninstall <ref> Remove an installed skill or bundle.
list Show installed skills and bundles.
ingest [path] Scan your system (or a directory), detect existing skills, upload as drafts.
team list / show / create / add / remove / push / unpush Manage teams: shared skill libraries for your org.
undo Restore the most recent backup run (reversible).
backups list / restore / diff / clear Browse, restore, diff, and prune backup runs.
check-updates Check installed refs for available updates (1h cached).
install-instructions [target] Write/refresh AGENTS.md (or install a shell hook with --shell-hook).
login Authenticate by opening your browser; pass --token bd_xxx for headless/CI (--sync-library enables /library).
whoami Show the currently authenticated user.

Every command accepts --json for machine-readable output.

Run botdocs <command> --help for full flags on any command.

Look & feel

botdocs login and botdocs sync are interactive and live by default — a cyan-to-violet gradient brand mark, an animated polling spinner, and per-file status rows that update in place. The CLI auto-detects when it's running in a real terminal vs. a piped/CI environment and renders the right thing without any flags. If you prefer plain output even on a TTY (screen-reader friendly, or just calmer), pass --no-ink to either command:

botdocs login --no-ink
botdocs sync --no-ink

botdocs sync --json keeps emitting the same machine-readable JSON it always has — it never touches the Ink renderer.

Configuration

Variable Default Purpose
BOTDOCS_API_URL https://botdocs.ai Override the registry API endpoint (useful for local development).

Auth is stored at ~/.botdocs/auth.json after botdocs login. Delete it to log out. The default botdocs login opens your browser at /cli-auth, where you sign in with whichever provider you prefer (GitHub, Google, or email-OTP) and confirm the terminal session. For non-interactive environments, mint a token at /settings/tokens and run botdocs login --token bd_xxx instead.

Teaching agents to use this CLI

Run once in any project to drop a managed AGENTS.md block that teaches Claude Code, Cursor, Codex, and Copilot how to invoke the CLI:

botdocs install-instructions

If AGENTS.md already exists with markers from a prior run, the block is refreshed in place. Use --print to dump the snippet to stdout instead of writing.

Library + update notifications

Enable the personalized Library page at https://botdocs.ai/library:

botdocs login --sync-library

After install/sync/uninstall, the CLI uploads a sanitized snapshot (refs + versions only — never file contents) so the web library can show what you have, what your team has, and what's new. Privacy-conscious users can leave the flag off; the CLI no-ops silently and the page shows an onboarding banner with the command.

Set up a shell hook so new terminals show pending update notices:

botdocs install-instructions --shell-hook

Detects your shell (zsh/bash/fish), writes a marker-delimited block to the rc file, and runs botdocs check-updates --quiet on shell open. Silent when there's nothing to report. Remove with --remove-shell-hook when you want it gone.

Or check manually anytime:

botdocs check-updates           # full list of pending updates
botdocs check-updates --quiet   # one-liner only when updates pending

check-updates caches the response for 1 hour so opening many terminals in quick succession doesn't hammer the API.

Multi-ecosystem authoring (BYOK)

Authors write a skill once in their preferred ecosystem (Claude Code, Cursor, etc.) and use their own LLM key to generate the other formats locally. The server never runs inference — your file content stays on your machine.

export BOTDOCS_ANTHROPIC_KEY=sk-ant-...    # or BOTDOCS_OPENAI_KEY=sk-...

botdocs init my-skill                       # canonical scaffold by default:
                                            # claude-code source + ecosystems list
                                            # in botdocs.json

# edit claude-code/commands/my-skill.md

botdocs compile my-skill/                  # generates claude/SKILL.md,
                                            # cursor/rules/my-skill.mdc,
                                            # codex/my-skill.md,
                                            # copilot/instructions/my-skill.instructions.md,
                                            # windsurf/rules/my-skill.md,
                                            # gemini/instructions/my-skill.md,
                                            # antigravity/skills/my-skill.md,
                                            # opencode/instructions/my-skill.md, etc.

botdocs publish my-skill/                  # auto-compiles if stale; --no-compile to skip

To revise a published file later via the LLM:

botdocs edit @you/my-skill --ecosystem cursor
# enter your change in plain English
# review the diff, accept to push as a draft
# visit botdocs.ai/@you/my-skill to publish

compile and edit both prefer BOTDOCS_ANTHROPIC_KEY (Claude Haiku) when set, otherwise fall back to BOTDOCS_OPENAI_KEY (GPT-4o mini). Use --key-env <NAME> to point at a different env var.

Teams

A team is a curated library of skills shared across its members. Skills stay user-owned; teams pin skills to indicate "these are the ones we use." Members install/sync the pinned set automatically.

botdocs team create teamco --name "Team Co"          # admin-only side: create
botdocs team add teamco @bob --role write            # add a member
botdocs team push teamco @alice/eng-review-skill     # pin a skill (WRITE+)
botdocs team push teamco @alice/eng --version 3      # pin to a specific version

botdocs team list                                    # what teams am I in?
botdocs team show teamco                             # members + pinned skills
botdocs sync                                         # pulls personal + team pins

botdocs sync walks the team's pinned skills and installs/updates them locally, marking the lockfile entry with the team they came from. Pinning is curation, not access control — skills are public in v1.

Skills + bundles

Skills are bundles of files that ship to specific destinations on disk (Claude skills, Cursor rules, Claude Code commands). A bundle is a curated playlist of skills for an org or team. Two key flows:

Install a team's bundle — files land in the right places automatically:

botdocs install @teamco/eng-skills

Stay current — walks the lockfile, applies clean updates, prompts on conflicts (skip or overwrite with double confirm):

botdocs sync

botdocs list shows what you have installed; botdocs uninstall <ref> removes it.

Safety: backups before overwrite

install and sync will never silently clobber a hand-written file at a colliding destination. Before any overwrite of a file the lockfile doesn't claim as "ours and unchanged," the original is copied to a timestamped backup directory:

  • Project-scoped files → <cwd>/.botdocs-backup/<ISO-ts>/<relative-path>
  • Global-scoped files (e.g. ~/.claude/skills/...) → ~/.botdocs/backup/<ISO-ts>/<flattened-path>

A single CLI invocation reuses the same <ts> folder, so all backups from one run live together. A one-line warning is printed to stdout for each backup taken. If the existing file matches a fingerprint we recorded — i.e. we wrote it ourselves and the user hasn't edited it since — no backup is taken (there's nothing to save). Backup failures (e.g. permission errors) print a warning but don't block the install.

Pass --no-backup on install or sync to opt out — useful in CI where backups are noise.

Undo and the backups surface

Backups are reversible. If you realize an install or sync clobbered something you wanted to keep:

botdocs undo              # restore the most recent backup run
botdocs undo --dry-run    # preview without writing
botdocs undo --yes        # skip the confirm prompt (scripts)

Before writing the restored content, the CURRENT state at each path is itself backed up under a new timestamp — so botdocs undo is reversible. Running it twice in a row swaps the state back. Pass --no-backup to skip the pre-backup (loses reversibility).

For more granular control, the backups group browses, partial-restores, diffs, and prunes:

botdocs backups list                              # every run, newest first
botdocs backups list <ts>                         # files in a specific run
botdocs backups restore <ts>                      # restore the full run
botdocs backups restore <ts> --files a.mdc,b.mdc  # restore a subset
botdocs backups diff <ts> <relpath>               # diff backup vs current
botdocs backups clear                             # delete all runs (confirm)
botdocs backups clear --older-than 30d            # delete runs older than N days
botdocs backups clear --dry-run                   # preview without deleting

Each backup run records a manifest.json sidecar mapping original→backup, so restoration is unambiguous even when global-scope filenames flatten ambiguously (e.g. paths containing _).

Authors who want to share their existing collection of skills run botdocs ingest <path> — the CLI walks the directory, detects each skill across all 11 supported ecosystems (claude, claude-code, claude-code-agents, cursor, chatgpt, codex, copilot, windsurf, gemini, antigravity, opencode), and uploads them as drafts in your BotDocs account for review before publishing.

For nested ecosystems (claude SKILL.md, claude-code-agents AGENT.md), ingest also sweeps adjacent files inside the skill directory — scripts/*.sh, templates/*, reference docs — and uploads them with their original POSIX file mode so the executable bit on helper scripts survives the round-trip. botdocs install restores the mode on disk.

Per-skill size limits (enforced both client- and server-side):

  • 64 KB per file
  • 512 KB total per skill
  • 25 files per skill

Binary files are detected by a null-byte sniff on the first 8 KB and skipped with an inline warning. Cap violations warn and skip without failing the ingest. Skipped dirs: node_modules/, .git/, dist/, build/, .next/, .turbo/, __pycache__/, venv/, .venv/, plus all dotfiles, .DS_Store, *.log, *.lock.

By default ingest expects the canonical BotDocs layout (e.g. claude-code/commands/<slug>.md, cursor/rules/<slug>.mdc). If your files live in real on-disk locations instead, point --from-tool=<ecosystem> at them and every matching file becomes a draft for that ecosystem:

# Ingest all your Claude Code commands directly:
botdocs ingest --from-tool=claude-code ~/.claude/commands/

# Ingest a project's Cursor rules:
botdocs ingest --from-tool=cursor .cursor/rules/

# Ingest GitHub Copilot instructions (the .instructions.md extension is
# stripped from the slug automatically):
botdocs ingest --from-tool=copilot .github/instructions/

The upload always uses the canonical BotDocs filename, so when someone else botdocs installs the resulting skill it lands in the right on-disk location.

Publishing drafts (and taking them back down)

botdocs ingest and botdocs edit both create drafts — hidden from /explore, 404 for everyone but the author. To flip a draft live:

botdocs publish @me/my-skill      # → ✓ Published @me/my-skill
botdocs publish @me/my-skill --json
# → {"ok":true,"ref":"@me/my-skill","status":"published"}

botdocs publish is overloaded by argument shape: a local path (./my-skill/) runs the existing upload flow unchanged; a @user/slug ref toggles the publish flag via the API.

To hide a published BotDoc again (e.g. you want to revise it without the in-progress version visible publicly):

botdocs unpublish @me/my-skill          # prompts to confirm
botdocs unpublish @me/my-skill --yes    # skip the prompt (scripts/CI)
botdocs unpublish @me/my-skill --json   # implies --yes, emits JSON

Unpublishing sets the draft flag back; the URL 404s for non-authors and the BotDoc disappears from /explore. It's idempotent — calling it on something already a draft is a no-op.

To delete a BotDoc entirely:

botdocs delete @me/my-skill             # state-aware confirm prompt
botdocs delete @me/my-skill --yes       # skip the prompt (scripts/CI)
botdocs delete @me/my-skill --json      # implies --yes, emits JSON

delete behaves differently depending on what's there:

  • Drafthard delete. The row and all children (files, version history, bundle pins, team pins) are removed. The confirm prompt is a single yes/no.
  • Publishedsoft delete. Sets deletedAt; the BotDoc disappears from /explore and the public URL 404s, but version history is kept. The confirm prompt requires typing the full ref (@user/slug) so a fat-finger doesn't strand bookmarks at a 404.

JSON output is {ok, ref, mode} where mode is "hard" or "soft", mirroring the server's decision.

Zero-argument discovery mode

Run botdocs ingest (no path) and the CLI scans your machine across every known on-disk location for the ten supported ecosystems:

  • ~/.claude/commands/ and <repo>/.claude/commands/ (Claude Code)
  • ~/.claude/agents/**/AGENT.md and <repo>/.claude/agents/**/AGENT.md (Claude Code agents, multi-file)
  • ~/.claude/skills/**/SKILL.md (Claude skills, nested by scope)
  • <repo>/.cursor/rules/ (Cursor)
  • <repo>/.codex/skills/ (Codex)
  • <repo>/.github/instructions/ (GitHub Copilot)
  • <repo>/.codeium/windsurf-rules/ (Windsurf)
  • ~/.gemini/instructions/ (Gemini CLI)
  • ~/.gemini/antigravity/skills/ (Antigravity)
  • ~/.config/opencode/instructions/ (OpenCode)

Project-scoped scans (Cursor, Codex, Copilot, Windsurf, the project flavor of Claude Code) only run when the current directory is inside a git repo.

A scan opens an interactive Ink TUI sectioned by ecosystem. Multi-file skills show their aggregate size + file count instead of per-file lines:

BotDocs ingest
Found 7 skills across 4 tools:

  Claude Code:
    [x] scx-pr-craft           2.1 KB · 67 lines
    [x] pr-review-craft        1.8 KB · 54 lines
    [ ] generic-test-cmd       0.1 KB · 4 lines    ← unchecked (< 100 bytes)

  Claude skills:
    [x] code-review            12.4 KB · 4 files    ← SKILL.md + 3 adjacent

  Cursor rules:
    [x] typescript-strict      0.8 KB · 25 lines

  Gemini CLI:
    [x] research-protocol      2.4 KB · 81 lines

  ↑/↓ navigate · space toggle · a select all · n select none · enter confirm · q cancel

Useful flags:

  • --auto — skip the TUI and upload everything discovery finds (with the < 100-byte stub filter applied).
  • --dry-run — list what discovery found in plain text; don't upload.
  • --json — emit the discovery as JSON; don't upload.
  • --no-ink — disable the TUI on TTYs (for screen readers or simple terminals). Falls back to plain-text listing without uploading; combine with --auto if you want one-shot ingestion.

When the discovery returns nothing the CLI prints a hint pointing at botdocs init (to scaffold a new skill) or botdocs ingest <dir> (to ingest from a specific path).

Development

pnpm install
pnpm --filter @botdocs/cli build       # tsc -> dist/
pnpm --filter @botdocs/cli test        # vitest
pnpm --filter @botdocs/cli typecheck

Releasing

Versioning and publishing run on changesets:

  1. After making changes, run pnpm changeset from the repo root. Pick @botdocs/cli, choose patch/minor/major, write a one-line summary.
  2. Commit the generated .changeset/<slug>.md along with your code.
  3. When your PR merges to master, a "Version Packages" PR is opened automatically with the bumped version and CHANGELOG entries.
  4. Reviewing and merging that PR triggers npm publish from CI.

No manual tagging or version bumps required.

License

MIT © BotDocs contributors