shelbi config
View as markdownshelbi 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
| Command | Description |
|---|---|
inventory | Discover every Shelbi-owned configuration file and materialize an isolated candidate snapshot for safe editing. |
lint | Validate the selected configuration surfaces (live or staged) through Shelbi's production parsers. |
upgrade | Detect deprecated/legacy configuration forms, classify each as auto-heal or needs-judgment, and (with --apply) heal the safe ones. |
list-actions | Print every action with its mode, name, description, and the chord(s) bound to it after the keys.yaml merge. |
dump-keybindings | Dump the full default keymap as YAML (a starting point for ~/.shelbi/keys.yaml). |
check | Validate ~/.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:
| Field | Meaning |
|---|---|
schema_version | Inventory format version. A newer staged snapshot is rejected by an older shelbi (see Compatibility). |
shelbi_version | The shelbi build that produced the snapshot. |
staged_dir | Absolute 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 splitproject.yaml+local.yamlfor 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.jsonand 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.
| Flag | Type | Default | Description |
|---|---|---|---|
--all | flag | off | Include every locally registered project instead of just the resolved one. |
--apply | flag | off | Perform 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-judgment | flag | off | Show 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> | string | none | Apply 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|json | enum | human | Diagnostic 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-actionsPrint 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.
| Flag | Type | Default | Description |
|---|---|---|---|
-o, --out <OUT> | path | stdout | Write the dumped keymap to this file instead of printing it. |
--force | flag | off | Overwrite the --out file if it already exists. |
check
shelbi config checkValidate ~/.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 jsonLint every registered project's live configuration before a release:
shelbi config lint --allValidate a staged candidate directory you have been editing:
shelbi config lint --project demo --staged /tmp/shelbi-config-1234 --format jsonPreview 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 jsonSee what every action is bound to after your overrides are applied:
shelbi config list-actionsSee also
- System configuration: how the reserved configuration skill and system plugin drive these commands, plus ownership, fallback, and compatibility behavior.
- Global config: the
keys.yamlschema, modes, actions, chord syntax, and the built-in defaults. - Config modes: flat versus in-repo project
layouts, which shape the registration surfaces
inventoryreports. - Config upgrade: the boot-time
validate-and-upgrade pass
upgradeshares its detector with.