UNPKG

akm-cli

Version:

akm (Agent Knowledge Manager) — a portable, local-first capability library for AI agents. Discover, load, share, and improve reusable skills, scripts, workflows, and knowledge across any shell-capable coding agent, including Claude Code, OpenCode, and Cur

760 lines (588 loc) • 29.1 kB
# Migrating from akm 0.5.x to 0.6.0 > **Also see the [archived pre-1.0 plan](https://github.com/itlackey/akm/blob/be3a6a632b0cbe7a63ce71b7d093d8ac266e857c/docs/archive/pre-1.0-migration.md).** The architecture refactor landed mid-0.6 > cycle. It removes the `openviking` source provider, renames the config key > `stashes[]` to `sources[]` (auto-migrated in memory), adds the > `writable` and `defaultWriteTarget` fields, and treats Context Hub as a > regular git repo. If you are on 0.5.x and upgrading to a current 0.6.x > build, read both this file and the archived plan. This guide covers everything you need to know to upgrade from akm 0.5.x to 0.6.0. Most projects will work without changes thanks to automatic on-disk migrations; a small number of config fields and CLI flags require manual updates. If you only want a one-line summary of breaking changes, run: ```sh akm help migrate 0.6.0 ``` That command prints the same content you are reading here, sourced directly from `CHANGELOG.md` and the release notes embedded in this document. ## Table of contents - [Installing 0.6.0](#installing-060) - [What changed in 0.6.0](#what-changed-in-060) - [Automatic migrations (no action required)](#automatic-migrations-no-action-required) - [Manual actions required](#manual-actions-required) - [Wire format change: `kits[]` → `stashes[]`](#wire-format-change-kits--stashes) - [Registry index schema v3](#registry-index-schema-v3) - [Publisher / kit-maker changes](#publisher--kit-maker-changes) - [Sibling repositories](#sibling-repositories) - [New in 0.6.0 (bonus features)](#new-in-060-bonus-features) - [Internal types and file renames (developers only)](#internal-types-and-file-renames-developers-only) - [Removed without replacement](#removed-without-replacement) - [Verifying the upgrade](#verifying-the-upgrade) - [Troubleshooting](#troubleshooting) - [Rolling back](#rolling-back) ## Installing 0.6.0 Pick whichever install method you used for 0.5.x: ```sh # npm npm install -g akm-cli@0.6.0 # bun bun install -g akm-cli@0.6.0 # From source (contributors) git fetch origin && git checkout v0.6.0 && bun install ``` If you installed via `akm upgrade` on 0.5.x, you can use it again on 0.6.0 — the command re-runs the same underlying package install: ```sh akm upgrade ``` The upgrade itself does **not** touch your stash files, your `config.json`, or your registry index. Automatic migrations run the first time a 0.6.0 command reads them. See [Automatic migrations](#automatic-migrations-no-action-required) for the exact list. ## What changed in 0.6.0 0.6.0 unifies the runtime domain model around two concepts: **stashes** (any source of content akm can read) and **registries** (services that help you discover stashes). Several historical layers — "kits" as a runtime concept, the parallel `installed[]` config array, the special-cased `context-hub` provider type — are removed in favour of that simpler model. First run after upgrade triggers a full `index.db` rebuild because `DB_VERSION` was bumped 8 → 9 to add the `workflow_documents` table. The next `akm index` repopulates everything; `workflow.db` (run state) is unaffected. The high-level changes: | Area | 0.5.x | 0.6.0 | | --- | --- | --- | | Wire format used by registries | `kits[]` | `stashes[]` | | Discovery keyword / topic | `akm-kit` | `akm-stash` | | Registry index schema | v2 (with `kits[]`) | v3 (with `stashes[]`) | | Runtime domain noun | "source" / "kit" / "stash" | **stash** (one term) | | Provider types | `filesystem`, `git`, `openviking`, `context-hub` (special-cased) | `filesystem`, `git`, `openviking` (only) | | Stash source kinds (`StashSource["type"]`) | `local`, `npm`, `github`, `git`, `website` | `filesystem`, `git`, `npm`, `github`, `website`, `openviking` | | Lock file | `stash.lock` | `akm.lock` | | `installed[]` in `config.json` | user-facing | machine-managed in `akm.lock` | | `stashDir` top-level field | required for primary stash | deprecated; use `primary: true` on a stash entry | | `disableGlobalStashes` | boolean | replaced by `stashInheritance: "merge" \| "replace"` | | `--for-agent` flag | top-level flag | deprecated; use `--detail=agent` | | `akm enable context-hub` | hardcoded toggle | removed; add as a regular git stash | Each of these is covered in detail below. ## Automatic migrations (no action required) These migrations happen silently on first run of v0.6.0. None of them lose data; all of them are idempotent. ### 1. `stash.lock` → `akm.lock` If `~/.config/akm/stash.lock` (or the equivalent path under `AKM_CONFIG_DIR`) exists and `akm.lock` does not, akm renames it on startup. The first command you run in 0.6.0 will perform the rename and then proceed normally. If both files exist, akm prefers `akm.lock` and leaves the old `stash.lock` in place untouched. You can delete `stash.lock` manually after confirming your config is healthy with `akm info`. ### 2. `installed[]` → `stashes[]` + `akm.lock` Every entry in `config.installed[]` is mapped to a `StashEntry` record in `config.stashes[]`, and its lock data (resolved version, cache directory, install timestamp) is written to `akm.lock`. The `installed[]` field is removed from `config.json` the next time akm writes it (for example, after `akm config set …` or `akm add …`). The mapping uses these rules: | `installed[]` field | New location | | --- | --- | | `id` | `stashes[].name` (also kept as `stashes[].id` for compatibility) | | `source` (`npm` / `github` / `git` / `local`) | `stashes[].source.type` | | `ref` | `stashes[].source.ref` | | `installRef` | `stashes[].source.ref` (resolved form) | | `installedAt` / `version` / `cachePath` | `akm.lock.stashes[<name>]` | Until your `config.json` is rewritten, both representations are read at startup. ### 3. `stashDir` → `primary: true` The top-level `stashDir` field is still read for backwards compatibility. At load time, akm synthesizes a primary stash entry equivalent to: ```json { "name": "primary", "type": "filesystem", "primary": true, "source": { "type": "filesystem", "path": "<stashDir>" } } ``` No on-disk rewrite happens automatically. The field is rewritten only when you next run `akm config set …` against any other field. ### 4. Type alias normalization Stash entries with `type: "context-hub"` or `type: "github"` are loaded as `type: "git"` in memory. `akm config list` will show the normalized form. Update your config files to use `"git"` directly (and the `source.type` in the discriminated union) to remove the migration step on future runs. | Alias on disk | Normalized to | | --- | --- | | `"context-hub"` | `"git"` | | `"github"` (as a stash type, not a source locator) | `"git"` | The locator forms `github:owner/repo` and `git+https://…` passed to `akm add` are unaffected — they continue to mean what they always have. ## Manual actions required The following items are not auto-migrated. They are small in scope but must be applied to keep your scripts and project configs working. ### 1. Replace `disableGlobalStashes` If your project `.akm/config.json` (or user config) contains: ```json { "disableGlobalStashes": true } ``` Replace it with: ```json { "stashInheritance": "replace" } ``` `stashInheritance` accepts two values: | Value | Meaning | | --- | --- | | `"merge"` (default) | Project stashes are appended after user-level stashes | | `"replace"` | Project stashes replace user-level stashes entirely | This is a strict superset of the old behavior — `disableGlobalStashes: true` maps exactly to `stashInheritance: "replace"`. ### 2. Replace `--for-agent` with `--detail=agent` In scripts, aliases, or agent prompts that use the `--for-agent` flag: ```sh # Before akm search "deployment" --for-agent # doclint:ignore (pre-0.7.0 flag, this is the "Before" side of the migration) akm show script:deploy.sh --for-agent # doclint:ignore (pre-0.7.0 flag, this is the "Before" side of the migration) # After akm search "deployment" --detail=agent akm show script:deploy.sh --detail=agent ``` `--for-agent` is still accepted in 0.6.0 but emits a deprecation warning to stderr. It will be removed in 0.7.0. ### 3. Replace `akm enable context-hub` / `akm disable context-hub` context-hub is no longer a special-cased provider. It is just a git repository like any other. The hardcoded enable/disable toggles are removed. ```sh # Before akm enable context-hub # doclint:ignore (pre-0.6.0 command, this is the "Before" side of the migration) akm disable context-hub # doclint:ignore (pre-0.6.0 command, this is the "Before" side of the migration) # After — add it explicitly if you want it akm add github:andrewyng/context-hub --name context-hub # doclint:ignore (historical — pre-0.9.0 command spelling) # To temporarily disable without removing # Edit your config.json and set "enabled": false on the stash entry ``` The generalized commands `akm registry enable/disable <name>` and `akm stash enable/disable <name>` are now available for toggling any configured registry or stash by name. See [CLI Reference](../reference/cli.md) for the full syntax. ### 4. Update `akm list` parsing in scripts The single tri-state `kind` field (`"local" | "managed" | "remote"`) in `akm list --format json` output is replaced by two orthogonal fields: | Field | Values | Meaning | | --- | --- | --- | | `origin` | `"local"`, `"remote"` | Where the content comes from | | `access` | `"indexed"`, `"live"` | How akm queries it | The old combinations map cleanly to the new ones: | Old `kind` | New `origin` | New `access` | | --- | --- | --- | | `"local"` | `"local"` | `"indexed"` | | `"managed"` | `"remote"` | `"indexed"` | | `"remote"` | `"remote"` | `"live"` | ```sh # Before — checking for managed kits akm list --format json | jq '.[] | select(.kind == "managed")' # doclint:ignore (historical — pre-0.9.0 command spelling) # After — checking for remote indexed stashes akm list --format json | jq '.[] | select(.origin == "remote" and .access == "indexed")' # doclint:ignore (historical — pre-0.9.0 command spelling) ``` The `--kind` filter on `akm list` is replaced by `--origin` and `--access`. For backward compatibility during 0.6.x, `--kind <legacy-value>` is still accepted and translated to the new pair. ### 5. Handle new error codes in automated scripts Error JSON now includes a machine-readable `code` field on every failure: ```json { "ok": false, "error": "Stash not found: foo", "code": "STASH_NOT_FOUND", "hint": "Run `akm list` to see configured stashes." } ``` Scripts that previously parsed error messages by string matching should switch to `code` comparisons. The full code list is documented in the [CLI Reference](../reference/cli.md#exit-codes-and-error-envelope). Common codes you can rely on: | Code | Meaning | | --- | --- | | `STASH_NOT_FOUND` | Named stash does not exist in config | | `STASH_DUPLICATE` | A stash with that name is already configured | | `REGISTRY_NOT_FOUND` | Named registry does not exist in config | | `ASSET_NOT_FOUND` | `akm show <ref>` could not resolve the ref | | `INSTALL_AUDIT_BLOCKED` | Install was blocked by the security audit | | `CONFIG_INVALID` | Config file failed validation | | `USAGE` | The CLI was invoked with bad flags or arguments | ## Wire format change: `kits[]` → `stashes[]` The wire format that registries publish, and that the akm CLI consumes when searching a registry, has been renamed from `kits[]` to `stashes[]`. This is a clean break — there is **no** transparent fallback. `akm-cli >= 0.6.0` only parses the v3 schema. **Before** (v2 index, parsed by 0.5.x): ```json { "version": 2, "updatedAt": "2026-04-01T00:00:00Z", "kits": [ { "id": "npm:@scope/my-kit", "name": "my-kit", "description": "Deployment scripts and skills", "ref": "@scope/my-kit", "source": "npm", "tags": ["deploy"], "assetTypes": ["script", "skill"] } ] } ``` **After** (v3 index, parsed by 0.6.x): ```json { "version": 3, "updatedAt": "2026-04-23T00:00:00Z", "stashes": [ { "id": "npm:@scope/my-kit", "name": "my-kit", "description": "Deployment scripts and skills", "tags": ["deploy"], "assetTypes": ["script", "skill"], "stash": { "name": "my-kit", "type": "npm", "source": { "type": "npm", "ref": "@scope/my-kit" } } } ] } ``` The new `stash` property carries a `Partial<StashEntry>` draft. `akm add <registry-hit-id>` takes that draft, fills in defaults (notably `name` if not provided), and writes it directly into your `config.stashes[]`. This removes the parallel `source` / `ref` / `installRef` fields that previously had to be reassembled by the CLI. The old `source` / `ref` / `installRef` fields **may** appear on a v3 entry and are accepted for one version cycle as deprecated read-only fallbacks. They will be removed in v4. Index generators should write only the new `stash` field going forward. ## Registry index schema v3 The schema previously shipped as `registry-index.schema.json` (removed from the repository since; the highlights below still describe the v3 structure it covered). Highlights: - `version` enum is `[1, 2, 3]`. `akm-cli >= 0.6.0` parses only `version: 3`. - The top-level array is `stashes[]` (was `kits[]`). - Each entry carries a `stash: Partial<StashEntry>` draft. - A new `$defs.StashSource` definition describes the discriminated union used by `stash.source`. - The legacy `source` / `ref` / `installRef` fields are present but marked `deprecated: true` for one version cycle. ### Migrating a self-hosted registry If you publish your own registry index, follow these steps: 1. **Bump `version` to `3`.** akm 0.6.0 will refuse to load `version: 1` or `version: 2` indexes and report `REGISTRY_INDEX_INCOMPATIBLE`. 2. **Rename `kits` to `stashes`.** A simple JSON rewrite is sufficient. 3. **Add the `stash` draft to each entry.** For an npm package: ```json "stash": { "name": "my-kit", "type": "npm", "source": { "type": "npm", "ref": "@scope/my-kit" } } ``` For a GitHub repo: ```json "stash": { "name": "my-kit", "type": "git", "source": { "type": "git", "url": "https://github.com/owner/repo", "ref": "main" } } ``` 4. **Optionally remove the legacy `source` / `ref` / `installRef` fields.** They are deprecated in v3 and will be removed in v4. Keeping them does not hurt during the 0.6.x window if you have older clients to support. 5. **Republish.** akm 0.6.x clients will pick up the new index on their next refresh (1-hour TTL for `static-index` providers). If you generate your index with the akm repository's index builder (`scripts/build-registry-index.ts`, formerly the `akm registry build-index` subcommand), upgrading to 0.6.0 is sufficient — the generator emits v3 by default. For a hand-rolled v1/v2 index, the migration is a small mechanical rewrite: rename the top-level `kits` array to `stashes`, set `version` to `3`, and republish. A scripted helper (e.g. `jq` one-liner) is enough: ```sh jq '{version: 3, updatedAt, stashes: .kits}' old-index.json > new-index.json ``` ## Publisher / kit-maker changes If you publish a kit (npm package or GitHub repo) and want it to be discoverable through registry search, the keyword / topic has changed. ### npm packages Update `keywords` in your `package.json`: ```diff { "name": "@you/my-kit", "version": "1.0.0", - "keywords": ["akm-kit"] + "keywords": ["akm-stash"] } ``` For maximum compatibility during the transition, you can include both: ```json { "keywords": ["akm-stash", "akm-kit"] } ``` `akm-cli >= 0.6.0` discovers packages tagged with `akm-stash`. The legacy `akm-kit` keyword is no longer queried by the CLI and existing registry build pipelines should switch to the new keyword. Older 0.5.x clients that have not upgraded will only see your package if you also keep `akm-kit` in your keywords list — drop it once your audience has moved. ### GitHub repositories Update the repo topic: ```sh gh repo edit --add-topic akm-stash gh repo edit --remove-topic akm-kit # optional, after the transition ``` Or update topics from the repository **About** sidebar in the GitHub web UI. ### `package.json` `akm.include` and friends The `akm.include` array and other publish-time `package.json` fields are unchanged in 0.6.0. Existing kits do not need to be re-published unless you also want to drop the `akm-kit` keyword. ## Sibling repositories akm ships as three coordinated repositories. All three shipped the 0.6.0 terminology cut together: - **`itlackey/akm`** (this repo) — the CLI. Ship as `akm-cli@0.6.0`. - **`itlackey/akm-stash`** — the reference stash of official agent assets. Its `package.json` `keywords` and repo topic both moved from `akm-kit` to `akm-stash`. If you depend on the published npm package, pin the 0.6.0-compatible release. - **`itlackey/akm-registry`** — the build pipeline that generates the public registry index. It now emits schema v3 (`stashes[]`). If you self-host a registry built from this pipeline, pull the 0.6.0 tag and regenerate your index — older clients (`akm-cli` 0.5.x) will not parse v3, so you may want to keep two index URLs during your transition window. If you consume only the official hosted registry, no action is needed — the registry already serves a v3 index from every 0.6.0+ CLI build. ## New in 0.6.0 (bonus features) These are additive — none of them require action to upgrade — but they are worth a scan because they unlock new workflows once you're on 0.6.0. - **Memory frontmatter on `akm remember` (#169).** `--tag`, `--expires`, `--source`, plus opt-in `--auto` (heuristics) and `--enrich` (LLM) attach structured metadata to memories so the indexer can rank them. Bare `akm remember "body"` still writes a flat memory, so existing agent scripts keep working. See [`akm remember`](../reference/cli.md#remember). - **Workflow parser accepts intro prose (#158).** You can now put a short advisory paragraph between `# Workflow:` and the first `## Step:` without tripping a validation error. - **Workflow resume reclassifies blocked steps (#156).** After `akm workflow resume <id>`, the previously-blocked step becomes actionable again so you can mark it `completed`, `failed`, or `skipped`. - **Workflow create works in clean stashes (#157).** `akm workflow create <name>` and `--from <file>` no longer false-positive on a path escape when any ancestor of your stash is a symlink (macOS `/tmp` → `/private/tmp`, symlinked `HOME`, etc.). - **Registry search filters incomplete hits (#159).** Providers that return partial records no longer surface as empty `{}` objects in JSON output; dropped counts appear in `warnings`. - **Isolated sandbox recipe (#160).** Introduced a one-terminal recipe for a throwaway `HOME + XDG_* + AKM_STASH_DIR` environment — handy for agent testing, CI, and issue reproduction. See [`docs/guides/getting-started.md`](../guides/getting-started.md) for the current setup guide. - **CI coverage for release branches (#170).** If you fork the repo or run downstream CI off it, the shipped `.github/workflows/ci.yml` now fires on PRs targeting `release/*` in addition to `main`. ## Internal types and file renames (developers only) These changes only affect contributors to akm itself or to projects that import from akm's source. akm has no public API (no barrel exports, no `exports` map in `package.json`), so importing from akm internals was never officially supported — but we list the renames here for anyone who was doing it anyway. ### Type renames | Before | After | | --- | --- | | `RegistryKitEntry` | `RegistryStashEntry` | | `InstalledKitEntry` | `StashEntry` + `StashLockEntry` (split) | | `InstalledKitListEntry` | `StashListEntry` | | `KitInstallResult` | `StashInstallResult` | | `KitInstallStatus` | `StashInstallStatus` | | `KitSource` (`"npm" \| "github" \| "git" \| "local"`) | `StashSource["type"]` (`"filesystem" \| "git" \| "npm" \| "github" \| "website" \| "openviking"`) | `StashSource` is a discriminated union per type — see `src/stash-source.ts`. ### Domain model unification (#123) The old triplet of "source" / "kit" / "stash" is collapsed to a single runtime concept: **stash**. `StashEntry` is the canonical shape used by config, registry drafts, and the index. `kit` survives only as a publishing concept (the bundle you ship via npm or GitHub). The data shape of `StashEntry`: ```ts type StashEntry = { name: string; // required, unique within config type: StashSource["type"]; // discriminator primary?: boolean; // exactly one entry may set this enabled?: boolean; // default true source: StashSource; // discriminated union per type options?: Record<string, unknown>; }; ``` `akm.lock` records the **resolved** state separately: ```ts type StashLockEntry = { name: string; // matches StashEntry.name resolvedVersion?: string; // for npm / github / git resolvedRef?: string; // commit SHA / tarball SHA-256 cachePath?: string; // absolute path under ~/.cache/akm/ installedAt: string; // ISO timestamp }; ``` ### File renames | Before | After | | --- | --- | | `src/installed-kits.ts` | `src/installed-stashes.ts` | | `src/registry-kit-entry.ts` | `src/registry-stash-entry.ts` | | `docs/kit-makers.md` | `docs/stash-makers.md` (with a redirect stub at the old path) | | `tests/installed-kits.test.ts` | `tests/installed-stashes.test.ts` | The redirect stub at `docs/kit-makers.md` is a one-line link to `stash-makers.md` so existing inbound links and `akm hints` snippets continue to resolve. ### context-hub removal (#124) `src/providers/context-hub.ts` is removed. The old hardcoded provider type is gone; `akm enable context-hub` and `akm disable context-hub` now error with `STASH_NOT_FOUND` and a hint pointing at `akm add github:andrewyng/context-hub`. context-hub remains usable as an ordinary git stash — it is just a public repo. If you previously imported `ContextHubProvider` directly, switch to the generic `GitStashProvider` from `src/providers/git.ts`. ### Registry-install fold (#125) The `registry-install` path is folded into the unified install pipeline in `src/install/`. `registry-install.ts` no longer exists as a top-level module. The behaviour is unchanged — registry hits hand off to the same install pipeline used by `akm add`, and audit/lock/index steps run in the same order. ### `cli.ts` decomposition (#126) The monolithic `src/cli.ts` is split into per-command modules under `src/cli/`. The exported `runCli()` function and the `akm` binary behaviour are unchanged; this is purely an internal refactor. Tests that imported helpers from `src/cli.ts` should now import from the corresponding `src/cli/<command>.ts`. ### Provider / dep refactor (#127) `RegistryProvider` and `StashProvider` interfaces are aligned around a shared `BaseProvider` shape with explicit lifecycle (`init`, `search`, `show`, `dispose`). The dependency-injection wiring moves into `src/provider-registry.ts`. Provider authors should re-read [Registry Providers](../reference/registry.md#registry-providers) — the public contract is unchanged but the internal hook points have moved. ### Config ergonomics (#128) Embedding and LLM connection config now share a `BaseConnectionConfig` shape: ```ts type BaseConnectionConfig = { endpoint?: string; apiKey?: string; model?: string; headers?: Record<string, string>; timeoutMs?: number; }; ``` Both `embedding` and `llm` config keys accept this shape. Existing configs continue to work — the previous fields are a strict subset. A new `output.detail: "agent"` preset replaces the `--for-agent` flag (see [Manual actions required §2](#2-replace---for-agent-with---detailagent)). The `ASSET_TYPES` mutable array export is removed from public API. Use `getAssetTypes()` from `src/asset-spec.ts` instead. ## Removed without replacement | Removed | Reason | | --- | --- | | `akm enable context-hub` | context-hub is just a git stash; use `akm add github:andrewyng/context-hub` | | `akm disable context-hub` | same | | `ASSET_TYPES` exported array | use `getAssetTypes()` (already existed) | | `InstalledKitEntry` type | replaced by `StashEntry` + `StashLockEntry` (split) | | `KitSource = "npm" \| "github" \| "git" \| "local"` type | replaced by `StashSource["type"]` | | `disableGlobalStashes` config field | replaced by `stashInheritance: "merge" \| "replace"` | | `installed[]` config array | now machine-managed in `akm.lock` | | `kits[]` registry wire format | replaced by `stashes[]` (schema v3) | | `akm-kit` keyword / topic for discovery | replaced by `akm-stash` | | `context-hub` as a stash type | normalized to `git` at load time | ## Verifying the upgrade After upgrading, run: ```sh akm info ``` Look for these signals that the migration completed cleanly: - `version` reports `0.6.0` or higher. - `stashProviders` lists only `filesystem`, `git`, and `openviking`. - The output does **not** include any `context-hub` entries. - `assetTypes` matches the types you expect. Then: ```sh akm config list akm list # doclint:ignore (historical — pre-0.9.0 command spelling) ``` `akm config list` should show your `stashes[]` populated (including entries that were migrated from the old `installed[]` array). `akm list` should show `origin` and `access` columns instead of the old `kind` column. If `akm.lock` was created from a previous `stash.lock`, you should see it at `~/.config/akm/akm.lock` (or under `AKM_CONFIG_DIR`). A full reindex is **not** required by the upgrade. Run one only if you also changed your embedding model or want to pick up new asset types: ```sh akm index --full ``` ### Post-upgrade checklist Five-step confirmation that nothing regressed: ```sh akm info --format text # 1. version 0.6.x, no context-hub provider akm config list --format json | head -40 # 2. stashes[] populated; no `installed[]` akm list # 3. your sources resolve; `origin`/`access` columns # doclint:ignore (historical — pre-0.9.0 command spelling) akm workflow list --format json | head -20 # 4. any active workflow runs still show akm search "<a query you know works>" --format json # 5. indexed content still matches ``` If any step returns an error or missing data, see Troubleshooting below. ## Troubleshooting **"Unknown stash type 'context-hub'" after upgrade.** Legacy aliases normalize at config load, but a truly corrupt entry can still slip through. Run `akm config show` to see how your entry is parsed. If it still rejects, edit `config.json` to set `"type": "git"` and restore the URL from your backup. **`registry search` returns `warnings: ["schema version 2 unsupported"]`.** Your registry is still serving v2. Pull the latest `akm-registry` and regenerate, or swap your registry URL to the official hosted one. See [Migrating a self-hosted registry](#migrating-a-self-hosted-registry). **`akm list` shows empty `stashes[]` but your 0.5.x config had entries.** The migration copies `installed[]` into `stashes[]` only on the first 0.6.0 command that **writes** config (e.g. `akm add`, `akm config set`). If you've only run read-only commands, the new array may not yet be populated. Run `akm add <any-stash>` or force a rewrite with `akm config set stashes "$(akm config get stashes)"`. **`akm workflow create <name>` in a fresh stash still errors `path escapes the stash`.** That was fixed in 0.6.0 (#157) — confirm you're on the 0.6.0 CLI with `akm info | grep version`. If you are and still see it, the symlink resolution is likely hitting an edge case; file an issue with the output of `realpath "$AKM_STASH_DIR"`. **`akm.lock` was not created.** akm only creates the lockfile when it first writes to the stash directory. Run any write command (`akm add`, `akm remember`, `akm import`, `akm workflow create`) to generate it. **`--for-agent` still works, but I want to migrate my scripts.** Replace it with `--detail=agent` — same behaviour, preferred spelling. The old flag is retained as a deprecated alias through at least the 0.6.x series. ## Rolling back If you need to roll back to 0.5.x for any reason, the auto-migrations are non-destructive but **your config.json may have been rewritten** to remove `installed[]` if you ran any `akm config set` or `akm add` command on 0.6.0. Restore from a backup if you need the old shape. `akm.lock` is not read by 0.5.x — it will be ignored. Your stash content itself is unchanged across versions; only the metadata layer evolves. To pin to the last 0.5.x release: ```sh npm install -g akm-cli@0.5 # or bun install -g akm-cli@0.5 ``` If you find a regression in 0.6.0, please file an issue at <https://github.com/itlackey/akm/issues> with the output of `akm info` and a redacted copy of your `config.json`.