Usage
actup <command> [paths...] [options]actup takes at most one path (a repo root); the default is the current working directory. Passing more than one path is a hard error. The default command is check.
Commands
check (default)
Scan workflows and composite actions, resolve every uses: ref, and report. No files are written. Exits non-zero when there is actionable or unresolvable work (see exit codes).
bun run actup check
bun run actup # same thing — check is the default
bun run actup check ../other-repoHuman output looks like:
actup
.github/workflows/ci.yml
! :12 actions/checkout: v3 -> v4
! :20 actions/setup-node: floating ref 'main' → pin to v4.0.2
✘ :28 some/action@weird-tag: non-semver tag — cannot compare
1 outdated · 1 floating · 0 pinnable · 0 unpinnable · 1 unresolvableupdate / fix
fix is an alias for update. Rewrites refs per the effective policy. When the effective policy.track is keep, update raises it to major for this invocation so it actually moves refs. Use --dry-run to preview without writing.
bun run actup update --dry-run # prints "would update <path>" lines
bun run actup update # writes changes, prints "updated <path>"Writes are atomic (temp file + rename) and span-surgical, so untouched lines keep their exact text and comments. A successful non-dry-run write resolves the "outdated" condition, so the exit code becomes 0 even though refs were outdated before the run. --dry-run keeps the findings-based code.
pin / pin --unpin
pin forces policy.pin = sha for the run: every resolvable ref is rewritten to its immutable commit SHA with a trailing # <tag> comment recording the original ref. pin --unpin forces policy.pin = tag, reversing a previous pin back to the tag stored in that comment.
bun run actup pin # actions/checkout@v4 → actions/checkout@<sha> # v4
bun run actup pin --dry-run # preview
bun run actup pin --unpin # actions/checkout@<sha> # v4 → actions/checkout@v4Unpin only reverses a pin when the trailing comment holds a non-SHA tag (i.e. one written by a prior pin). Floating branches (@main) and non-semver tags that have a known SHA are also pinned.
config
Print the fully-resolved effective configuration (defaults + file + env/flag overrides) as JSON.
bun run actup config{
"defaultHost": "github.com",
"fetch": { "apiMode": "graphql", "maxTagsPerRepo": 20, "cacheTtl": 3600, "offline": false },
"hosts": {},
"policy": { "track": "major", "pin": "keep", "bump": "major" },
"scan": {},
"output": { "format": "human", "githubAnnotations": false },
"overrides": []
}cache info | clear | path
Manage the SQLite version cache. A bare actup cache is equivalent to actup cache info. An unknown subcommand is a hard error (unknown cache subcommand: <x> (use info|clear|path)).
bun run actup cache info # entries: <n>\npath: <db path>
bun run actup cache path # just the cache db path
bun run actup cache clear # empties the cache, prints "cache cleared"$ bun run actup cache info
entries: 0
path: /home/you/.cache/actup/cache.dbThe cache file defaults to $XDG_CACHE_HOME/actup/cache.db, falling back to ~/.cache/actup/cache.db. If that location is unwritable or corrupt, the cache silently degrades to in-memory for the run.
schema
Print the config file's JSON Schema (derived from the canonical zod schema, so it never drifts from validation).
bun run actup schema
bun run actup schema > actup.schema.jsoncompletions [shell]
Emit a minimal completion script. Supported shells: bash, zsh, fish, powershell (alias pwsh). With no argument the shell is guessed from $SHELL, defaulting to bash.
bun run actup completions zsh > ~/.zsh/completions/_actup
bun run actup completions bash >> ~/.bashrcinit [dir]
Scaffold a starter actup.json in dir (default: cwd). The written config validates against the schema. Refuses to overwrite an existing actup.json (exit 2) unless --force is given. Exit 0 on success.
bun run actup init # writes ./actup.json
bun run actup init --force # overwrite an existing onehelp
actup help or -h/--help prints usage and exits 0.
Global flags
All flags come from the argument parser; values are required where noted.
| Flag | Effect |
|---|---|
-c, --config <path> | Use this config file (overrides ACTUP_CONFIG; missing file is a hard error) |
--format <fmt> | Output format: human, json or sarif. Unknown value is a hard error |
--color <when> | auto (default), always, never. auto = TTY and no NO_COLOR |
-q, --quiet | Suppress non-essential stdout (render output / "updated" lines) |
--offline | Never hit the network; resolve from cache only |
--github-annotations | Also emit ::warning / ::error workflow-command annotations |
--dry-run | update/pin: compute and report changes but do not write files |
--unpin | pin: reverse SHA pins back to their recorded tag |
-h, --help | Show help and exit 0 |
An unknown flag (anything starting with - that is not recognized) is a hard error. Hard errors print to stderr and exit 2.
Environment variables
| Variable | Effect |
|---|---|
ACTUP_CONFIG | Config file path (overridden by --config) |
ACTUP_FORMAT | human | json | sarif (applied to loaded config) |
ACTUP_OFFLINE | Sets offline when 1/true/yes (case-insensitive) |
NO_COLOR | Disables color under --color auto |
XDG_CACHE_HOME | Cache location base (default ~/.cache) |
XDG_CONFIG_HOME | User config base for actup/config.json (default ~/.config) |
Token variables (GITHUB_TOKEN/GH_TOKEN, GITLAB_TOKEN, GITEA_TOKEN) are covered in install.
Output formats
human— grouped per file, colorized severity marks (✘error,!warn,·info), with a one-line summary.up to daterefs are hidden.json—{ summary, findings[], errors[] }; each finding carriesfile,line,col,severityand the full finding union.sarif— SARIF 2.1.0 (actup/<kind>rule ids), suitable for GitHub code-scanning upload.up to daterefs are excluded.
--github-annotations prepends ::warning/::error lines (file, line, col) ahead of the chosen format; up to date and pinned refs are skipped.
Exit codes
The exit code is computed by classifyExit over the scan result and fully reflects findings and errors — a network error never yields a false 0.
| Code | Meaning | When |
|---|---|---|
0 | OK | No actionable findings, no unresolvable refs, no errors |
1 | Actionable | At least one outdated / floating / pinnable / unpinnable ref |
2 | Unresolvable | An unresolvable finding, or a parse/config/cache/notFound error |
3 | Network / auth / limit | Any network, auth or rateLimit error (short-circuits to 3) |
Precedence: a single network/auth/rateLimit error short-circuits the whole run to 3. Otherwise any parse/config/cache/notFound error or any unresolvable finding gives 2. Otherwise any actionable finding gives 1. Otherwise 0.
For update/pin without --dry-run, a result that would have been 1 (outdated) becomes 0 after a successful write, since the files are now current. 2 and 3 are still returned. Argument-parse errors and uncaught fatals exit 2.