Migrating From Trunk - axnic/rtunk GitHub Wiki
Migrating From Trunk
Point CI and hooks at the rtunk binary: your .trunk/trunk.yaml, trunk-ignore comments and
plugin sources work unchanged. Six behaviors differ, listed
below, so nothing about the switch is discovered in CI.
rtunk check # reads .trunk/trunk.yaml as-is
This page does not explain how to use rtunk itself; see Command Reference
and Configuration Reference for that.
What carries over unchanged
Three things travel from trunk to rtunk without translation (AGENTS.md's "How it relates to
trunk" section):
- Configuration.
rtunkunderstands.trunk/trunk.yamlas-is — no rewrite is required to start.rtunk's own native config file,.rtunk/rtunk.yaml, is modeled closely on trunk's schema and semantics, so moving to it later is a rename plus whatever new, rtunk-only keys you choose to add, not a rewrite. See Configuration Reference for the exact discovery and precedence rules. - Ignore comments.
trunk-ignore(...),trunk-ignore-all(...), and the-begin/-endblock form are permanent, fully equivalent aliases ofrtunk's ownrtunk-ignoredirectives — the same matching regex accepts either prefix. There is no deadline to rewrite existingtrunk-ignorecomments. See Ignoring Issues for every form and its matching rules. - Ignored paths.
lint.ignore(linters:andpaths:entries,ALLfor every linter) works as in trunk for gitignore-style globs, with one exception: a!negation is rejected as a configuration error instead of being applied. See Configuration Reference. - The plugin ecosystem.
rtunkconsumes trunk-io/plugins directly — the same linter/tool/runtime/action definitions trunk itself reads, not a reimplementation of linter metadata. Aplugins.sourcesentry pointing at that repository (or a fork of it) works unchanged.
Compatibility is scoped to configuration only: cache layout, the CLI surface beyond the commands
trunk and rtunk both have, and output rendering carry no compatibility constraint and are not
covered by the guarantee above.
Behavioral differences to expect
Items 1, 3–5, and 6 are ROADMAP.md's own closed
list of deliberate divergences — recorded there so none of them is ever mistaken for an open bug.
Item 2 is not a separate ROADMAP entry; it is the current, already-implemented flag-level
consequence of item 1's decision, surfaced here because it changes how an existing trunk check --fix invocation needs to be rewritten. None of the six is something rtunk is still working
toward matching trunk on — all are shipped, current behavior. Full rationale for each is in
Decision Log.
1. Plain check does not run formatters
- trunk: a
checkrun also runs every enabled formatter and reports an unformatted file as a normal, autofixable finding. - rtunk: plain
checkonly ever runs genuine checking commands; formatting is never a side effect ofcheckby default. - Why: running every formatter on every checking invocation was judged an annoying default — a formatting-only concern surfacing as a failure on every check, for a repository that may not want formatting enforced as a gate at all (Decision Log).
- To reproduce trunk's default behavior: pass
--format-before-check, which runs every enabled formatter first, then checks the reformatted files — see item 2 below.
2. check --fix's scope is narrower than trunk's, under a different flag split
- trunk:
check --fixruns the "format, then check" sequence — every formatter, then the checking pass — and applies linter fixes. - rtunk:
check --fix(-y) applies linter-level fixes only — every non-formatter fix command plus every finding's own attached autofix — then reports whatever remains; it never runs a formatter. The combined "format, then check" sequence trunk's--fixperforms is a separate, opt-in flag:--format-before-check. Given together,--format-before-checkand--fixcompose in order: format pass, checking pass, fix application, final checking pass. - Why: this is the direct consequence of item 1's decision — since plain
checkno longer formats by default,--fix's formatting half moved to its own explicit flag rather than staying bundled under one name with two different meanings (Decision Log). - Migration impact: a CI script or pre-commit hook that relies on
trunk check --fixreformatting files needsrtunk check --fix --format-before-checkinstead, or two separate invocations (rtunk fmtthenrtunk check --fix) — seertunk checkfor the full flag reference.
3. Windows is not a supported host platform
- trunk: ships and supports Windows as a host platform.
- rtunk: does not — there is no Windows build. A command variant declared Windows-only in the plugin catalog is skipped during configuration resolution rather than attempted, so an otherwise-working config does not fail on a Windows-restricted command; it simply never runs that variant. macOS and Linux are the two supported host platforms (see Installation).
- Why: no rtunk build for Windows exists today (Decision Log).
- Migration impact: a team running trunk on Windows hosts (developer machines or Windows CI
runners) cannot switch those hosts to
rtunkyet.
4. The run journal doesn't log file selection or provisioning
- trunk: its equivalent run history/journal records more context around each run, including what led up to running the recorded commands.
- rtunk: the run journal (
rtunk logs) records, per command invocation, its argv/cwd/PATH prefix, raw output, exit code, output-parser sub-invocation, and resulting findings, plus a run-level start/end marker. It deliberately does not record which files were selected for the run, or anything about provisioning (a tool/runtime already cached versus freshly fetched, fetch progress, a fetch failure). - Why: the journal's scope is the checking/formatting commands actually run and what they produced, not everything that led up to running them; if file-selection or provisioning visibility is ever needed, it belongs in a separate, purpose-built mechanism rather than an expansion of this journal (Decision Log).
- Migration impact: a workflow that inspects trunk's run history to see which files a given run
considered, or to debug a provisioning/download failure, cannot do the same through
rtunk logs.
5. Actions can't trigger on file changes or a schedule
- trunk: an action can declare a file-change trigger or a periodic-schedule trigger, alongside git-hook triggers.
- rtunk: refuses both. An action whose configuration relies on a file-change or schedule trigger — even mixed alongside a supported git-hook trigger — is rejected outright at configuration validation, not silently accepted and never fired.
- Why: both trigger kinds require a background process watching for changes or waiting out an
interval, and
rtunkrefuses to run as a daemon under any circumstance — every invocation is a single, foreground, exit-when-done run (Decision Log). - Migration impact: an action configuration that relies on either trigger kind needs an external
scheduler (cron, a CI schedule trigger, a file-watcher wrapper) invoking
rtunk actions run/rtunk checkinstead —rtunkwill not do the watching or waiting itself.
6. A failed action never raises a desktop notification
- trunk: an action can set
notify_on_error: true|false, surfacing a native OS notification when its command exits non-zero. - rtunk: does not parse
notify_on_errorat all, and never raises a notification on action failure. The failure is still visible in the command's own output, its exit code, andrtunk logs. - Why: maintaining a native OS notification integration (and its darwin/linux/windows backend differences) was judged not worth the ongoing surface for a CLI tool (Decision Log).
- Migration impact: a workflow relying on
notify_on_errorfor failure visibility needs another surface for that — the process's own exit code (CI), orrtunk logs(local).
Not a difference: exit codes
rtunk's exit codes for check, fmt, and run are identical to trunk's: 0 on success or on a
run that found nothing to report, 1 on any finding, error, invalid config, nonexistent path, or
failed tool invocation. Only 0 and 1 exist — there is no separate code distinguishing "findings"
from "error." A fmt that fixes files exits 0, not an error. A CI pipeline or pre-commit hook
gating on trunk's exit code needs no change here; this is called out explicitly so a migrating team
does not spend time re-verifying something that already matches.
Switching a repository
- Point CI and pre-commit hooks at the
rtunkbinary instead oftrunk. Same invocation shape for the commands both tools share (check,fmt); adjust any script that depended on item 2's flag split above. On GitHub Actions, replacetrunk-io/trunk-actionwith the GitHub Action (axnic/rtunk), which installs, verifies and caches rtunk and reports findings as annotations (check-mode: changed-since-baselimits it to the changed files). - Leave
.trunk/trunk.yamlin place, or move it to.rtunk/rtunk.yaml. Both work:rtunkreads.trunk/trunk.yamlwhen no.rtunk/rtunk.yamlexists. Renaming is optional and can happen later, at your own pace — see Configuration Reference for the exact discovery order. trunk's ownuser_trunk.yamlanduser.yamlnext to the config are read too, as local override files. - Run
rtunk checkonce and diff its findings against the lasttrunk checkrun. This is the practical way to catch any of the six itemized divergences above in your actual configuration — a missing formatter finding under plaincheck(item 1), a Windows-only command that no longer runs (item 3), or an action that now fails validation (item 5) will show up as a concrete difference in this diff rather than as a surprise later.
Where to go next
- Checking Code — how
rtunk checkselects files, reports and sets exit codes - Formatting Code —
rtunk fmt, the replacement for trunk's formatting pass - GitHub Action — run rtunk in GitHub Actions, in place of
trunk-action - Decision Log — the full rationale behind each difference