Migrating to 2.0
Catenary 2.0 is a major release. Every breaking change is in user
configuration — your ~/.config/catenary/config.toml and any project
.catenary.toml. Agent-facing workflow changes (implicit editing start, the
catenary diagnostics command) need no migration: the host’s session primer
teaches them fresh each session, so they are not an upgrade concern.
If you have never written a [commands] section, only the last item — the new
optional knobs — applies to you, and even those have safe defaults.
At a glance
| Change | Affects you if… | Action |
|---|---|---|
Writes resolve-or-deny; allow_file_redirects retired | your config set allow_file_redirects | delete the key — the write model is now automatic |
awk/sed dropped from the default pipeline | your [commands].pipeline lists awk or sed | remove them; sweep with native sed -i / perl -i -pe |
Project [commands] enforcement keys ignored | you set enforcement keys in a .catenary.toml | move them to user config |
| New diagnostics + notification knobs | — (optional) | nothing required; tune if desired |
1. Writes resolve-or-deny
The allow_file_redirects knob is retired. There is no on/off switch for
redirects any more, and setting the key has no effect (a stale config still
loads — the key is silently ignored).
In its place, every shell write is judged by one config-free rule:
resolve-or-deny. Before a command runs, the PreToolUse hook resolves the
complete set of files it will write — from shell grammar (>, >>, &>,
heredoc targets), argument convention (cp, mv, tee, sed -i, ln),
checkable interpreter programs (awk, perl -pe), or a state query
(hook-expanded globs, git asked about its own index). A write whose target set
resolves is allowed and recorded into your modified-set, so the next
catenary diagnostics sees it; catenary grep pat > hits.txt is a first-class,
tracked redirect. A write whose targets cannot be seen — > $DYNAMIC,
python -c "open(…,'w')", xargs sed -i — is denied with a message that
teaches the resolvable form. File-descriptor duplications (2>&1, >&2) and
device sinks (/dev/null, /dev/stdout, /dev/stderr) are never writes.
If your config set allow_file_redirects, delete the line. Resolvable
redirects that used to need the opt-in now just work; the rare opaque one is
denied with guidance.
See Command Filtering → The write model.
2. awk and sed removed from the default pipeline
The recommended [commands].pipeline no longer includes awk or sed. The
shipped default is now:
pipeline = ["grep", "wc", "jq", "sort", "tr", "cut", "uniq"]
Both awk and sed can execute arbitrary code and write files in-band
(sed -i/sed w, awk’s system() and print > file). The filter
quote-masks an interpreter’s program string before parsing, so it cannot see
those side effects — which would silently bypass the tracked Edit/Write path.
For that reason they are denied at every pipeline position now.
If your pipeline list includes awk or sed, remove them. Your existing
file is honored as written, so they keep working until you regenerate or edit
your config — but they are an exec/write hole and should be dropped.
For sweeping multi-file edits, reach for native sed -i (or perl -i -pe
when you need look-around or back-references): the PreToolUse hook resolves
the write-set from the command line and records the touched files into the
diagnostics batch, so diagnostics stay complete. See Command Filtering → The
write model.
Regenerate the recommended template any time with catenary config.
See Command Filtering → Recommended [commands] config.
3. Project [commands] enforcement keys are ignored
In a project .catenary.toml, the [commands] table now honors only
build (the per-root build tool). Every enforcement key is user-level only
and is ignored at project scope:
client_enforcement_onlyallowpipelinedenydeny_flagsallow_flagsscript_hostsguidance
Catenary warns when it sees one of these in a project file.
Why: the command filter resolves daemon-globally — one Catenary daemon serves every connected session. A project that changed enforcement would change the filter every session sees, including agents in unrelated repositories. The tighten/turn-on direction would fail silently (enforcement simply never engages), so the keys are refused at project scope outright.
If you set any of these in a .catenary.toml, move them to your user config
at ~/.config/catenary/config.toml. build stays where it is:
# .catenary.toml — still valid
[commands]
build = "make"
# ~/.config/catenary/config.toml — enforcement lives here now
[commands]
allow = ["git", "gh", "cp", "rm", "mkdir", "mv", "touch", "cat", "head", "diff"]
pipeline = ["grep", "wc", "jq", "sort", "tr", "cut", "uniq"]
[commands.deny]
git = ["grep", "ls-files", "ls-tree"]
See Command Filtering → Project-scoped commands.
4. New optional knobs
These are additive — they have defaults and require no action — but they are new surfaces you may want to set.
catenary diagnostics tuning
[tools]
diagnostics_severity = "error" # default
diagnostics_severity(default"error") — the minimum severity that labels a run “dirty” (vs “clean”). One of"error","warning","info","hint". A status label only: the run always exits0and prints every diagnostic; it no longer gates an exit code.
See Configuration → Diagnostics.
Notifications: threshold removed
The store-and-forward systemMessage notification queue retired, and with it
its severity floor. The [notifications] table now has one knob:
[notifications]
desktop = true # default — OS notifications for error-severity events
threshold— removed. Warns now persist on the TUI health dashboard (a warn is a health finding) and everything is queryable viacatenary query; neither is severity-tunable. A leftoverthresholddoes not break startup — it is ignored — butcatenary doctorflags it as an unknown key, so delete it.desktop(defaulttrue) — fire OS-level desktop notifications for error-severity events (the urgent interrupt).CATENARY_NOTIFY=0also suppresses.
See Configuration → Notifications and Notifications.
Not a migration concern
These changed in 2.0 but need no config action — the session primer teaches the current workflow each session:
- Editing starts implicitly on the first edit; there is no
editing startstep (it remains an idempotent no-op). editing stopis nowcatenary diagnostics— it ends the edit batch and prints diagnostics for every modified file.