AgentKit
DocsKitsCLI ReferenceDesktop App
BetaYou are reading docs for the beta channel (3.0.0-beta.15). Features may change before the next stable release.Switch to stable →

ak kit

ak kit refresh

Reconcile an installed kit route, remove stale clean owned output, and preserve user changes.

Use ak kit refresh to re-emit an installed kit after its exported content changes. Refresh removes retired generated files only when AgentKit can prove they are clean and owned; it preserves unknown and user-modified content.

Syntax

ak kit refresh <kit-name>

<kit-name> is required. The command refreshes an existing route; use ak kit install when no route exists.

Before you run

Remote registry resolution is the default. The channel resolves in this order: an explicit --channel, then the channel recorded in the destination's install receipt, then kit.channel, then stable. An explicit --channel applies to this request only and is not saved. Conflicting receipts print a warning, fall through to kit.channel, and are never rewritten. Paid kits require a valid CLI session and entitlement. Resolution can refresh saved authentication, contact the registry, download an artifact, and update the verified cache before lifecycle writes begin.

ak whoami
ak licenses

Use --local --kits-dir <dir> only for an explicit development or CI source. Refresh has no dry-run flag. Run ak audit first when you need to inspect drift.

Grok Build and Pi are signed registry targets for normal Kit refresh. Use --local --kits-dir <dir> only when intentionally selecting a development or CI source. AgentKit re-emits target runtime files and lifecycle metadata; the selected runtime still owns authentication, model, trust, permission, and sandbox behavior.

Arguments

<kit-name> is the single installed Kit ID to reconcile. It is required; the command does not prompt for a Kit.

The command has no alias.

Options

OptionDefaultEffect
--channel <channel>Receipt channel, then kit.channel, then stableSelect the remote kit channel for this request only; the value is not saved.
-g, --globalfalseRefresh user-scope routes instead of the current project.
--kits-dir <dir>EmptySelect an explicit local kit source.
--localfalseUse the explicit local source instead of the registry.
--no-backupfalseSkip the pre-refresh recovery snapshot.
--registry-url <url>Environment or release defaultOverride the registry base URL.
--remotetrueUse the authenticated remote registry; explicit use is unnecessary.
--switch-to-pluginfalseSelect Claude Code plugin delivery at project or user scope.
--target <ids>Detected installed targetsSelect one or more comma-separated emitter targets, including grok and pi.
--version <version>Channel latestSelect a remote kit version.

Shared flags are documented in CLI conventions.

Target, scope, and mode resolution

When --target is omitted, refresh inspects lifecycle markers for the chosen scope and refreshes every installed runtime it detects. Project scope detects project-native Claude Code, project Cursor, and recognized project output. User scope scans registered user lifecycle targets. If no target is detected, the command exits 6 and asks you to pass --target or install the kit first. For Grok or Pi routes, pass --target grok or --target pi when detection is ambiguous; remote registry resolution remains the default unless you explicitly select --local --kits-dir <dir>.

A project refresh is refused with exit 6 when the route of any selected or detected runtime resolves to the user-level install, for example when you run it from your home directory. The check runs once for every runtime, before any per-runtime pass, lock, snapshot, or write. Use ak kit refresh <kit> --global for the user-level install.

Claude plugin delivery must always be explicit:

# Project Claude plugin.
ak kit refresh engineer --switch-to-plugin --yes

# User Claude plugin.
ak kit refresh engineer --global --switch-to-plugin --yes

An installed Claude plugin is not silently treated as native output, even when another target is also present. Project and user scopes remain independent.

Refresh several runtimes

Remote Kit packages are runtime-specific. When a remote refresh covers more than one runtime, whether detected or listed with --target, AgentKit refreshes them one at a time. Each runtime gets its own verified download, preflight, confirmation preview, and snapshot-backed write. If one runtime fails, only that runtime's changes roll back and the remaining runtimes still refresh.

After the last runtime, the command prints a refresh summary with one line per runtime. Every runtime that did not refresh gets a retry: command that refreshes it alone:

ak kit refresh <kit-name> [--global] --target <target> --yes

The retry command repeats the scope and any --channel, --version, --registry-url, --no-backup, --switch-to-plugin, and --yes options from the original run. Run it after fixing the reported error.

Declining a runtime's preview stops the loop: that runtime is reported as declined and later runtimes as not_attempted. An interrupt also marks the remaining runtimes not_attempted. Runtimes that already refreshed stay refreshed. A refresh from an explicit --local source does not use these per-runtime passes.

Examples

# Auto-detect an installed project route.
ak kit refresh engineer --yes

# Refresh one Codex route explicitly.
ak kit refresh engineer --target codex --yes

# Refresh one Pi route explicitly.
ak kit refresh engineer --target pi --yes

# Refresh from an explicit local development source.
ak kit refresh engineer --local --kits-dir ./kits --target codex --yes

# Refresh the Grok project route.
ak kit refresh engineer --target grok --yes

# Intentional unattended refresh.
ak kit refresh engineer --target codex --yes --no-interactive --json

Confirmation behavior

Refresh uses the install destination preview and asks Continue? [y/N]: on an interactive TTY. Only y or yes proceeds.

--json, --no-interactive, and non-TTY stdin skip the prompt and can refresh without --yes. Include --yes in automation to make the write explicit.

A TTY decline currently exits 1, not 3.

Output and streams

Human progress, destination preview, and confirmation use stderr. The final summary uses stdout. It reports the kit, route, file count, install mode, scope, Hook result, warnings, preserved changes, and recovery information.

With --json, stdout uses the versioned kind=kit.init envelope because refresh reuses the installation result model. Data includes kit, target, optional targets, mode, installMode, scope, outDir, filesWritten, success, and optional Skill, Hook, warning, transition, and snapshot fields. Unless --quiet is set, stderr also emits raw preview and complete status records with action=install.

A refresh that runs one pass per runtime uses a kind=kit.refresh envelope instead. Its data holds kit and a targets[] array with one entry per runtime:

FieldMeaning
targetThe runtime ID.
statusrefreshed, failed, declined, or not_attempted.
errorThe failure reason when status is failed.
rerunThe single-runtime retry command for every runtime that did not refresh.
resultThat runtime's refresh result when status is refreshed, with its warnings and notices beside it.

Each refreshed runtime also emits its own preview and complete status records on stderr.

Hook projection data can also include optional hooksDropped, droppedHookSummaries, hookMatchersNarrowed, and narrowedHookSummaries. Human output separates Hook groups not projected from Hook matchers narrowed (some tool matches unsupported on this target) and prints the corresponding warnings. A disclosed drop or narrow remains a successful refresh.

JSON-mode failures, including flag-parse errors (exit 2), end stderr with the shared error envelope: schema_version, error, error_code, and exit_code.

Human and JSON execution errors show the recovery reason by default, with known secret shapes and URL query strings redacted and paths preserved. --verbose can expose the raw underlying error; review it before sharing.

Exit status

ExitMeaning
0The selected route was reconciled successfully.
1Validation, source, authentication, entitlement, mode, ownership, emission, snapshot, write, or TTY-decline failure. Current runtime also uses 1 for most local-kit-not-found and unsafe-target errors. In a per-runtime refresh, 1 means at least one runtime failed or did not run, even if others refreshed.
2Cobra rejected flags, arguments, or a flag combination.
3A shared cancellation or interrupt path returned cancellation.
4Another kit lifecycle mutation holds the lock.
6No installed target could be detected for the selected scope, or the project route resolves to the user-level install.

Command help reserves 5 for a missing local kit and describes 6 more broadly, but only the no-detected-target path and the user-level route refusal are explicitly classified as 6; do not assume every source or ownership error uses the help-reserved code.

Effects and stale-file safety

Refresh runs the force re-emission path internally. With --yes, it verifies the lifecycle update requirements before that snapshot-backed write path. It snapshots affected owned surfaces unless --no-backup, writes current output, updates lifecycle manifests, and removes stale paths whose recorded hashes still match disk.

  • Clean owned stale paths can be removed.
  • Current clean owned paths can be replaced.
  • Modified owned paths are preserved and reported.
  • Unknown files are preserved and are not adopted into ownership.
  • Unsafe linked paths and empty intended-output sets fail closed or are skipped with warnings instead of triggering broad deletion.

The previous Skill selection is retained when the refreshed route has selection metadata. Refresh is not permission to delete custom runtime content.

Recovery and limitations

Keep every reported snapshot until the runtime has rediscovered the refreshed Kit and an installed Skill works.

ak backups show <id>
ak backups verify <id>

Use the reported restore command when the snapshot is in restore scope; otherwise use the reported manual recovery directory. Recovery is bounded and multi-file restore is not guaranteed to be transactional.

Codex does not project every Claude command, Hook matcher, or status-line feature. Engineer refresh can report one full task-state drop plus two shared narrows; Marketing can report three narrows and no full drop. Supported atoms remain active. On Windows, refresh can also emit owned .cmd shims for eligible in-home Codex .cjs Hook paths containing spaces; unsupported external or unsafe paths remain warnings.

For global Codex Hooks, refresh follows only a final hooks leaf alias to canonical ~/.codex/hooks — a POSIX symlink or a Windows directory junction — and keeps commands, writes, rollback, and ownership on that canonical identity. Linked parents and other targets are refused.

agy is a global projection target, not a production refresh lifecycle peer. Re-run its explicit global init/install route instead of treating it as an installed route that refresh can discover.

hooksDeferred is a subset of hooksDropped: the harness bridge defers that subscription, which does not mean the runtime cannot express it. Read the summary to distinguish deferred from unsupported groups.