AgentKit
DocsKitsCLI ReferenceDesktop App

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. When --channel is omitted, ak kit refresh uses persisted kit.channel if that key is set; otherwise it uses stable. Passing --channel stable or --channel beta persists that value. 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>stable, or persisted kit.channelSelect the remote kit channel; an explicit value is persisted.
-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. 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>.

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.

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.

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 execution errors are written to stderr with schema_version, error, error_code, and exit_code. Flag-parse errors can remain plain-text usage.

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.
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.

Command help reserves 5 for a missing local kit and describes 6 more broadly, but only the no-detected-target path is 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.