Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 43 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,10 @@ cfg status
`cfg doctor` is read-only. Run it before the first import for a new database or
`.cfg.toml`; it reports secret-deny matches, large fields, and live-rule/key
issues in one pass, with paste-ready `secret_fields` and `ignore_fields`
suggestions.
suggestions. `cfg doctor --status` prints a "where am I" header: the resolved config
file, env, target database, identity mode and whether it is verified, store reachability,
and how many records are tracked or drifted — plus a warning if a `needs_approval`
environment is still in `open` identity mode (writes would succeed unaudited).

Check drift:

Expand All @@ -212,10 +215,24 @@ cfg status
cfg diff agent_configs:agent_planner =HEAD =live
```

Commit a full JSON document:
Edit a few fields in place (the fast path — no temp file). `cfg set` fetches the live
document and commits the change through the same drift-guarded path as `cfg commit`, so
it refuses on out-of-band drift rather than clobbering it:

```bash
cfg set modelgarden_models:openai/gpt-4o-mini enabled=true retry.max=3 -m "enable + retry"
```

Values are JSON-coerced (`enabled=true` → bool, `n=5` → int, `tags=["a","b"]` → list);
prefix with `str:` to force a string (`version=str:1.0`). Use `cfg edit <record>` to hand-edit
the whole document in `$EDITOR`.

Commit a full JSON document (add `--dry-run` to preview the field-level delta and exit
without writing):

```bash
cfg commit agent_configs:agent_planner --from planner.json -m "tune planner routing"
cfg commit agent_configs:agent_planner --from planner.json --dry-run
```

Commit multiple records as one batch intent:
Expand Down Expand Up @@ -305,12 +322,16 @@ Common commands:
```bash
cfg init
cfg doctor [record]
cfg doctor --status
cfg import --all -m "initial import"
cfg status [record]
cfg diff <record> [from] [to]
cfg impact <record> [from] [to]
cfg commit <record> --from <file.json> -m "message"
cfg commit <record> --from <file.json> --dry-run
cfg commit --bulk-from <batch.json> -m "message"
cfg set <record> field=value nested.field=value -m "message"
cfg edit <record> -m "message"
cfg branch list
cfg branch create <name> --from main
cfg branch delete <name>
Expand All @@ -337,7 +358,17 @@ cfg whoami
cfg ui
```

Every command supports `--json` for scripts and agents.
Every command supports `--json` for scripts and agents. By default output is human-readable
when stdout is a terminal and JSON when piped or redirected; set `CFG_OUTPUT=json|human|auto`
to control this, and `--json` always forces JSON.

Every refusal and terminal outcome also carries a `next` block — a plain-language reason plus
the exact next command(s) to run. On the CLI it prints to stderr; over `--json`/MCP it is a
structured `next` field so agents can act on `next.commands` directly.

Environment defaults: `CFG_ENV` (default env), `CFG_CONFIG` (config file path), and
`CFG_AUTHOR` (author) let you set a session once instead of repeating flags. cfgit also
discovers `.cfg.toml` by walking up from the current directory.

Refs:

Expand Down Expand Up @@ -413,10 +444,17 @@ The MCP server exposes the same operations with a uniform envelope:
"status": "ok",
"code": 0,
"message": "",
"data": {}
"data": {},
"state": null,
"next": null
}
```

`state` echoes the outcome's terminal state (for example `changed_outside_cfgit`), and `next`
carries a self-teaching remedy — `{why, remedy, commands, docs}` — when the outcome needs one
(a refusal, drift, a blocked batch, an identity/permission failure). Agents should branch on
`state` and follow `next.commands`; both are `null` on a clean success.

Tools include:

- `cfg_status`
Expand All @@ -425,6 +463,7 @@ Tools include:
- `cfg_impact`
- `cfg_commit`
- `cfg_bulk_commit`
- `cfg_set`
- `cfg_branch_list`
- `cfg_branch_create`
- `cfg_branch_delete`
Expand Down
72 changes: 66 additions & 6 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,48 @@ secret-shaped fields and values from `[secrets]`. Fields in `secret_fields` are
stripped before history. Use `--allow-secret` only for intentional fixtures or
false positives; cfgit records that override in history metadata.

## Preview a commit

Add `--dry-run` to a single-record commit to see the exact field-level delta versus the live
record and exit without writing. It returns `would_commit` with the changes, or the same
`changed_outside_cfgit` / `noop` a real commit would, and still runs the secret policy so a
blocked secret surfaces before you write:

```bash
cfg commit agent_configs:agent_planner --from planner.json --dry-run
```

## Fast field edits (set / edit)

For a few scalar fields you do not need a full document or a temp file. `cfg set` fetches the
live document, applies your changes, and commits through the same path as `cfg commit` — so it
still refuses on out-of-band drift instead of clobbering it (it is not a raw write):

```bash
cfg set modelgarden_models:openai/gpt-4o-mini enabled=true retry.max=3 -m "enable + retry"
```

Paths are dotted, with list indices as `tags[0]`. Values are JSON-coerced — `enabled=true`
becomes a boolean, `n=5` an integer, `tags=["a","b"]` a list — and a `str:` prefix forces a
string (`version=str:1.0`). Add `--dry-run` to preview. To hand-edit the whole document in your
`$EDITOR` instead, use `cfg edit <record> -m "message"`.

## Situational awareness

`cfg doctor --status` prints a one-look header of where you are pointed: resolved config file,
env, target database, identity mode and whether it is verified, store reachability, and the
number of tracked and drifted records. If a `needs_approval` environment is still in `open`
identity mode — so writes would succeed unaudited — it prints a warning with the fix. That same
warning also prints on any mutating command against such an environment; suppress it in scripts
with `CFG_WARN_OPEN_MODE=0`.

## Guidance on every outcome

Every refusal and terminal outcome carries a `next` block: a plain-language reason plus the
exact next command(s) to run (for drift, that is `cfg diff` then `cfg adopt`). On the CLI it
prints to stderr; over `--json` and MCP it is a structured `next` field, so agents can follow
`next.commands` without guessing.

## Branches and PRs

Branching is opt-in:
Expand Down Expand Up @@ -274,14 +316,32 @@ shows recent activity across all configured records: current live drift plus the
latest cfgit history entries. Selecting one of those entries opens that record's
normal history and diff view.

## JSON mode
## Output mode

By default output is human-readable when stdout is a terminal and JSON when piped or
redirected, so interactive use reads well while pipelines stay parseable. Control it with
`CFG_OUTPUT`:

```bash
cfg status # human on a TTY, JSON when piped
cfg --json status # always JSON
CFG_OUTPUT=json cfg status # always JSON
CFG_OUTPUT=human cfg status # always human
```

`--json` and `CFG_OUTPUT=json` always force JSON. Agents and scripts should branch on `status`
and `state`, not on human-readable text.

## Session defaults

Every command supports JSON output:
To avoid repeating flags, set environment defaults once:

```bash
cfg --json status
cfg --json diff agent_configs:agent_planner
export CFG_ENV=prod # default for --env
export CFG_CONFIG=./cfgit/aistudio.cfg.toml # default for --config-file
export CFG_AUTHOR=you@example.com # default author (open identity mode)
```

Agents and scripts should branch on `status` or the command output state, not on
human-readable text.
cfgit also discovers `.cfg.toml` by walking up from the current directory, so you can run it
from a subdirectory without `--config-file`. Global flags (`--config-file`, `--env`, `--author`,
`--branch`, `--json`) go before the subcommand: `cfg --env prod status`.
Loading