Skip to content

release: v0.7.0 - #42

Merged
subbeh merged 35 commits into
mainfrom
develop
Oct 25, 2026
Merged

subbeh merged 35 commits into
mainfrom
develop

Conversation

@subbeh

@subbeh subbeh commented Oct 25, 2026

Copy link
Copy Markdown
Owner

Release v0.7.0. The release notes are the CHANGELOG's 0.7.0 section.

After merging, tag v0.7.0 on main to run the release workflow.

subbeh and others added 30 commits October 17, 2026 06:44
Homebrew 7 does not install an untrusted cask during a tap migration, so
existing formula users have to trust and install the cask themselves.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The long #encrypted, #template and #symlink attributes are replaced by
#enc, #tmpl and #link, for scripts too. Any attribute mate does not
recognise is now an error naming the file, as is a #perm: mode that is
not octal. Before, it was dropped silently, so a typo deployed the file
without its effect, and a leftover #encrypted would have deployed
ciphertext.

The state database is migrated once (user_version 1) to rewrite recorded
script and source paths to the short names. Scripts are looked up by
path, so renaming the sources would otherwise make every #once script
look unrun.

BREAKING CHANGE: sources and scripts named with #encrypted, #template or
#symlink must be renamed to #enc, #tmpl or #link.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Brings the v0.5.0 and v0.6.0 release merges into develop's history, so
git describe (and with it mate version) sees those tags.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
`mate add -s <name>` now asks to create the source when its directory
does not exist, then adds the file to it. The config is left untouched;
a warning reminds the user to list the source under `sources:`.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The machine-local config moves from ~/.config/statemate/mate.yaml to
~/.config/statemate/config.yaml; config.yml is accepted too. The old
name is no longer read.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Variable values containing {{ are rendered as templates, in every
layer and inside lists and maps, so '{{ cmd "..." }}' replaces the
variable_commands key, which is removed. cmd now fails rendering on a
non-zero exit, showing stderr, instead of returning an empty string.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Change markers, doctor check results, warnings and errors, script and hook
progress, and section headers are colored. fatih/color turns color off when
stdout is not a terminal or NO_COLOR is set. The three copies of the marker
switch become ChangeStatus.Marker, which also gives mate check its missing
import marker.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A global --no-color turns colored output off, alongside the automatic
switch-off when stdout is not a terminal or NO_COLOR is set.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
--log-file appends a log of each run: every external command with its
exit code and duration, and the error the run ended with. At
--log-level debug it also records the resolved config and profile,
each file's status, conflict answers, and which scripts and hooks were
due. Both can come from STATEMATE_LOG_FILE/STATEMATE_LOG_LEVEL or
log_file/log_level in mate.yaml or the local config.

External commands now go through util.Command, which logs argv only,
never output or environment.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A script marked #noconfirm, or a hook with `confirm: false`, runs during
`mate apply` without a prompt, including when there is no terminal.
`--no-scripts` still skips them. Lists and status mark them noconfirm.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A source subdirectory can now deploy to multiple locations, e.g. a
shared Claude config into both ~/.claude.personal and ~/.claude.work.
Relative targets paths resolve under the global target base.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-v prints info log records to stderr and -vv adds debug ones. At info
the log file now records only what a run changed (files written, moved
or removed, source-tree changes, forgotten files, secrets fetched,
scripts, hooks and packages), and writes its run header only before the
first record. Every external command now logs at debug.

BREAKING CHANGE: apply -V/--verbose is now -l/--list, packages status -v
is now -d/--descriptions, and hooks run -v and scripts run -v are
removed. mate -v no longer prints the version. go.mod requires Go 1.26.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
internal/plan owns what every read-only command rebuilt by hand: the
Env (config, profile, encryptor, template context, scanner) and the
Plan (scanned tree, changes, orphans). status, diff, check, clean,
scripts list, eval, managed, unmanaged, hooks and completions use it.

Because the pipeline exists once, scripts list now compares #tmpl files
rendered, an identity that fails to load is reported with its real
error where an #enc file needs it, and identity_command runs fewer
times per command.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
apply now gets its config, identity, template context and scan from
plan.Env, narrows the plan to its scope with Plan.Narrow, and reloads
after #before scripts with Env.Reload. Scope and its path matching
move into the plan package; the flag parsing and script/package
narrowing stay in cli.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sudoLstat ran GNU stat's -c format, which macOS's /usr/bin/stat
rejects, so every target needing sudo was reported as skipped. It
also cast the raw Unix mode to os.FileMode, losing the directory and
symlink type bits. The format now follows the platform and the type
bits are mapped, checked against the platform's real stat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Entry.SourceDir replaces deriving it from SourcePath and RelPath,
which took a special case for generated entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rename, encrypt, decrypt, delete and edit find their file through
Env.Resolve: an ordinary path, relative to the current directory and
then the source directory, naming an entry by its source (with or
without attributes) or its target. The suffix search rename, encrypt
and decrypt used, which took the first file that matched, is gone;
docs/adr/0001 records why. Resolve scans with .mate.yaml rendered, so
templated targets are found, and picks the current profile's variant
of a target or reports the ambiguity.

BREAKING CHANGE: a bare file name or a path suffix no longer finds a
managed file in rename, encrypt or decrypt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
runRemovalHooks takes the Env that clean, delete and rename already
have, hooks run reuses the template context loadHookEnv built, and add,
packages and scripts run call plan.FromConfig directly. That removes
newScanner and newTemplateContext, and the doubled "creating template
context:" prefix their callers added to the Env's own error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Apply, status, the conflict diff and mate diff each decrypted and rendered
entries themselves, with different rules: status swallowed render errors,
and the diffs went through temp files and paths. One render now feeds all
of them, and Diff compares bytes, reading the target with the sudo fallback.
The conflict diff uses diff_tool too.
…ange script

- Read triggers from a "# Onchange:" comment near the top of the script:
  "self" runs it when the script changed since its last run, and target
  patterns run it when a matching file in its source has pending changes
- Fail discovery on an empty comment, an invalid pattern, or the comment
  on a script that is not #onchange
- Track target paths alongside changed sources so patterns can be matched
- Move target pattern matching from hooks to source as MatchTarget and
  export config.ValidatePattern for reuse
- Document the comment in the scripts and hooks guides
Cut the [Unreleased] section as 0.7.0. It removes variable_commands,
declares packages as a list and renames mate packages status to list,
alongside new features such as # Onchange: triggers, -v logging and
multi-target sources, so this is a minor pre-1.0 release.
@coderabbitai

coderabbitai Bot commented Oct 25, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b2153f0b-f369-4bc2-903f-f6f55f5310ff
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@subbeh
subbeh merged commit d800ba0 into main Oct 25, 2026
9 checks passed
@subbeh
subbeh deleted the develop branch October 25, 2026 04:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant