Help us shape the future of Go! Take the 2026 Go Developer Survey

ccshelf

module
v0.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: MIT

README

ccshelf

Profiles and a plugin catalog for Claude Code. Unofficial: not affiliated with Anthropic.

Status: implemented and under adversarial review. Stable releases are available. The launcher, catalog, Action and starter template build for all six targets. The test suites pass on native macOS, Linux and Windows CI runners. Phase 0 evidence items (routing eval, adopt-or-build and bundle prototype) are still open. See the roadmap. Start with docs/README.md and the decision log. The interactive report is docs/report.html, generated from the Markdown.

Install

Install the latest release with the platform-specific script below, or build from source (the Go version in go.mod or newer):

go install github.com/yorch/ccshelf/cmd/ccshelf@latest
ccshelf --version

Or clone the repository and run go build -o ccshelf ./cmd/ccshelf.

The installers below fetch the latest release. Both installers:

  • verify the download before they install anything.
  • never need administrator rights.
  • send no telemetry.
  • write only into the install directory (created with any missing parent folders) and a private temporary directory. They remove the temporary directory afterwards.

"What the installer verifies" in SECURITY.md gives every check and its limits.

Linux and macOS (amd64 and arm64, and WSL counts as Linux). Installs into ~/.local/bin. install.sh needs curl (for example apk add curl or apt install curl):

curl -fsSL https://github.com/yorch/ccshelf/releases/latest/download/install.sh | sh

Pin a version, choose a directory, or require the signature check (options go after sh -s --):

curl -fsSL https://github.com/yorch/ccshelf/releases/latest/download/install.sh | sh -s -- --version v0.2.0 --bin-dir "$HOME/bin" --require-signature

Prefer to read it first? curl -fsSLO https://github.com/yorch/ccshelf/releases/latest/download/install.sh, read it, then sh install.sh. sh install.sh --help lists every option (--base-url for a mirror of the public release, such as one hosted on your GitHub Enterprise Server, --dry-run, --quiet, --force, --cosign-identity, --cosign-issuer).

Windows (amd64 and arm64, with Windows PowerShell 5.1 or PowerShell 7). Installs into %LOCALAPPDATA%\Programs\ccshelf:

irm https://github.com/yorch/ccshelf/releases/latest/download/install.ps1 | iex

With options (-Version, -BinDir, -BaseUrl, -RequireSignature, -AddToPath, -DryRun, -Force). The irm | iex form leaves your session alone: it defines no variable or function and changes no preference. The script edits your user PATH only with -AddToPath:

& ([scriptblock]::Create((irm https://github.com/yorch/ccshelf/releases/latest/download/install.ps1))) -Version v0.2.0 -AddToPath

Verify by hand. Follow "Verifying a release" in SECURITY.md. Then extract the binary with tar -xzf ccshelf_X.Y.Z_<os>_<arch>.tar.gz ccshelf (on Windows, Expand-Archive the .zip). On Windows, compare (Get-FileHash -Algorithm SHA256 <archive>).Hash with the archive's line in checksums.txt.

Notes. The binaries are not notarized (macOS) or Authenticode-signed (Windows) yet. A file fetched by curl or the installers carries no quarantine mark, so Gatekeeper does not stop it. A browser download carries the mark, and macOS may ask you to allow it in System Settings (or run xattr -d com.apple.quarantine ccshelf). Windows SmartScreen may warn about a downloaded .exe.

Uninstall.

  • Delete the binary: rm ~/.local/bin/ccshelf, or the directory you chose.
  • On Windows, delete %LOCALAPPDATA%\Programs\ccshelf. If you used -AddToPath, also delete its entry in your user PATH.
  • Optionally, delete ccshelf's own cache (~/.cache/ccshelf, or %LOCALAPPDATA%\ccshelf on Windows) and its configuration directory.

ccshelf never writes to ~/.claude.

A reusable GitHub Action is also available (action/).

Use

A profile is a named recipe of plugins, standalone skills and MCP servers. ccshelf run starts claude with exactly that set, so each terminal can run a different one.

ccshelf new sre-night --from base --plugin sre-kit@acme   # create a personal profile
ccshelf ls                                                # list profiles from every source
ccshelf show sre-night                                    # resolved plugins, MCP servers, trust closure
ccshelf dry-run sre-night                                 # print the exact claude command, run nothing
ccshelf run sre-night                                     # start claude with the profile
ccshelf run --account personal sre-night --resume         # ccshelf flags first, then claude's

A new user can follow the getting started guide.

Missing plugins

A profile chooses plugins. It does not install them. When a plugin of the profile is not installed, ccshelf run warns and prints the /plugin install command. To let ccshelf install the plugins, add --install-missing:

ccshelf run --install-missing sre-night                          # print the commands, ask, install all missing plugins
ccshelf run --install-missing --yes sre-night                    # the same, without the question
ccshelf run --install-missing=sre-kit@acme --yes sre-night       # only the plugins that you name (each must be in the profile)

ccshelf runs claude plugin install --scope user <id> for each plugin. It installs only from a marketplace that you already added. It runs after the trust check, and not for a profile from a project source. Managed policy applies, because Claude Code does the install. A plugin that Claude Code refuses stays missing, and ccshelf starts as it does without the flag. dry-run never installs. The decision is D-65 in docs/DECISIONS.md.

Every command works with flags alone. On a terminal, ccshelf asks for missing values and prints the equivalent command. You must trust profiles from a shared source (a git repo of your organization) first. ccshelf trust <profile> shows what the profile does. Nothing is ever accepted automatically (--yes does not accept trust). Exit codes: 0 ok, 1 failure, 2 usage, 3 policy, 4 trust required, 130 interrupted.

Accounts

An account is a separate Claude Code configuration directory (CLAUDE_CONFIG_DIR) with its own login, plugins and history. A profile says what is active. An account says who you are.

CLAUDE_CONFIG_DIR=~/.claude-work ccshelf run sre      # ccshelf keeps a variable you set
ccshelf account add work                              # create ~/.claude-work and print the login steps
ccshelf account add personal --dir ~/.claude-personal --default
ccshelf account ls
ccshelf run --account personal sre                    # pick an account for one command
ccshelf account rm personal                           # forget it, keep its directory

ccshelf uses the first of these that is set:

  1. --account. It replaces a CLAUDE_CONFIG_DIR that is already set, and ccshelf prints a warning.
  2. An existing CLAUDE_CONFIG_DIR.
  3. The profile's account field.
  4. default_account in config.toml.
  5. Claude Code's default ~/.claude.

Install the plugins in each account. ccshelf never reads, copies or moves credentials and never deletes an account directory. Details: docs/design/launcher.md.

Update
ccshelf update --check     # current and latest version; exit 0 either way
ccshelf update             # verify (SHA-256, and cosign if installed), then replace this binary
ccshelf update --rollback  # restore the previous binary kept as ccshelf.old
ccshelf update --yes       # the scripted form: no question (the automatic update never acts in scripts)

Before it replaces anything, ccshelf update checks the archive's SHA-256 against checksums.txt of the same release, and the keyless signature when cosign is on PATH. --require-signature insists on the signature. "Network use and updates" in SECURITY.md lists every check and what ccshelf sends.

--force never installs an older release than the one you run. --allow-downgrade does. ccshelf leaves these copies to their package manager and prints the command (--force overrides):

  • a copy installed with Homebrew, Scoop, WinGet or go install.
  • development builds.

Nothing checks for updates by itself unless you opt in:

# config.toml
[update]
mode = "notify"   # off (default) | notify (one line when a release exists) | install (see below)
interval = "24h"

install takes only a newer stable release of the same major version (for 0.x, the same minor). Both modes act only in an interactive terminal (stdin, stdout and stderr all terminals), so never in scripts, cron jobs, pipelines or when CI is set. CCSHELF_NO_UPDATE_CHECK=1 turns them off. Details: docs/design/update.md.

For organizations, ccshelf lint, compile, catalog build, search, recommend and doctor work on the org data repo (see examples/org-data-repo for a starter template). The design is in docs/.

Set up your org repo

ccshelf catalog init bootstraps the org data repo. It works on:

  • a new repo in an empty directory.
  • an existing marketplace repo (.claude-plugin/marketplace.json and/or plugins/). It retrofits this repo without changing any existing file.

It prints a plan (create, skip-exists, needs-merge). Then it writes ccshelf.toml, a marketplace skeleton, a sidecar stub per plugin, CODEOWNERS, the pinned validate, catalog and release workflows, a README and .gitattributes. There are no built-in profiles. ccshelf lint reports placeholders (TODO(ccshelf)) as warnings until you fill them in.

ccshelf catalog init ./acme-claude --marketplace-name acme --org "Acme Corp" \
  --platform-owners @acme/platform --dry-run          # print the plan, write nothing
ccshelf catalog init ./acme-claude --marketplace-name acme --org "Acme Corp" \
  --platform-owners @acme/platform --yes              # write it
ccshelf catalog init . --platform-owners @acme/platform --write-suggestions --yes   # adopt an existing repo

On a terminal, ccshelf asks for missing values. The design is in docs/design/catalog-and-org-repo.md.

The project website lives in site/. It is static, and the build generates the /docs pages from the Markdown. just site-check checks it. A workflow deploys it to GitHub Pages automatically on every change to main (.github/workflows/pages.yml, see site/README.md).

Licensed under the MIT License.

Directories

Path Synopsis
cmd
ccshelf command
Command ccshelf runs Claude Code with a named profile and lints and publishes an organization's plugin catalog.
Command ccshelf runs Claude Code with a named profile and lints and publishes an organization's plugin catalog.
internal
account
Package account manages named Claude Code accounts: a name that maps to a separate CLAUDE_CONFIG_DIR (launcher.md, "Combining profiles with accounts", way 2).
Package account manages named Claude Code accounts: a name that maps to a separate CLAUDE_CONFIG_DIR (launcher.md, "Combining profiles with accounts", way 2).
analytics
Package analytics reads optional plugin usage data.
Package analytics reads optional plugin usage data.
bundles
Package bundles compiles resolved profiles into generated profile bundles: dependency-only plugins that let a profile's plugins install natively from the org's marketplace (decision D-17).
Package bundles compiles resolved profiles into generated profile bundles: dependency-only plugins that let a profile's plugins install natively from the org's marketplace (decision D-17).
cache
Package cache manages the launcher's private cache directory and the content-addressed files in it (security requirement SR4).
Package cache manages the launcher's private cache directory and the content-addressed files in it (security requirement SR4).
catalog
Package catalog builds the plugin catalog of an org data repo: a merged, sanitized, deterministic view of the marketplace entries, their sidecar metadata, what inspecting the plugin directories found, and optional git history, plus renderers (catalog.json, CATALOG.md) and a text search.
Package catalog builds the plugin catalog of an org data repo: a merged, sanitized, deterministic view of the marketplace entries, their sidecar metadata, what inspecting the plugin directories found, and optional git history, plus renderers (catalog.json, CATALOG.md) and a text search.
catalog/catalogtest
Package catalogtest holds helpers shared by the tests of the catalog packages: the fictional org data repo fixture and small file helpers.
Package catalogtest holds helpers shared by the tests of the catalog packages: the fictional org data repo fixture and small file helpers.
catalog/codeowners
Package codeowners parses CODEOWNERS files and answers "who owns this path" with GitHub's semantics.
Package codeowners parses CODEOWNERS files and answers "who owns this path" with GitHub's semantics.
catalog/gitdata
Package gitdata collects optional history data for the catalog by running the user's git: the last commit date and the number of distinct authors of each plugin directory, the latest tag, and which plugin directories changed since a tag.
Package gitdata collects optional history data for the catalog by running the user's git: the last commit date and the number of distinct authors of each plugin directory, the latest tag, and which plugin directories changed since a tag.
catalog/lint
Package lint checks an org data repo against the catalog rules and reports stable, sorted findings.
Package lint checks an org data repo against the catalog rules and reports stable, sorted findings.
catalog/safepath
Package safepath confines file access to a repository root.
Package safepath confines file access to a repository root.
catalog/sidecar
Package sidecar reads the catalog-only metadata of plugins: one TOML sidecar file per plugin (catalog/plugins/<name>.toml), or, in single-file mode, the free-form "metadata" object of each marketplace entry, and the taxonomy file (catalog/taxonomy.toml).
Package sidecar reads the catalog-only metadata of plugins: one TOML sidecar file per plugin (catalog/plugins/<name>.toml), or, in single-file mode, the free-form "metadata" object of each marketplace entry, and the taxonomy file (catalog/taxonomy.toml).
catalog/site
Package site writes the static catalog site: four plain files that a web server, GitHub Pages or an internal static host can serve as they are.
Package site writes the static catalog site: four plain files that a web server, GitHub Pages or an internal static host can serve as they are.
claude
Package claude is everything ccshelf needs from the claude binary: finding it, asking it questions, parsing what it prints, and starting it.
Package claude is everything ccshelf needs from the claude binary: finding it, asking it questions, parsing what it prints, and starting it.
cli
Package cli assembles the ccshelf command tree: the global flags, the launcher commands and the org and catalog commands.
Package cli assembles the ccshelf command tree: the global flags, the launcher commands and the org and catalog commands.
cli/clicore
Package clicore holds the small, dependency-light pieces every ccshelf command shares: the global flags, the environment a command may touch, and the per-invocation Context that carries the terminal mode and the prompter.
Package clicore holds the small, dependency-light pieces every ccshelf command shares: the global flags, the environment a command may touch, and the per-invocation Context that carries the terminal mode and the prompter.
cli/launcher
Package launcher implements the launcher commands of ccshelf: run, dry-run, show, ls, diff, new, edit, init, trust, account, shell-init, version and completion.
Package launcher implements the launcher commands of ccshelf: run, dry-run, show, ls, diff, new, edit, init, trust, account, shell-init, version and completion.
cli/orgcmd
Package orgcmd implements the org and catalog commands of the ccshelf CLI: lint, compile, catalog build, search, recommend and doctor.
Package orgcmd implements the org and catalog commands of the ccshelf CLI: lint, compile, catalog build, search, recommend and doctor.
cli/updatecmd
Package updatecmd implements the "ccshelf update" command and the opt-in automatic update hooks around the other commands.
Package updatecmd implements the "ccshelf update" command and the opt-in automatic update hooks around the other commands.
config
Package config loads, validates and saves the user's ccshelf configuration file (config.toml) and resolves which Claude Code account a run uses.
Package config loads, validates and saves the user's ccshelf configuration file (config.toml) and resolves which Claude Code account a run uses.
config/tomlkeys
Package tomlkeys closes a gap in the TOML decoder.
Package tomlkeys closes a gap in the TOML decoder.
doctor
Package doctor analyzes an org's catalog, profiles and installed plugins and returns findings.
Package doctor analyzes an org's catalog, profiles and installed plugins and returns findings.
e2e
Package e2e holds end-to-end tests of the real ccshelf binary.
Package e2e holds end-to-end tests of the real ccshelf binary.
envpolicy
Package envpolicy decides which environment variable names a profile may set for a Claude Code session (security requirement SR1).
Package envpolicy decides which environment variable names a profile may set for a Claude Code session (security requirement SR1).
marketplace
Package marketplace reads a Claude Code plugin marketplace repository without running the claude binary.
Package marketplace reads a Claude Code plugin marketplace repository without running the claude binary.
orgconfig
Package orgconfig reads ccshelf.toml, the org config at the root of an organization's data repo.
Package orgconfig reads ccshelf.toml, the org config at the root of an organization's data repo.
policy
Package policy detects Claude Code managed policy on this machine and turns it into a capability matrix for the launcher (requirement R3, decision D-06).
Package policy detects Claude Code managed policy on this machine and turns it into a capability matrix for the launcher (requirement R3, decision D-06).
profile
Package profile parses profile manifests, resolves them across sources and computes the trust closure (SR1 to SR3).
Package profile parses profile manifests, resolves them across sources and computes the trust closure (SR1 to SR3).
profile/gitsource
Package gitsource provides a profile.Source backed by a pinned git repository: the shared "org data repo" that holds profiles/, mcp/registry.toml and prompts/ (security requirements SR2 and SR4).
Package gitsource provides a profile.Source backed by a pinned git repository: the shared "org data repo" that holds profiles/, mcp/registry.toml and prompts/ (security requirements SR2 and SR4).
profile/pluginsource
Package pluginsource provides a profile.Source that reads profiles from a Claude Code plugin that is already installed: the "data-only plugin" way of shipping an org's profiles.
Package pluginsource provides a profile.Source that reads profiles from a Claude Code plugin that is already installed: the "data-only plugin" way of shipping an org's profiles.
recommend
Package recommend suggests plugins and profiles for a directory.
Package recommend suggests plugins and profiles for a directory.
scaffold
Package scaffold plans and writes the files of an org data repo for "ccshelf catalog init": a new repository in an empty directory, or the missing pieces of an existing marketplace repository.
Package scaffold plans and writes the files of an org data repo for "ccshelf catalog init": a new repository in an empty directory, or the missing pieces of an existing marketplace repository.
settings
Package settings generates and validates the --settings JSON that ccshelf gives to Claude Code (security requirement SR1: a closed schema).
Package settings generates and validates the --settings JSON that ccshelf gives to Claude Code (security requirement SR1: a closed schema).
shellinit
Package shellinit generates the shell integration printed by "ccshelf shell-init <shell>": one small function per profile that runs "ccshelf run <profile>" with the rest of the command line passed through.
Package shellinit generates the shell integration printed by "ccshelf shell-init <shell>": one small function per profile that runs "ccshelf run <profile>" with the rest of the command line passed through.
testutil
Package testutil holds helpers shared by ccshelf's tests: a build of the fake claude (internal/testutil/fakeclaude), an isolated environment that cannot touch the real home directory, and small file helpers.
Package testutil holds helpers shared by ccshelf's tests: a build of the fake claude (internal/testutil/fakeclaude), an isolated environment that cannot touch the real home directory, and small file helpers.
testutil/fakeclaude command
Command fakeclaude is a test double of the claude binary, driven by environment variables and files, for ccshelf's tests.
Command fakeclaude is a test double of the claude binary, driven by environment variables and files, for ccshelf's tests.
trust
Package trust decides whether a resolved profile may run (SR2).
Package trust decides whether a resolved profile may run (SR2).
ui
Package ui is the terminal layer of ccshelf: how a command decides whether it may prompt, how it asks, how it prints, and how it exits (requirement R6).
Package ui is the terminal layer of ccshelf: how a command decides whether it may prompt, how it asks, how it prints, and how it exits (requirement R6).
update
Package update implements "ccshelf update" and the opt-in automatic update: discovering the latest release, downloading and verifying it, and replacing the running binary.
Package update implements "ccshelf update" and the opt-in automatic update: discovering the latest release, downloading and verifying it, and replacing the running binary.
update/updatetest
Package updatetest is a fake GitHub release server for tests of the update flow: it speaks the few REST routes ccshelf uses (latest, list, by tag) and serves real tar.gz and zip archives, a checksums.txt and, on request, a signature bundle placeholder.
Package updatetest is a fake GitHub release server for tests of the update flow: it speaks the few REST routes ccshelf uses (latest, list, by tag) and serves real tar.gz and zip archives, a checksums.txt and, on request, a signature bundle placeholder.
version
Package version reports the build identity of the ccshelf binary.
Package version reports the build identity of the ccshelf binary.
Package schema embeds the handwritten JSON Schema (draft 2020-12) files for ccshelf's three TOML formats: profile manifests, the user config and the MCP registry.
Package schema embeds the handwritten JSON Schema (draft 2020-12) files for ccshelf's three TOML formats: profile manifests, the user config and the MCP registry.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL