ccshelf

Command reference

Generated file: do not edit by hand. Run scripts/gen-cli-reference.sh --write to regenerate it.

verified This page is generated from the real ccshelf binary: every section below is the output of ccshelf --help or ccshelf <command> --help, parsed and laid out here, and the exit codes are read from internal/ui/exit.go. scripts/gen-cli-reference.sh --check (run in CI) fails when this file is stale. It documents the command line as built from the repository; no version has been released yet.

Global flags#

These flags are accepted by every command. Flags of ccshelf itself go before a profile name: everything after the profile is passed to claude unchanged.

FlagValueDescription
--accountstringaccount to use for this invocation
--claudestringpath to the claude binary
--configstringpath to the user config file
--jsonmachine-readable output where supported
--no-colordisable color
--no-interactivenever prompt, and fail with the name of the missing flag
--plainline-oriented output and prompts
--rootstringorg data repo root (default: current directory)
-h, --helphelp for ccshelf
-v, --versionversion for ccshelf

Exit codes#

Scripts can rely on these; they never change meaning.

CodeMeaning
0success
1the command failed
2a usage error, including a value that was missing and could not be prompted for
3the action was blocked by managed policy
4the profile needs trust before it can run
130the user interrupted the command (Ctrl+C, Ctrl+D at a prompt), by the shell convention 128 + SIGINT

Commands#

CommandWhat it does
ccshelf diffCompare two resolved profiles
ccshelf dry-runPrint the exact claude command a run would execute
ccshelf editOpen a personal profile in $VISUAL or $EDITOR
ccshelf lsList the profiles of all sources
ccshelf newCreate a user or project profile
ccshelf runStart claude with a profile
ccshelf showShow a resolved profile: parents merged, MCP servers, closure
ccshelf trustReview and trust a shared profile (or a project folder)
ccshelf doctorCheck the org's catalog and profiles for overlap, staleness and policy conflicts
ccshelf recommendSuggest plugins and profiles for a project directory (rule based)
ccshelf searchSearch the plugin catalog of the org data repo
ccshelf catalogSet up the org data repo and build its plugin catalog
ccshelf catalog buildWrite catalog.json, CATALOG.md and the static site
ccshelf catalog initSet up a new org data repo, or add the missing pieces to an existing marketplace repo
ccshelf compileGenerate the profile-* bundle plugins from the profile manifests
ccshelf lintCheck the org data repo: marketplace, sidecars, ownership and profiles
ccshelf accountManage named Claude Code accounts (separate CLAUDE_CONFIG_DIR)
ccshelf account addAdd an account and print the one-time steps to log in
ccshelf account lsList the configured accounts
ccshelf account rmForget an account (its directory is left alone)
ccshelf completionPrint a shell completion script
ccshelf configShow and change the configuration file
ccshelf config editEdit config.toml in $VISUAL or $EDITOR, checked before it replaces the file
ccshelf config pathPrint the configuration file path in use
ccshelf config setChange one setting
ccshelf config showPrint the effective configuration
ccshelf config sourceList, add, pin and remove profile sources
ccshelf config source addAdd a profile source (git, dir or plugin)
ccshelf config source lsList the configured profile sources
ccshelf config source pinChange the pinned ref or the tracked branch of git source number n
ccshelf config source rmRemove source number n
ccshelf config unsetPut one setting back to its default
ccshelf initCreate the configuration file, optionally from an org data repo
ccshelf shell-initPrint shell functions cs-<profile> that run each profile
ccshelf updateUpdate ccshelf to the latest release (verified), or roll back
ccshelf versionPrint the ccshelf version

ccshelf diff#

Compare two profiles after their parents are merged: plugins, skills, MCP servers, environment variable names and session defaults. "+" marks what b adds to a and "-" what b lacks. Environment values, prompt text and instructions text are never printed. The exit code is 0 whether or not they differ. --json has an "identical" field.

Usage

ccshelf diff [profile-a] [profile-b] [flags]

Flags

FlagValueDescription
-h, --helphelp for diff

ccshelf dry-run#

Run the whole pipeline of "run" (including the trust check) and print the exact claude command instead of starting it. The command writes the generated settings, MCP config, prompt and instructions files to the private cache, so the printed command is valid. It never prints environment values from profiles.

Usage

ccshelf dry-run [profile] [-- claude args]

Flags

FlagValueDescription
-h, --helphelp for dry-run
--refreshcheck tracked branches for a new commit now, not only once per trust.branch_check_interval

ccshelf edit#

Open one of your personal profiles in the editor named by $VISUAL or $EDITOR (the command is split on spaces, quotes group words, and it is never run through a shell), then check the result. Profiles from shared sources are read-only here: copy one with "ccshelf new <name> --from <profile>" and edit the copy.

--path prints the file name instead of opening it, for scripts and for editors you start yourself.

Usage

ccshelf edit [profile] [flags]

Flags

FlagValueDescription
-h, --helphelp for edit
--pathprint the profile file path instead of opening it

ccshelf ls#

List the profiles of every source: your personal directory, the configured sources and, only when trusted, the repository's .ccshelf folder. Invalid profiles are listed with their error. Use --json for a stable machine-readable form.

Usage

ccshelf ls [flags]

Aliases: ls, list

Flags

FlagValueDescription
-h, --helphelp for ls
--refreshre-resolve git tags and branches on the remote instead of using the commits the trust lockfile pins

ccshelf new#

Create a separate TOML file in your user profiles directory (default), or with --scope project in the Git root/.ccshelf/profiles (cwd outside Git). --from names a parent profile to extend (repeatable). With no content flags, a terminal offers a wizard and prints its equivalent flag command. Creation never enables or trusts project profiles. --yes confirms creation only.

Usage

ccshelf new [name] [flags]

Examples

ccshelf new sre-night --from base --plugin sre-kit@acme
ccshelf new notes --description "Writing and notes" --skill-off legacy-helper

Flags

FlagValueDescription
--descriptionstringone-line description
--effortstringdefault effort level
--exclude-pluginstringArrayplugin to always mask, name@marketplace (repeatable)
--fromstringArrayparent profile to extend (repeatable)
-h, --helphelp for new
--mcpstringArrayMCP server from the registry to add (repeatable)
--modelstringdefault model
--ownerstringowner (team or person)
--pluginstringArrayplugin to include, name@marketplace (repeatable)
--scopestringprofile location: user or project (default "user")
--skill-offstringArraystandalone skill to turn off (repeatable)
--yesskip creation confirmation only (never accepts trust)

ccshelf run#

Start claude with a profile: the plugins, skills and MCP servers it names.

ccshelf passes the arguments after the profile name (and after -- when no profile is given) to claude unchanged. Thus flags of ccshelf itself must come before the profile name: ccshelf run --account work sre --resume.

Without a profile name, a terminal gets a picker. Anything else exits with code 2. You must trust a profile from a shared source first (exit code 4 otherwise). --yes never accepts trust. Only an interactive confirmation of the printed closure or "ccshelf trust <profile> --accept <closure-hash>" accepts it.

A git source that tracks a branch runs the commit you trusted, with no network. At most once per trust.branch_check_interval (default 24h), ccshelf asks the remote for the head of the branch. If the head moved, a terminal shows what changed and asks. Without a terminal, or with --yes, ccshelf keeps the trusted commit and prints the command that reviews the update. --refresh checks now. If another profile of the same source trusted a later commit of the branch, ccshelf offers that commit to this profile at once, with no network call and whatever the interval says. It offers only a commit that it can prove is later, and it runs only a commit that this profile trusts.

--install-missing installs the plugins of the profile that claude does not list. It runs "claude plugin install --scope user <id>" for each one, in the cache directory and not in the project, after it prints the commands. Without a value, it installs all missing plugins. With --install-missing=id,id, it installs only the plugins that you name. Each one must be in plugins.include of the profile. In a terminal, ccshelf asks you to confirm. --yes skips the question and is the only way to confirm without a terminal. It installs only from a marketplace that you already added, and it never adds one. It does not work with a profile from a project source. Managed policy applies, because claude does the install. When claude refuses a plugin, ccshelf reports it and goes on as it does without the flag.

Usage

ccshelf run [profile] [-- claude args]

Examples

ccshelf run sre
ccshelf run sre -- -p "summarize this repo"
ccshelf run --account personal sre --resume

Flags

FlagValueDescription
-h, --helphelp for run
--install-missingstringsinstall plugins of the profile that claude does not list. Without a value: all of them. With =id,id: only these. --yes skips the confirmation
--refreshcheck tracked branches for a new commit now, not only once per trust.branch_check_interval
--yesanswer yes to confirmations other than trust (trust is never auto-accepted)

ccshelf show#

Show a profile as it would run: the extends chain, plugins, skills, MCP servers, session defaults, warnings and the closure that a trust decision pins, plus the trust state. Environment values are never printed. Use --json for a stable, versioned machine-readable form.

Usage

ccshelf show [profile] [flags]

Flags

FlagValueDescription
-h, --helphelp for show

ccshelf trust#

Show what a profile's closure runs (MCP servers, prompts, plugins, environment names) and record it as trusted. In a terminal, the command asks you to confirm what it shows. For scripts, name exactly what you accept:

ccshelf trust <profile> --accept <closure-hash>

"ccshelf trust <profile>" and "ccshelf show <profile>" print the hash. --yes does not exist here: trust is never accepted by default.

--project reviews the repository's .ccshelf folder (loaded only when trust.trust_project_profiles is true). With --project, --accept takes the folder hash. --revoke removes the records of a profile (or of the project folder).

Usage

ccshelf trust [profile] [flags]

Flags

FlagValueDescription
--acceptstringclosure hash (or, with --project, folder hash) you accept
-h, --helphelp for trust
--projectact on the repository's .ccshelf folder
--revokeremove the trust records instead

ccshelf doctor#

Analyze the org data repo (--root, default the current directory): overlapping plugins, plugins in no profile, deprecated plugins in use, stale or missing review dates and owners, protected plugins that a profile masks, and plugins that need platform review.

The command skips the checks that need more input and lists them as skipped. It never passes them silently. These flags give the input:

- --installed reads 'claude plugin list' (read only). It uses the account
  from --account, CLAUDE_CONFIG_DIR or default_account, in that order.
- --usage-file reads an OpenTelemetry JSONL export.
- --usage-api asks the Enterprise Analytics API. It needs the admin key in
  CCSHELF_ANALYTICS_KEY. This is the only network call.
- --skills-dir lists the standalone skills in a directory (read only). Each
  subdirectory with a SKILL.md is a skill. ccshelf never reads ~/.claude on
  its own.
- --policy reads the machine's managed Claude Code policy (read only, never
  bypassed) and prints the capability matrix.

With --policy, the command checks the needs of every profile against the policy that it could read. The needs are extra MCP servers, strict MCP, dropping user settings, a system prompt file, hiding claude.ai connectors, and the marketplaces of its plugins. The exit code is 3 when the policy blocks something a profile needs (POL002, POL005, POL006). A feature whose state is unknown is a warning, never a failure. A policy that exists but could not be read is a warning. It gives exit code 3 only with --strict.

The exit code is 1 for error findings, and when the directory is not an org data repo (its marketplace file cannot be read).

With --policy and no --root, a directory that is not an org data repo is not an error, because the managed policy belongs to the machine, not to a repository. Only the policy part runs: the capability matrix and the policy findings that do not need profiles. The command lists the checks that need the catalog as skipped. A developer who reaches the org through a git source can use it that way.

Usage

ccshelf doctor [flags]

Flags

FlagValueDescription
-h, --helphelp for doctor
--installedread the installed plugins with 'claude plugin list'
--policyalso read managed Claude Code policy and print the capability matrix
--skills-dirstringdirectory of standalone skills to check against the profiles (read only)
--strictwith --policy: exit 3 also when a managed policy exists but could not be read
--usage-apiread plugin usage from the Enterprise Analytics API
--usage-daysintusage window in days for --usage-api and --usage-file (default 30)
--usage-filestringOpenTelemetry JSONL export to read plugin usage from

ccshelf recommend#

Look at a project directory (--dir, default the current directory) and suggest plugins and profiles of the org data repo (--root, default the current directory) whose relevance signals and when_to_use text match it. The rules are deterministic and there is no model call. The command reads only file names and a few small manifest files of the project.

Outside an org data repo (the marketplace file of ccshelf.toml cannot be read) and without --root, the command gets [catalog].remote_url of the user config over HTTPS when it is set. Otherwise it uses the catalog data of the organization's source from its local directory or verified git cache. Remote JSON can recommend profiles. Plugin recommendations need marketplace relevance rules from the org data repo.

Usage

ccshelf recommend [flags]

Flags

FlagValueDescription
--dirstringproject directory to look at (default the current directory)
-h, --helphelp for recommend
--limitintshow at most this many suggestions (0 for all) (default 10)

Search the catalog of the org data repo (--root, default the current directory). Every word of the query must match a field (name, display name, tags, category, when_to_use, description or owner). Better matches come first. Equal matches sort by name.

Outside an org data repo and without --root, [catalog].remote_url in the user config takes precedence and retrieves catalog.json over HTTPS for this search. Otherwise search reads a configured org source from its local directory or verified git cache. A query that matches nothing in a real catalog is not an error.

Usage

ccshelf search <query> [flags]

Flags

FlagValueDescription
-h, --helphelp for search
--limitintshow at most this many matches (0 for all) (default 10)

ccshelf catalog#

Set up the org data repo and build its plugin catalog

Usage

ccshelf catalog [flags]
ccshelf catalog [command]

Flags

FlagValueDescription
-h, --helphelp for catalog

Subcommands

CommandWhat it does
ccshelf catalog buildWrite catalog.json, CATALOG.md and the static site
ccshelf catalog initSet up a new org data repo, or add the missing pieces to an existing marketplace repo

ccshelf catalog build#

Build the catalog from the org data repo and write it into --out (default dist/catalog, relative to the current directory):

- catalog.json
- CATALOG.md
- the static site (index.html, app.js, style.css), unless --no-site

With --no-site, the command removes the files of an earlier site build from --out. The command writes nothing outside --out. The output is published files: directories 0755, files 0644.

--out must not:

- be the repo root or contain it
- be inside the repo's source directories (profiles, bundles, catalog,
  plugins, .github and so on)
- pass through a symbolic link below the working directory or the repo root

A directory that is not an org data repo (its marketplace file cannot be read or parsed) is an error (exit 1), and the command writes nothing.

The catalog has no timestamp unless you give --timestamp, so the output is reproducible. The command prints lint findings to stderr. A repo with lint errors still produces its catalog (for previews), but the command exits 1.

Usage

ccshelf catalog build [flags]

Flags

FlagValueDescription
--git-dataadd last-change and contributor data from git
-h, --helphelp for build
--no-sitewrite only catalog.json and CATALOG.md
--outstringoutput directory (default dist/catalog)
--timestampstamp generated_at into the output

ccshelf catalog init#

Bootstrap an org data repo in dir (default: --root, else the current directory). This is the organization's setup. "ccshelf init" is each developer's own.

Modes (detected, or forced with --mode):

new    an empty or missing directory (a lone .git counts as empty).
adopt  a directory with content, such as a marketplace repo that has
       .claude-plugin/marketplace.json and/or plugins/. The command changes
       nothing that exists. It prints a plan and only creates the files
       that are missing. It reports an existing file as one of these:
         - skip-exists (and up to date when it already equals what the
           command would write)
         - needs-merge for CODEOWNERS, .gitattributes and .gitignore, with
           the lines to add. --write-suggestions saves them next to the
           file as <name>.ccshelf-suggested.
       The command never rewrites a marketplace.json. --force replaces the
       other differing files after it saves <file>.bak.

Generated files (a --no-<group> flag leaves out its group):

- ccshelf.toml
- .claude-plugin/marketplace.json: a skeleton. In adopt mode, it lists the
  plugins found under plugins/.
- catalog/plugins/<name>.toml: a stub per plugin with the owner from
  CODEOWNERS or --owner, status experimental, and TODO(ccshelf)
  placeholders that ccshelf lint reports as warnings (CAT048).
- .github/CODEOWNERS
- .github/workflows/{validate,catalog,release}.yml
- README.md, .gitattributes and .gitignore

ccshelf has no built-in profiles. The command writes profiles/example.toml.sample, an all-comment sample, only with --example-profile.

--profiles-only sets up an org data repo that holds profiles (and prompts/ and mcp/registry.toml) but no plugin marketplace and no catalog. ccshelf.toml gets [catalog] enabled = false. The command writes ccshelf.toml, .github/CODEOWNERS, a README.md, .gitattributes, .gitignore and only the validate workflow (lint). It writes no marketplace.json, sidecars, catalog.yml or release.yml. These are usage errors with --profiles-only:

- --marketplace-name, --owner and --sidecars stub
- a directory that already has a marketplace file

An existing ccshelf.toml must already have [catalog] enabled = false. Add it yourself, or use --force to replace the file. The command refuses --no-config unless the file has it.

The workflows call the ccshelf action pinned by full commit SHA. Pass --ccshelf-ref <40-hex SHA> and --ccshelf-version <vX.Y.Z> to pin it. A tag given as --ccshelf-ref sets the version only. Without them, the workflows contain a placeholder and fail with a clear message until you pin them.

Flags are the contract: you can give every value as a flag. In a terminal, the command asks for the missing values, shows the plan and prints the equivalent flag command. Without a terminal, a missing value is a usage error (exit 2) that names the flag. Writing needs --yes (or --dry-run to print the plan). The command commits, pushes and fetches nothing. --git-init only runs git init when the directory is not a repository yet.

Usage

ccshelf catalog init [dir] [flags]

Examples

ccshelf catalog init ./acme-claude --marketplace-name acme --org "Acme Corp" --platform-owners @acme/platform --yes
ccshelf catalog init . --platform-owners @acme/platform --dry-run
ccshelf catalog init ./acme-profiles --profiles-only --platform-owners @acme/platform --yes
ccshelf catalog init . --mode adopt --platform-owners @acme/platform --write-suggestions --yes

Flags

FlagValueDescription
--ccshelf-refstringfull 40-hex commit SHA of the ccshelf action to pin, or a release tag vX.Y.Z (sets the version only)
--ccshelf-versionstringccshelf release tag the action installs, such as v0.1.0
--default-branchstringdefault branch the catalog workflow publishes from (default: read from an existing repository, else main)
--dry-runprint the plan and write nothing
--example-profilealso write profiles/example.toml.sample, an all-comment sample
--forcereplace existing files that differ, after saving <file>.bak (never marketplace.json)
--git-initrun git init when the directory is not a git repository (nothing else of git)
-h, --helphelp for init
--marketplace-namestringmarketplace name (lower case letters, digits and hyphens)
--modestringnew or adopt (default: detected from the directory)
--no-codeownersdo not generate .github/CODEOWNERS
--no-configdo not generate ccshelf.toml
--no-gitattributesdo not generate .gitattributes
--no-gitignoredo not generate .gitignore
--no-marketplacedo not generate .claude-plugin/marketplace.json
--no-readmedo not generate README.md
--no-sidecarsdo not generate catalog/plugins/<name>.toml (same as --sidecars none)
--no-workflowsdo not generate the .github/workflows files
--orgstringdisplay name of the organization (default: the marketplace name)
--ownerstringdefault owner of the plugin sidecars (default: the first platform owner)
--platform-ownersstringsCODEOWNERS owners of everything that runs code or shapes the catalog (@user, @org/team or an email address, repeatable)
--profiles-onlyset up a repo of profiles only: no marketplace, sidecars, bundles or catalog (ccshelf.toml gets [catalog] enabled = false, and the command writes only the validate workflow)
--quietdo not print the suggested lines of the files that need a merge (they stay in --json and in --write-suggestions)
--runner-labelstringfallback of runs-on in the workflows when the RUNNER_LABEL variable is unset (default ubuntu-latest)
--sidecarsstringsidecar files for the plugins found: stub or none (default "stub")
--write-suggestionswrite <name>.ccshelf-suggested files for the files that need a merge
--yeswrite without asking for confirmation (never accepts trust)

ccshelf compile#

Compile every profile of the org data repo into a profile bundle: a plugin under bundles/profile-<name>/ whose dependencies are the profile's resolved plugins. The command skips profiles that resolve to no plugins (abstract bases).

The whole bundles/ tree is generated output. The command removes the files that no profile produces. With --check, the command writes nothing. It prints the differences and exits 1 when the committed bundles are stale.

Usage

ccshelf compile [flags]

Flags

FlagValueDescription
--checkwrite nothing, and exit 1 when the bundles are stale
-h, --helphelp for compile

ccshelf lint#

Check the org data repo (--root, default the current directory) against its ccshelf.toml: marketplace entries, catalog sidecars, taxonomy, review dates, CODEOWNERS coverage of hooks and MCP servers, profile manifests and their profile-* bundle entries.

Formats: text (default), json (same as the global --json: the common {"version","kind":"lint","data":{"summary","findings"}} envelope) and github (workflow annotations, one ::error/::warning/::notice line per finding). The exit code is 1 when there is any error finding (with --strict, also any warning).

Usage

ccshelf lint [flags]

Flags

FlagValueDescription
--formatstringoutput format: text, json or github (default "text")
-h, --helphelp for lint
--strictfail on warnings too

ccshelf account#

An account is a name for a separate Claude Code configuration directory, so work and personal logins, plugins and history stay apart. ccshelf never reads, copies or moves credentials and never deletes a directory.

Usage

ccshelf account [command]

Flags

FlagValueDescription
-h, --helphelp for account

Subcommands

CommandWhat it does
ccshelf account addAdd an account and print the one-time steps to log in
ccshelf account lsList the configured accounts
ccshelf account rmForget an account (its directory is left alone)

ccshelf account add#

Create the account's configuration directory (mode 0700), save it in the configuration and print the one-time steps you run yourself: start claude with the variable set, /login, then marketplace adds and plugin installs inside it. The directory defaults to ~/.claude-<name>.

Usage

ccshelf account add [name] [flags]

Examples

ccshelf account add work
ccshelf account add personal --dir ~/.claude-personal --default

Flags

FlagValueDescription
--defaultmake this the default account
--dirstringconfiguration directory (default ~/.claude-<name>)
-h, --helphelp for add
--marketplacestringArraymarketplace to add inside the account, such as acme/claude-plugins (repeatable)
--pluginstringArrayplugin to install inside the account, name@marketplace (repeatable)

ccshelf account ls#

List the configured accounts

Usage

ccshelf account ls [flags]

Aliases: ls, list

Flags

FlagValueDescription
-h, --helphelp for ls

ccshelf account rm#

Remove the account from the configuration. The directory, with its login and history, is never deleted.

Usage

ccshelf account rm <name> [flags]

Aliases: rm, remove

Flags

FlagValueDescription
-h, --helphelp for rm

ccshelf completion#

Print a completion script generated from the command definitions, for bash, zsh, fish or PowerShell.

Usage

ccshelf completion <bash|zsh|fish|powershell> [flags]

Flags

FlagValueDescription
-h, --helphelp for completion

ccshelf config#

Show the effective configuration, and add, pin or remove profile sources and change a few settings in place, without editing config.toml by hand. Every subcommand works with flags alone. In a terminal, "ccshelf config" alone opens a menu, and the command shows a change and asks you to confirm it (default no) before it writes it.

The command writes a change by encoding the file again. Comments and layout are lost, and the command keeps the previous file as config.toml.bak. When there is no terminal, a change that weakens a security setting needs --yes. These changes weaken a security setting:

- turning off pinning
- trusting project profiles
- installing updates automatically
- adding a source that tracks a branch, is not pinned or has a path that is
  a variable
- changing claude.path or the update source

Nothing here fetches a source or records trust. Only "ccshelf init" creates the file.

Settings you can change with "config set": trust.on_change, trust.require_pin, trust.trust_project_profiles, trust.branch_check_interval, update.mode, update.interval, catalog.remote_url, default_account, ui.color, ui.interactive. Anything else (accounts, claude.path, the update source) has its own command or needs "ccshelf config edit".

Usage

ccshelf config [flags]
ccshelf config [command]

Examples

ccshelf config show
ccshelf config source add --git-url git@ghe.example.com:acme/claude-marketplace.git --ref v2026.10.1
ccshelf config source pin 1 --ref v2026.11.0
ccshelf config set update.mode notify
ccshelf config edit

Flags

FlagValueDescription
-h, --helphelp for config

Subcommands

CommandWhat it does
ccshelf config editEdit config.toml in $VISUAL or $EDITOR, checked before it replaces the file
ccshelf config pathPrint the configuration file path in use
ccshelf config setChange one setting
ccshelf config showPrint the effective configuration
ccshelf config sourceList, add, pin and remove profile sources
ccshelf config unsetPut one setting back to its default

ccshelf config edit#

Open a copy of config.toml (mode 0600, in the same folder) in the editor named by $VISUAL or $EDITOR (split on spaces, quotes group words, never run through a shell). When the editor exits, the command checks the copy like the real file. The copy replaces config.toml only if it is valid. Comments are kept, because the command writes the text as you saved it. It keeps the previous file as config.toml.bak. If the copy is invalid, the command prints the errors with line numbers, does not touch config.toml and keeps the copy so you can fix it. The command needs a terminal and an existing file (ccshelf init creates it).

--path prints the file name instead, for scripts and for editors you start yourself.

Usage

ccshelf config edit [flags]

Flags

FlagValueDescription
-h, --helphelp for edit
--pathprint the configuration file path instead of opening it
--yesconfirm the write after the check, but never accept trust

ccshelf config path#

Print the path of config.toml (the --config file when given). The file need not exist.

Usage

ccshelf config path [flags]

Flags

FlagValueDescription
-h, --helphelp for path

ccshelf config set#

Change one setting of the configuration. The keys are: trust.on_change, trust.require_pin, trust.trust_project_profiles, trust.branch_check_interval, update.mode, update.interval, catalog.remote_url, default_account, ui.color, ui.interactive. Values:

- true or false
- trust.on_change: prompt or fail
- update.mode: off, notify or install
- update.interval: a duration such as 24h (1h to one year)
- trust.branch_check_interval: a duration such as 24h (1h to one year)
- catalog.remote_url: an https URL
- default_account: an account name
- ui.color: auto, always or never
- ui.interactive: auto or never

The command refuses anything else. Accounts and sources have their own commands, and the rest needs "config edit".

Turning trust.require_pin off, trust.trust_project_profiles on, or update.mode to install weakens a security setting and needs --yes without a terminal.

Usage

ccshelf config set [key] [value] [flags]

Examples

ccshelf config set update.mode notify
ccshelf config set update.interval 48h
ccshelf config set trust.on_change fail

Flags

FlagValueDescription
-h, --helphelp for set
--yesconfirm the write (and a weakening change), but never accept trust

ccshelf config show#

Print the sources (numbered from 1, with the numbers that config source pin and rm take), trust, update, catalog, accounts and ui settings. The command marks a value that the file does not set with (default). A missing file shows the defaults.

Usage

ccshelf config show [flags]

Flags

FlagValueDescription
-h, --helphelp for show

ccshelf config source#

Change the [[sources]] of the configuration. Sources are numbered from 1 in the order of "config source ls". The order carries no meaning. The command fetches nothing and records no trust. ccshelf fetches shared profiles when you first use them, and they need your trust then.

Usage

ccshelf config source [command]

Flags

FlagValueDescription
-h, --helphelp for source

Subcommands

CommandWhat it does
ccshelf config source addAdd a profile source (git, dir or plugin)
ccshelf config source lsList the configured profile sources
ccshelf config source pinChange the pinned ref or the tracked branch of git source number n
ccshelf config source rmRemove source number n

ccshelf config source add#

Add one profile source with exactly one of these flags:

- --git-url, with --ref or --branch, and --path for the folder inside the
  repository
- --dir, an absolute directory
- --plugin (name@marketplace), with --marketplace and --path

The command checks the source with the rules of the configuration file and refuses an exact duplicate. For a duplicate, use "config source pin" or "config source rm". The command fetches and trusts nothing.

In a terminal, without any of those flags, the command asks the questions.

A source with --branch follows a branch, which can move. A run still uses the commit you trusted, and every new commit needs your trust again. Adding one weakens a setting and needs --yes without a terminal. The same applies to a git source that is not pinned to a tag or full commit. That source is possible only while trust.require_pin is off.

Usage

ccshelf config source add [flags]

Examples

ccshelf config source add --git-url git@ghe.example.com:acme/claude-marketplace.git --ref v2026.10.1
ccshelf config source add --git-url git@ghe.example.com:acme/claude-marketplace.git --branch main --yes
ccshelf config source add --dir ~/team-profiles
ccshelf config source add --plugin org-profiles@acme --marketplace acme/claude-marketplace

Flags

FlagValueDescription
--branchstringgit source: branch to track, instead of --ref
--dirstringdir source: absolute directory of profiles
--git-urlstringgit source: repository URL
-h, --helphelp for add
--marketplacestringplugin source: the marketplace source the plugin must come from (owner/repo or git URL)
--pathstringgit or plugin source: folder inside the repository or plugin (git default: profiles)
--pluginstringplugin source: name@marketplace
--refstringgit source: tag or full commit id to pin to
--yesconfirm the write (and a weakening change), but never accept trust

ccshelf config source ls#

List the [[sources]] with the numbers that config source pin and rm take. ccshelf always searches your personal profiles directory, and the list does not show it.

Usage

ccshelf config source ls [flags]

Aliases: ls, list

Flags

FlagValueDescription
-h, --helphelp for ls

ccshelf config source pin#

Change the tag or full commit id that git source number n (see config source ls) is pinned to, or make it track a branch with --branch. Give --ref or --branch, not both. A source can switch between a tag or commit and a branch. A branch can move, so a switch to a branch weakens a setting and needs --yes without a terminal. The next run that needs a profile from that source fetches the new ref. When its commit differs from the one you trusted, the profile needs your trust again. This command never records trust. Pinning to something that is not a tag or full commit is possible only while trust.require_pin is off, and it needs --yes without a terminal.

Usage

ccshelf config source pin [n] [flags]

Examples

ccshelf config source pin 1 --ref v2026.11.0
ccshelf config source pin 1 --branch main --yes

Flags

FlagValueDescription
--branchstringthe branch to track, instead of --ref
-h, --helphelp for pin
--refstringthe new tag or full commit id
--yesconfirm the write (and a weakening change), but never accept trust

ccshelf config source rm#

Remove the source with number n (see config source ls). Profiles from it no longer appear. The command keeps the trust records already made for its profiles as they are, and does not delete them.

Usage

ccshelf config source rm [n] [flags]

Aliases: rm, remove

Examples

ccshelf config source rm 2

Flags

FlagValueDescription
-h, --helphelp for rm
--yesconfirm the write, but never accept trust

ccshelf config unset#

Put one setting back to its default (the same keys as config set). The command removes the key from the file where it can. Otherwise it writes the key with its default.

Usage

ccshelf config unset [key] [flags]

Examples

ccshelf config unset update.interval

Flags

FlagValueDescription
-h, --helphelp for unset
--yesconfirm the write, but never accept trust

ccshelf init#

Create config.toml and your personal profiles directory. With --git-url the org data repo becomes a profile source. Pin it with --ref (a tag or a full commit id), or track a branch with --branch. A branch can move: ccshelf runs the commit you trusted, and every new commit on the branch needs your trust again. With --dir another local profiles directory becomes a source. In a terminal, running without source, account or update values starts the full setup wizard. It shows a summary and asks before writing (default no). Partial flag runs do not prompt. --yes confirms writing only, never trust. The wizard prints an equivalent flag command at the end. Nothing is fetched here. ccshelf fetches profiles from a shared source when you first use them, and they need your trust then.

Automatic updates are off unless you turn them on:

- --update-mode notify checks for a newer release once a day and prints one
  line when there is one.
- --update-mode install also installs it (same major version only).

The full wizard asks once.

Usage

ccshelf init [flags]

Examples

ccshelf init
ccshelf init --git-url git@ghe.example.com:acme/claude-marketplace.git --ref v2026.10.1
ccshelf init --git-url git@ghe.example.com:acme/claude-marketplace.git --branch main
ccshelf init --account-name work

Flags

FlagValueDescription
--account-dirstringdirectory of that account (default ~/.claude-<name>)
--account-namestringalso create an account with this name (see: ccshelf account add)
--branchstringbranch the git source tracks, instead of --ref (every new commit needs trust again)
--dirstringabsolute directory of profiles to add as a dir source
--forcereplace an existing configuration file
--git-urlstringorg data repo URL to add as a git source
-h, --helphelp for init
--pathstringfolder inside the repo that holds the profiles (default "profiles")
--refstringtag or full commit id the git source is pinned to
--update-modestringautomatic update mode: off, notify or install (default: asked in the full wizard, otherwise off)
--yesconfirm writing in the full wizard (never accepts trust)

ccshelf shell-init#

Print one function per profile (cs-<profile>) that runs "ccshelf run <profile>" with the remaining arguments passed through. Load it with:

eval "$(ccshelf shell-init zsh)"          bash, zsh
ccshelf shell-init fish | source          fish
ccshelf shell-init pwsh | Out-String | Invoke-Expression

Only profiles from local directories are listed, so starting a shell never touches the network. Add others with --profile. For cmd.exe, --write-cmd-shims <dir> writes cs-<profile>.cmd files into a directory on PATH.

Usage

ccshelf shell-init [bash|zsh|fish|pwsh|cmd] [flags]

Flags

FlagValueDescription
-h, --helphelp for shell-init
--profilestringArrayalso define a function for this profile name (repeatable)
--write-cmd-shimsstringwrite cs-<profile>.cmd files into this directory (cmd.exe)

ccshelf update#

Download the newest ccshelf release, verify it and replace this binary.

The archive's SHA-256 must match checksums.txt of the same release. The command gets checksums.txt over HTTPS without credentials. If cosign is on PATH, the command also verifies the keyless signature of checksums.txt against the project's release workflow. A mismatch stops the update. With --require-signature, a missing cosign is an error. The command keeps the previous binary as <name>.old. --rollback restores it.

Nothing contacts the network unless you run this command or set [update] mode in config.toml (off by default). Without --force, the command does not replace these, and prints the correct command instead:

- a copy installed by Homebrew, Scoop, WinGet, "go install" or a system package
- a development build

Usage

ccshelf update [flags]

Examples

ccshelf update --check
ccshelf update
ccshelf update --version v0.2.0 --yes
ccshelf update --rollback

Flags

FlagValueDescription
--allow-downgradeallow --version to install an older release
--checkonly report the current and latest version (exit 0 either way)
--dry-runshow what the update would download, verify and replace, and change nothing
--forcealso replace a package-managed or development build, or reinstall the same version (never installs an older release)
-h, --helphelp for update
--prereleaseconsider pre-releases when looking for the latest
--require-signaturefail (before anything else) unless cosign is available to verify the release signature
--rollbackrestore the previous binary kept by the last update
--versionstringinstall this release (for example v0.2.0) instead of the latest
--yesdo not ask for confirmation

ccshelf version#

Print the ccshelf version

Usage

ccshelf version [flags]

Flags

FlagValueDescription
-h, --helphelp for version