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
Markdown
# 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`.