3.0.0-beta.15). Features may change before the next stable release.Switch to stable →CLI Reference
ak update
Preview or apply project and global kit updates with drift-aware backups.
ak update refreshes AgentKit-owned project files or global kit installations while preserving user-owned content.
Syntax
ak update [project-dir] [options]
ak update --global [options]Before you run
- An implicit non-interactive preview exits
3. Add--dry-runfor an explicit preview that exits0, or--yesto apply. - A bare command in a TTY opens a unified wizard. Each CLI, global-kit, and project-kit update defaults to no;
--yesaccepts applicable steps. - Remote preview can still authenticate, check entitlements, download kit content, and update the cache before it calculates the plan.
--forceauthorizes replacement only after a snapshot unless--no-backupis set. It does not turn global installation into unconditional overwrite.--json,--quiet,--no-interactive, or a non-TTY selects scripted behavior. In an interactive project or global run, declining every prompt exits0.- An attended project update (TTY accept or
--yes) refreshes the trackedkits/tree, then every installed runtime of each project kit. See Project runtime refresh.
Arguments
[project-dir] selects a project. Without it, project mode discovers the current project unless --global is set. The command has no aliases.
Runtime targets and sources
Target validation uses both the selected scope and source:
| Scope and source | Valid targets |
|---|---|
| Project, remote | claude-code, codex, cursor, dsh, grok, omp, or pi |
| Global, remote | claude-code, codex, cursor, dsh, grok, or omp |
| Global, local | claude-code, codex, cursor, dsh, grok, or omp |
An explicit target that does not apply to its scope or source is rejected before
discovery or mutation and exits 2. In the unified wizard, the same selection
is projected onto each step: a project-only target such as pi is omitted from
the global step but remains available to the project step. If no selected target
applies globally, the wizard skips that step and continues.
In both scopes, --target a,b filters which installed runtimes refresh; unset
means every installed runtime. A requested runtime that has no install in that
scope is listed under skipped_targets rather than created. At project scope
the tracked kits/ tree still comes from one runtime's download: claude-code
when it is selected, installed, or nothing is selected; otherwise the first
selected runtime.
Project runtime refresh
After the tracked kits/ tree, an attended project update refreshes every
installed runtime of each project kit (.claude, .codex, and adapter roots)
through the same path as ak kit refresh, one pass per kit and
runtime. The kits it considers are the --kits list when given, otherwise the
kits tracked in kits/ plus every kit with an owned project install.
- A failed pass does not stop the others. Each pass reports its own row, and the
command exits
1after all passes finish. - A project that has only
ak kit initruntime installs, with no trackedkits/tree, refreshes those installs instead of exiting2. - Preview and
--dry-runlist each planned refresh as apreviewrow and write nothing. - The CLI preflight takes the highest kit CLI requirement across the selected runtimes.
- A project Claude Code plugin install is reported as
plugin_only, not converted. Refresh it withak kit refresh <kit> --target claude-code --switch-to-plugin --yes. - A runtime the remote source does not serve is skipped with reason
source_inapplicable; re-run with--local --kits-dir <dir>. - When the project directory resolves to the user-level install (for example,
the home directory), that runtime is skipped with reason
project_is_global_homeand never refreshed. Runak update --globalto refresh it. - If
--targetmatches no installed project runtime and there is no trackedkits/tree, the command exits2.
Background auto-update (opt-in)
--schedule daily|weekly turns on a detached background update that starts on
the first ordinary ak command after the chosen interval; --schedule off
stops it and clears its state. It refreshes the CLI and global kits, plus any
project opted in with --project <dir> (repeatable; the directory must
already be registered with ak projects add) whose git tree is clean and has
no live agent session. A background project update refreshes only the tracked
kits/ tree; it never refreshes project runtime installs. It records a notice
to run ak update <dir> --yes or ak kit refresh <kit> instead. --no-project <dir> (repeatable) opts a project back
out, even if its directory no longer exists. --status [--json] reports the
schedule and the last background result without changing anything; add
--ack to mark that result as seen.
These settings flags only write the auto_update: section of
~/.agentkit/config.yaml — they update nothing immediately, and none of
--schedule, --project, --no-project, --status, or --ack can be
combined with an update flag (--kits, --force, --global, …) or a
project-dir argument; run them as separate commands.
A background update never starts when AK_NO_AUTO_UPDATE=1 or CI is set, for
--json invocations, or for lifecycle/interactive top-level commands
(update, self-update, setup, onboard, kit, init, migrate,
backups, recover, gui, uninstall, completion, help, bootstrap*).
Liveness is tracked by a Kit hook (session-heartbeat.cjs) registered on
SessionStart, UserPromptSubmit, Stop, and SessionEnd; it writes a
per-session marker under the AgentKit home so the updater skips a project that
has a running session, and it never blocks or fails a session (exits 0 on
its own failure). On SessionStart, an unacknowledged background result
prints as a one-line notice; acknowledge it with ak update --status --ack --json.
See ak doctor's auto_update check for schedule, stuck-run, and
opted-in-project diagnostics.
Options
| Option | Default | Purpose |
|---|---|---|
--ack | false | With --status: mark the last background auto-update result as seen. |
--backup | false | Snapshot the whole project, not only the files the refresh changes; backups.enabled: true in ~/.agentkit/config.yaml makes this the default. |
--beta | false | Include beta CLI self-update behavior. |
--channel <channel> | Receipt channel, then kit.channel, then stable | Select the kit channel for this request only; the value is not saved. |
--dry-run | false | Preview without project or global installation writes. |
--force | false | Authorize drift replacement after backup unless --no-backup. |
-g, --global | false | Update global kit installations. |
--kits <names> | Empty | Limit the comma-separated kit selection. |
--kits-dir <path> | Empty | Read kits from a local directory. |
--local | false | Use the local kit source. |
--no-backup | false | Skip pre-update recovery snapshots, including the one --force takes (power users only — data loss risk). |
--no-project <dir> | Empty | Remove a project from background auto-update, even if its directory is gone (repeatable). |
--project <dir> | Empty | Opt a project registered with ak projects add into background auto-update (repeatable). |
--registry-url <url> | Empty | Override the registry URL. |
--remote | true | Use the remote registry. |
--runtime <runtime> | claude-code | Alias of --target; select runtime(s) from the scope-and-source matrix above. The default is not an explicit selection. |
--schedule <daily|weekly|off> | Empty | Set or clear the background auto-update schedule (settings only; updates nothing now). |
--show-diff | false | Include file diffs in the plan. |
--status | false | Show the background auto-update schedule and last result (read-only). |
--target <target> | Empty | Comma-separated runtime(s) from the scope-and-source matrix above; unset means all installed runtimes. Pass only one of --target or --runtime. |
--version <version> | Empty | Pin a kit version. |
Examples
Preview a project update with a successful preview status:
ak update . --dry-run --show-diffApply a project update without prompting:
ak update . --yesRefresh only the Claude Code and Codex installs of a project:
ak update . --target claude-code,codex --yesPreview global updates:
ak update --global --dry-run --kits core --runtime claude-code
ak update --global --dry-run --kits core --local --kits-dir ./kits --target grokTurn on background auto-update and check its status:
ak update --schedule daily --project .
ak update --status --jsonOutput and streams
With --json, stdout uses the shared envelope with "kind": "update". Project data includes project_dir, files_updated, files_skipped, files_new, and dry_run; it can also include snapshot fields, backup_skipped, skipped, diffs, project_config, project_config_created, and scope. When the project has runtime installs,
it also includes kits (one row per kit and runtime pass) and skipped_targets
(requested runtimes with no project install).
Global output also includes locations, kits, and skipped_targets. Each Kit result can report kit, runtime, status, channel, reason, error, why, next, snapshot fields, locations, and warnings. The global envelope can also report backup_skipped. A selected runtime that is not installed globally is reported as skipped rather than created.
An unfiltered remote global run may discover an existing local-only install. It
reports that install with status: "skipped" and reason: "source_inapplicable"
instead of changing sources implicitly. Follow its next guidance and run
ak update --global --local --kits-dir <dir> to refresh from an explicit local
source. An
explicit source-incompatible target is an exit-2 validation error, not a
source_inapplicable result.
An implicit JSON preview prints a success envelope to stdout and then exits 3. Command errors, including flag-parse errors (exit 2), write the shared
error envelope to stderr.
Human and JSON execution errors show the recovery reason without requiring
--verbose. Default disclosed errors redact known secret shapes and URL query
strings while preserving paths. A global Kit result that completes with an
attention item also shows its sanitized reason in human output without
--verbose; this does not turn that result into a failed update.
--verbose can expose raw execution errors and full warning lists. Review
diagnostics before sharing them.
Exit status
| Code | Meaning |
|---|---|
0 | Update applied, explicit dry-run completed, or an interactive prompt was declined. |
1 | Runtime, lifecycle, source, snapshot, write, partial global update, or a project runtime refresh pass failed; for the auto-update settings and --status --ack, also an I/O failure or a busy state file. |
2 | Flags, scope, source, target, or eligible global installation selection is invalid; at project scope, there is no tracked kit and no runtime install, or --target matches no project runtime install; for the auto-update settings, also an invalid --schedule, an unregistered --project, or a settings flag combined with an update flag or a project-dir argument. |
3 | A non-interactive implicit preview requires --yes to apply. |
Effects, safety, and recovery
Project updates classify owned files. Clean files can be replaced; modified or newly occupied files are skipped unless --force is used. Apply also prunes AgentKit-owned files under kits/<id>/ that the incoming source no longer ships, and only for kits present in that incoming set. Clean and already-missing copies are removed; a user-modified copy is preserved and reported unless --force is set. A path that is no longer a regular file is left in place. Empty directories left inside the kit tree are removed; the kit root is not.
By default, apply snapshots only the exact files it writes or prunes — a restorable bundle authorized by its project root (--allow-root), whose result includes the restore command. --force, --backup, or backups.enabled: true in ~/.agentkit/config.yaml instead captures the whole project; --backup does not widen global kit refresh snapshots. --no-backup skips every snapshot, including the one --force takes, and warns on stderr; --force --no-backup adds an escalated warning. Structured results report backup_skipped so a missing snapshot_id is not enough to tell an intentional skip from a no-op. Desktop plan apply that keeps user content takes the same exact-file capture unless user content is overwritten or backups.enabled is set, in which case it captures the whole project; it does not accept --no-backup. Some files outside its restore scope require manual recovery; follow snapshot_data_dir when reported. A missing project config can be created before classification and snapshot, even if a later step fails.
Writes are sequential, so an error can leave a partial update. Global updates continue across kits, report per-kit failures, and can create a support bundle under ~/.agentkit/support. Global force mode may archive authorized legacy Codex skills, but it still preserves user modifications. Project --force never archives legacy ClaudeKit Codex skills: a project runtime pass that finds them reports a skipped row with reason needs_legacy_migration. Run ak migrate --from ck from the project directory, then re-run the update. Archival through --force remains a --global --force consent.
On Windows, ak update applies the signed CLI replacement in place under an exclusive update lock, validates the running binary preimage, then re-executes the original command inside a Windows Job Object so Kit refresh continues on the first invocation. Standalone ak self-update still uses the staged detached helper handoff. Paired Desktop apply stages the matching CLI and Desktop artifacts, then a trusted helper commits the swap after the parent process releases the executables.
Related commands and limitations
Use ak new for a new project and ak uninstall to remove owned files. After a partial failure, ak doctor can filter dedicated suites only for claude-code, codex, and cursor; any other --adapter value is invalid and exits 2. See CLI conventions for shared flags.