shelbi config

View as markdown
shelbi config <COMMAND> [OPTIONS]

shelbi config inspects and validates the configuration Shelbi owns. Three commands cover every configuration surface: inventory discovers the canonical files and materializes an isolated candidate snapshot you can edit safely, lint validates those surfaces through the same parsers Shelbi uses at runtime, and upgrade detects legacy or drifted forms and heals the safe ones. Three older commands (list-actions, dump-keybindings, check) stay focused on the TUI keybindings in ~/.shelbi/keys.yaml.

These commands are what the built-in configuration workflow runs. When you ask a built-in orchestrator to change Shelbi configuration, it drives inventory and lint behind the reserved update-shelbi-configuration skill so edits are staged, validated, previewed, and confirmed before any live file is touched.

Every subcommand accepts the global --root <PATH> (override the Shelbi root directory, else $SHELBI_ROOT, else the install-time default) and -p, --project <PROJECT> (defaults to $SHELBI_PROJECT or the registered project whose work_dir contains the current directory) flags.

Commands

CommandDescription
inventoryDiscover every Shelbi-owned configuration file and materialize an isolated candidate snapshot for safe editing.
lintValidate the selected configuration surfaces (live or staged) through Shelbi's production parsers.
upgradeDetect deprecated/legacy configuration forms, classify each as auto-heal or needs-judgment, and (with --apply) heal the safe ones.
list-actionsPrint every action with its mode, name, description, and the chord(s) bound to it after the keys.yaml merge.
dump-keybindingsDump the full default keymap as YAML (a starting point for ~/.shelbi/keys.yaml).
checkValidate ~/.shelbi/keys.yaml and print any errors or warnings.

inventory

shelbi config inventory [--project <PROJECT> | --all] [--format json]

Discover the canonical global and per-project configuration files, copy the ones that exist into a fresh candidate directory, and print a JSON manifest. Scope it with --project <PROJECT> for one project or --all for every locally registered project (the two are mutually exclusive); with neither, it covers the global surfaces plus the project resolved from your working directory.

The candidate snapshot lives in a temporary staged_dir. Edit files there, not the canonical originals, so nothing goes live until you apply it deliberately.

The manifest is a stable contract:

FieldMeaning
schema_versionInventory format version. A newer staged snapshot is rejected by an older shelbi (see Compatibility).
shelbi_versionThe shelbi build that produced the snapshot.
staged_dirAbsolute path to the candidate directory.
entries[]One record per configuration surface.

Each entry carries a logical_id (a stable name like global.keybindings or project.demo.workflow.task), its scope (global or project:<name>), the canonical_path it was read from, the relative candidate_path inside staged_dir, its format (yaml, json, or markdown), whether it exists, and whether it is lifecycle_owned. A lifecycle_owned surface is one Shelbi regenerates through its own lifecycle commands (for example shelbi reload), so changing it usually means running that command, not only writing the file.

lint

shelbi config lint [--project <PROJECT> | --all] [--staged <DIR>] [--format human|json]

Validate configuration surfaces without mutating them. By default lint reads live files; pass --staged <DIR> to validate a candidate directory produced by inventory instead. A staged snapshot is self-contained, so with --staged the --all flag means every project the snapshot represents, regardless of what is registered on the machine running the lint.

Lint scope

lint covers every configuration family Shelbi owns, each through the parser that Shelbi itself uses, so a clean lint means the file will load at runtime:

  • global preferences (config.yaml), the hub config (shelbi.yaml), and keybindings (keys.yaml);
  • per-project registration (flat demo.yaml, or the split project.yaml + local.yaml for in-repo config), statuses, workflows, and the workspace-settings template;
  • per-project Markdown (Zen Mode policy, agent instructions, the shared preamble) and per-agent settings.json and skills.

Diagnostics come back with a stable code (for example CONFIG_UNKNOWN_FIELD, KEYBINDINGS_COLLISION, WORKFLOW_STATUS_REFERENCE_INVALID, TEMPLATE_UNKNOWN_PLACEHOLDER, ZENMODE_SUMMARY_MISSING), a severity (warning or error), a source location, and often a remediation hint.

Exit code

lint exits 1 when the report is not clean: warnings and errors both count. Configuration is either valid or it is not, so a warning is not something to apply and move past; it slots the command cleanly into a pre-flight check.

upgrade

shelbi config upgrade [--project <PROJECT> | --all] [--apply | --needs-judgment | --apply-finding <ID>] [--format human|json]

Detect deprecated or legacy configuration forms and classify each as an auto-heal (a deterministic, non-lossy rewrite exists) or needs-judgment (ambiguous or potentially lossy, so a human decides). Detection is version-agnostic: it sniffs each file's content, not a schema version, so it works for a config authored by any past release. This is the same pass the hub runs on start and on shelbi reload; see Config upgrade for the full boot-time flow.

Read-only by default: it reports the findings the on-start pass would act on without touching a file.

FlagTypeDefaultDescription
--allflagoffInclude every locally registered project instead of just the resolved one.
--applyflagoffPerform every auto-heal write-back (as hub start and shelbi reload do), disclosing each on events.log, then print the residual. Needs-judgment findings are still left for you. Conflicts with --needs-judgment and --apply-finding.
--needs-judgmentflagoffShow only the needs-judgment findings, the channel the orchestrator surfaces to you. Each carries a stable id, the surface and location, the legacy form, the proposed fix, and why it needs judgment. Read-only, and detected live against the files on disk (the same basis as the bare report), so a fix you apply drops off the list on the next run with no hub restart.
--apply-finding <ID>stringnoneApply exactly one finding by its stable id (from --needs-judgment), reusing the auto-heal write-back for a single approved fix and leaving every other finding untouched.
--format human|jsonenumhumanDiagnostic output format.

The boot pass persists its residual to ~/.shelbi/config-upgrade-findings.json as the record behind the events.log disclosure, and removes that file once the config set is clean. The orchestrator does not replay that snapshot; it reads the live channel with --needs-judgment, so what it surfaces always matches the files on disk. A finding with no mechanical resolution (an unknown key that might be a typo or real data) is refused by --apply-finding with a pointer to edit the file directly.

list-actions

shelbi config list-actions

Print every action with its mode, name, description, and the chord(s) bound to it after the keys.yaml merge, so it reflects your overrides, not just the built-in defaults. This is the reference for what's bindable and what each action currently does.

dump-keybindings

shelbi config dump-keybindings [OPTIONS]

Dump the full default keymap as YAML. By default it prints to stdout — drop the output into ~/.shelbi/keys.yaml as a starting point for customization, then edit the chords you want to change. Pass -o, --out <OUT> to write the dump straight to a file instead, and --force to overwrite an existing file at that path.

FlagTypeDefaultDescription
-o, --out <OUT>pathstdoutWrite the dumped keymap to this file instead of printing it.
--forceflagoffOverwrite the --out file if it already exists.

check

shelbi config check

Validate ~/.shelbi/keys.yaml and print any errors or warnings. It exits 1 on errors, so it slots cleanly into a pre-flight script; warnings still exit 0. (config lint validates keys.yaml alongside every other surface; check is the keybindings-only view.)

Compatibility

The inventory manifest is versioned by schema_version. A staged snapshot is only valid for the shelbi build that produced it: linting a snapshot whose version a newer or older binary does not recognize is refused rather than misread. Take a fresh inventory with the shelbi you are running instead of reusing an old staged_dir. Unknown fields are reported (CONFIG_UNKNOWN_FIELD) rather than silently ignored, so a config written for a different Shelbi version surfaces as a diagnostic you can act on.

Examples

Take an inventory of one project and read the candidate directory it staged:

shelbi config inventory --project demo --format json

Lint every registered project's live configuration before a release:

shelbi config lint --all

Validate a staged candidate directory you have been editing:

shelbi config lint --project demo --staged /tmp/shelbi-config-1234 --format json

Preview the config-upgrade findings for one project, then read just the ones that need a human decision:

shelbi config upgrade --project demo
shelbi config upgrade --project demo --needs-judgment --format json

See what every action is bound to after your overrides are applied:

shelbi config list-actions

See also

  • System configuration: how the reserved configuration skill and system plugin drive these commands, plus ownership, fallback, and compatibility behavior.
  • Global config: the keys.yaml schema, modes, actions, chord syntax, and the built-in defaults.
  • Config modes: flat versus in-repo project layouts, which shape the registration surfaces inventory reports.
  • Config upgrade: the boot-time validate-and-upgrade pass upgrade shares its detector with.