akm v0.10 migration notes (0.10.261019, the first stable 0.10 release)
0.10 is a clean-up and tuning release. It covers the daily alphas
0.10.26101001 through 0.10.26101202 and the monthly releases that follow
(0.10.YYMMNN). It
removes surface that nothing used, merges CLI spellings, sets the improve
defaults from measurements, replaces engines with connections and
harnesses, and runs OpenCode 2 inside akm. It adds no state.db migration
and keeps index.db at layout 26.
To upgrade from 0.9.15 or later:
akm upgrade
akm migrate status
akm health
akm upgrade installs the new release, runs akm migrate apply, then rebuilds
the index and waits for it; that first rebuild can take a while (see "Install,
platforms and the first run" below). Before you upgrade, search your scripts,
tasks and agent instructions for the removed spellings below: they fail with
exit 2 and no hint. The full ordered procedure, every replacement and the
verification steps are in the
0.9 to 0.10 migration guide.
Version floor
0.10 reads what 0.9.15 and later wrote. It converts nothing older. A config in
the old stashDir / sources[] / installed[] layout fails to load and names
akm migrate apply under akm 0.9.x. If you are on 0.9.14 or earlier, install
0.9.31, run akm migrate apply, then upgrade.
If you ran a 0.10 beta
The betas 0.10.261014 to 0.10.261017 dropped every opencode-sdk engine when
akm migrate apply converted config.json, so agent work moved from your own
OpenCode (and its model) to akm's own runtime over your default connection; the
note it printed did not say so. This release keeps those engines as opencode
harnesses. A
config a beta already migrated is not converted again: akm keeps the file as it
was before the rewrite in <cache dir>/config-backups/ (the five newest), and
step 5 of the migration guide
shows how to read the harnesses out of that copy and set them, or write them by
hand when no copy is left.
Version numbers
A 0.10 release is numbered 0.10.YYMMNN: the UTC year and month, then the
release within that month. Every release takes the next number, whatever its
stage. A prerelease carries its stage only (-alpha, -beta, -rc).
Prereleases publish to the npm next tag and stable releases to latest.
akm upgrade --next follows next. Versions sort by month and then number, so
the number says nothing about how big a change is. Read the CHANGELOG, which
still marks breaking changes. The 0.9 line keeps 0.9.N.
The daily alphas used an 8-digit patch (0.10.YYMMDDNN), which semver sorts
above every 0.10.YYMMNN. If you are on one, install the first monthly release
explicitly once (npm install -g akm-cli@0.10.261001-beta); akm upgrade will
not offer it.
Install, platforms and the first run
- An npm install is about 39 packages and none of them declares an install
script, so it works where npm runs none (npm 12 blocks dependency scripts by
default).
better-sqlite313 ships prebuilt bindings for Linux (glibc and musl) and macOS on x64 and arm64 and for Windows on x64 and arm64, so a Node upgrade no longer needsnpm rebuild; 32-bit ARM Linux has no SQLite binding on Node. akm'spreinstallcheck is gone andonnxruntime-nodeis no longer a dependency (its install script downloaded about 317 MB of CUDA providers on every Linux x64 install). The Node floor is still>=22: akm checks it when it starts and npm warns fromengines.node. Standalone binaries embed no native code and are up to 36 MB smaller. akm setupacquires what local embeddings need: ONNX Runtime 1.24.3 (about 86 MB, checked against the registry's sha512 integrity) and the model (about 127 MB), downloaded once into akm's cache. Local embeddings are offered on Linux x64 (glibc) and Apple-silicon macOS. Every other platform (Windows, Intel macOS, Linux on musl or arm64) takes the keyword-or-endpoint default, with one sentence saying why, so an install there that used the built-in embedder in 0.9 searches by keyword untilembeddingnames an endpoint. Until you runakm setup --embedding offor name an endpoint,akm healthwarns there and exits 4, so anakm health && ...chain stops. An install upgraded from 0.9 on a verified platform downloads the runtime at its nextakm index; the vectors are unchanged, so nothing is embedded again for that.- Search indexes the identifiers of fenced code (#1260). Names, CLI flags,
config keys, paths and dotted references such as
process.env.CIin a fenced block now reach thecontentsearch text; quoted strings, assignment values, URLs and long token-like strings still do not. Search results, fragments andakm showare unchanged. It lifts code lookups and keyword library search in akm-eval and costs about 2 NDCG points on the SkillRet skill-selection benchmark, where long, code-heavy skills now outrank short, code-free ones; tuning is tracked in #1284. On the first run after upgrading,akm index(and the indexakm upgraderuns, whichakm upgradewaits for) re-reads every bundle directory and re-embeds only the entries whose embedded text changed. Text pastembedding.maxInputTokens(default 512, about 2,048 characters) is not embedded, so a longer document whose fenced code sits past it keeps its vector. That can still take a while on a large stash with a remote embedder; the embedding phase opens withEmbedding N changed entries (M unchanged), andakm upgradeshows that line and the rest of the index's progress. Pass--skip-post-upgradetoakm upgradeto leave it to your nextakm index. No--fullis needed, andindex.dbstays at layout 26.
Breaking changes
Each of these is an unknown flag or command (exit 2), with no alias:
akm help agentsis gone. Useakm hints, orakm hints --detail brieffor the short guide.--shapeis gone.--detail agentreplaces--shape agent, and--detail briefreplaces--shape summary.--detailtakesbrief,normal,fulloragent.--targetis gone fromimport,env create,env remove,secret set,proposal accept,proposal diffandproposal revert. Use--bundle.akm task validateis folded intoakm lint --type tasks.akm task listis gone; useakm search --type task.akm config path --allis gone.akm inforeports the directories.akm improve --planis gone; use--dry-run.akm improve --auto-acceptis gone; useakm improve && akm proposal drain --promote --yes.--runand--sincebelong toakm improve report.akm improve reportandakm improve judgeare real subcommands.akm workflow create --resetis gone; use--force.akm search --assetsis gone. It printed nothing.
Other breaking changes:
enginesanddefaultsinconfig.jsonare replaced byconnections(the OpenAI-compatible endpoints akm sends model requests to) andharnesses(the agent programs you already have). The entry nameddefault, or the only one, is the default, anddefaults.improveStrategyisimprove.strategy. A config in the old form still loads, read as the new form in memory with one warning that namesakm migrate apply.akm migrate applyconverts it under a backup: every agent engine becomes a harness with its model (anopencode-sdkengine with nollmEngineran your own OpenCode, so it becomes anopencodeharness; one over anllmEngineis akm's own runtime over that connection; with nodefaults.llmEngineand no connection, akm's model work now runs on the default harness where 0.9 ran none, andmodelWork: falseon it turns that off), the default engine is renameddefault, keys (apiKeyFile, a literal or${secrets/...}apiKey) move tocredentials.json,models.jsonis folded into the connections'modelsand moved to the config backups,engine:in assets, workflows and task sources becomesconnection:orharness:, and an entry akm cannot use stays in the file with a note.provider,supportsJsonSchema,workflow.judgeEngine, a strategy'sengine,model,llmandtimeoutMs, and anextraParamskey that shadows a first-class setting are dropped with a note.- A key is an
apiKey: "$VAR"reference or an entry incredentials.json.apiKeyFile, a${secrets/...}apiKeyand theAKM_ENGINE_<NAME>_API_KEYandAKM_LLM_API_KEYlookups are gone. Untilakm migrate applyhas filed it, a key held inapiKeyFile, a literal or a${secrets/...}reference is not sent (akm warns);akm upgraderunsapplyfor you. models.jsonandakm models listandcopy-defaultsare gone.akm modelslists a connection's aliases, then the models its endpoint lists, andakm models set <alias> <model>changes one.akm env create|run|path|export|removeandakm secret set|runtake a full ref (env/prod,team//secrets/token). A bare name such asprodis a usage error (exit 2) that names the full form:akm env create prodis nowakm env create env/prod.--connection,--harnessand--modelreplace--engine.--engineand--require-engines(which now does nothing:akm improvestops at planning, exit 78, when no process has a connection or harness to run on, and no longer checks before the run that every enabled process has a usable target; runakm healthfor that) still run, hidden from--help, with one warning each; how an old engine name resolves is in the configuration reference.akm setuptakes one flag per question (--endpoint,--api-key-env,--name,--harness,--embedding, ...);--probeand--configare gone.akm health(theconnections-and-harnessescheck) andakm info(itsconnectionsAndHarnessesfield) print one table in place of the engine checks (default-engine,default-llm-engine,configured-engines,active-improve-strategy,thinking-control,engine-last-used). An unreachable connection is a warning.- akm no longer falls back to an
opencodebinary onPATH. With no connection and no harness, model features and agent work are off, and each command that needs one points atakm setup. - A workflow run whose plan holds a
routestep or ascripttarget, or a command target frozen before plan version 8, cannot be resumed:akm workflow runabandons it and names the command that starts it afresh. Let runs finish before you upgrade. akm indexno longer refreshes git or website bundles; 0.9 fetched them again after twelve hours. Bundles are fetched when added and onakm bundle update, so scheduleakm bundle updateif you relied on the index to pull them.- An agent's or command's
tools:(or a Claude command'sallowed-tools:) is no longer read, and a task'stools:is ignored with a warning, so an agent runs with the tools its harness gives it;execution.allowedToolsis an unknown key. Restrict an agent's tools in the harness's own agent definition. secret://namein config and${secret:NAME}in env files are retired for${secrets/name}. Both still load with one warning;akm migrate applyrewrites the config, not env files, andakm config setandakm bundle add --credentialno longer acceptsecret://.- A retire proposal 0.9 wrote records no judged scope, so 0.10 refuses to accept it. Accept or reject pending retire proposals under 0.9 before you upgrade; after it, reject them.
- JSON fields scripts read:
akm showdropsactiveRunandtoolPolicy,akm workflow listdropsscopeKey,akm task doctordropshistoryDir,akm proposal extract --dry-runlists preview refs insessions[].previewRefsinstead ofdry-run:<ref>entries inproposals, andrankingUpdate.appliedinakm feedbackistrueexactly when the event counts toward ranking. - Workflow output redacts only the values substituted from
secrets/refs; the rest of an env asset reaches the journal as written, so a credential typed straight into an env file is no longer redacted. Keep credentials insecrets/. - The built-in improve strategies
quick,reflect-distill,thorough,catchupandproactive-maintenanceare removed. Onlydefaultandconsolidateare built in. A config block with one of those names still loads, as a user-defined strategy that inheritsdefault. A name with no block makesakm improvefail and namedefault. The task templatesakm-improve-nightly,akm-improve-frequentandakm-improve-catchupare removed; a copy in your bundle keeps its old--strategyand must be edited. - Improve config keys that measured no effect or that nothing read are removed:
consolidate.antiCollapse,p90ChunkSecondsDefault,minPoolSize,distill.fidelityCheck,distill.limit,reflect.lowValueFilter,memoryInference.cls,proactiveMaintenance.limit,triage.policy,improve.salience.outcomeWeightEnabledandsalienceThreshold. A config that sets one still loads;akm migrate applydrops it. - The GitHub-shaped YAML workflow format is removed, with workflow-step
uses: tasks/...,scripts/...andcommands/.... Workflows are Markdown only. Top-leveloutputs:,routesteps andunit.isolation: worktreeare removed and are lint errors. Workflows ship as Experimental in 0.10.0; whether they stay is decided in 0.10.x (#1096). BundleAdapter.placeNew()is removed. Nothing called it.package.jsonhas anexportsmap: onlyakm-cli/api,akm-cli/package.jsonandakm-cli/dist/*resolve.- The runtime conversions for config older than 0.9.15 are removed, as above.
- A harness and an
execunit's command run with your environment as it is; 0.9 gave them an allowlist.pass_env:still loads and selects nothing. Codex agent work no longer gets--sandbox workspace-writeand Aider no longer gets--no-auto-commits: each runs with what its own configuration says.
New
- Connections and harnesses.
akm setup --endpoint URL --yessets up a connection;akm modelsshows and changes which model answers each alias (fast,balanced,reasoning);--connection,--harnessand--modelsay where one command runs. Model work runs on any harness, with its tools restricted on Claude Code, Codex and OpenCode 2 and unrestricted, with a notice, elsewhere. Harnesses run as thin shells: akm hands a program the prompt and takes its standard output as the reply. - OpenCode 2, run by akm. Agent work on a connection with no harness runs on
akm's own runtime, a pinned OpenCode 2 binary (2.2.0) that akm fetches from the
npm registry on first use and runs as a process, with no entry in config. The
fetch is the one platform package for your machine (about 114 MB, into its
cache), checked against the registry's sha512 integrity before anything is
extracted. One fetch runs per cache directory at a time: processes that start
together wait for it and download nothing more (#1266). The setup wizard
offers to fetch it right away;
--yesand--fromleave it to the first run. A run whose model makes the same tool call and gets the same result three turns in a row is told so in a message to the model, and failed with a message if it makes the call again, not left to its deadline. That one request raises a connection'stemperaturebelow 0.7 to 0.7: at temperature 0 the message alone changed nothing in the runs measured. A run that keeps making different calls is bounded by its timeout: the connection'stimeoutMs, one the run is given, or a scheduled task'stimeout:(six hours when unset); with none, as forakm agentby default, it runs until it finishes. With no network for that step, enable theopencodeharness with an installed OpenCode 2 instead. A harness withplatform: "opencode"is your OpenCode, whichever major is installed, run through its CLI with your config, providers, plugins, default model and logins; your OpenCode owns them and akm reads, copies and embeds none of it. OpenCode 1 keeps working; where akm reads its version it warns once that OpenCode 2 is recommended.akm proposal extract --type opencodereads OpenCode 2 history with SQLite, read-only.akm upgradeandakm healthknow the newakm-opencode-v2plugin. akm-cli/api.curate(query, options)returns exactly whatakm --detail agent -q curateprints, computed in-process. It is for the plugins; nothing else is a public API.- Feedback changes ranking.
akm searchandakm curatescale each hit by your feedback on it. The effect is small and the same for every asset: about +2, +3, +5 and +9 percent for 1, 2, 5 and 20 positives. In keyword-only search a vote moves a hit one place, whatever the keyword margin; when embeddings contribute too, a vote breaks only near-ties. Improve, task and audit feedback does not count. - Distill extends a lesson that a memory repeats, as a proposal for a person
(
distill-update). akm ui(Experimental) serves a local web UI on127.0.0.1over the dataakm health,akm metrics,akm config,akm proposalandakm searchreport. Browsing writes nothing; its explicit actions (accept or reject a proposal, feedback, bundle and config changes, editing knowledge and memories) run the same operations as the CLI.akm showreturns a Markdown document's outline astoc, one{ level, text, slug, startLine }entry per heading, at every--detaillevel.--detail briefis the outline without the body, andakm show <ref>#<slug>selects one section (#1259).- Workflows are Experimental in 0.10.0. The promote-or-remove decision
(#1096) comes in 0.10.x. The 0.10 redesign (#1245) has three parts. Installing
a bundle is the trust decision: there is no dangerous-env audit on
akm bundle addorupdateand no block inakm env run,akm secret runor a unit'senv:bindings (--allow-dangerous-env-keysis a no-op through 0.10, andakm lintstill reportsdangerous-env-key, without blocking). Refs resolve at use: a plan holds the refs it uses and no locations, so a run finds its bundle again at each step andakm bundle updateno longer fails a run in flight. Runs are ids:akm workflow run <ref>always starts a new run, with one warning naming the other active runs of that ref,akm workflow run <run-id>continues one, andakm workflow listshows every run on the host from any directory (--newand--all-scopesare accepted and do nothing). - Child workflows keep a simple form:
unit: { workflow: workflows/<name>, with: {...} }. A param'sdefault:is now applied at run start. akm proposal extractis Evolving, not Experimental.akm improve <scope>warns when the scope matches no asset.- Daily-build versioning and the
nextchannel, above.
Changed defaults
- The
defaultimprove strategy now drains the proposal queue inpromotemode with judgment off, up to 200 accepts a run. It accepts what a quality judge already passed and the retirements the consolidate pair pass staged. The judgment tier is off in every built-in strategy and may accept only consolidate promotions. Setimprove.strategies.default.processes.triage.enabledtofalseto leave every proposal for review. - The proactive-maintenance lane is on in
default: up to 15 assets a run that have no fresh feedback and are 30 days past their last reflect or distill. Its proposals always wait for a person. - A manual fix (
akm feedback --replace/--with/--source,--superseded-by,--outdated) applies at once instead of queuing a proposal.akm proposal revertundoes it. If the accept refuses, the command fails; drop any follow-upakm proposal acceptfrom your scripts. akm searchandakm curatedefault to--belief current(0.9:all), so deprecated, contradicted, superseded and archived assets leave the default results. Pass--belief allto see them.akm improvesyncs a git-backed bundle before it plans, asakm syncdoes, and again at the end. A conflict warns and the run continues.--no-syncand--no-pushapply to both.- A reflect revision the judge does not pass but scores 3.5 or more goes to a
person as
judge-uncertaininstead of locking the asset for 14 days. A missing distill judge queues for review instead of a 30-day lock. captureMode: hotmemories are consolidated like any other memory.- Retire proposals expire by age (
archiveRetentionDays, default 90) like every other proposal. The per-runimproveandindexlog files are purged underimprove.eventRetentionDays. - akm writes
observedforobserved_atandstarted/endedforstarted_at/ended_atin frontmatter; it still reads the old names and rewrites no file. - An env or secret file that is a symlink, also to a file outside the bundle
(such as
/run/secrets/<name>), now resolves, and a secret's value has its surrounding whitespace trimmed everywhere (akm secret runused to pass the trailing newline). - Stopping a child process (a timeout, an abort or a signal to akm) sends SIGINT first, then SIGTERM and SIGKILL 5 seconds apart, where 0.9 sent SIGTERM then SIGKILL.
- A standalone
akm proposal drainresolves to promote mode on a stock install and asks for confirmation. Without a terminal it exits 2 unless you pass--yes.
Removed
- Reflect's retrieval regression gate. It refused 12 to 17 percent of the revisions the judge had passed and lowered the defects fixed. A judge-passed revision is now minted as a proposal with no further check. It had no config key.
- The high-salience improve lane.
- The hint tables and error messages for the 0.9.0 renames, the
vault:,env:andsecret:ref rejections, the--from stash|botherror, and the bespoke errors for retired config keys. They are ordinary unknown commands, flags or keys now. - The
targetVocabmarker ontask_historyrows and the"mcp"package keyword. - The
opencode serveserver management, the OpenCode HTTP adapters, the per-harness result extractors and their JSON output modes, and the LLM feature gate.
Plugins
akm-opencodeis for OpenCode 1.akm-opencode-v2is for OpenCode 2. Each pins one exactakm-cli, andakm upgradeholds the CLI to the pin.- OpenCode 1 caches the plugin spec it resolved and does not re-check it. A new
build is picked up only after the plugin's cache folder is cleared.
akm upgradedoes this for@latest(or@next) when no OpenCode process runs. For OpenCode 2 it runsopencode plugin updateinstead, even while OpenCode runs; the new build loads at the next restart. A spec pinned in your OpenCode config is left alone. - OpenCode 1 asks before reading or writing outside the project directory.
OpenCode 2 does not unless its config says
ask. OpenCode's headlessrun, which akm's own runtime and theopencodeharness both use, rejects every permission request and cancels every question, and the model carries on; akm changes no OpenCode default. See Configuration. - The Claude Code and Codex plugins come from the
akm-pluginsmarketplace, and the 0.10 set needs akm 0.10.261004 or newer. Its default branch carries stable builds andnextcarries prereleases (itlackey/akm-plugins@nextin Claude Code,codex plugin marketplace add itlackey/akm-plugins --ref nextin Codex);akm upgradeupdates the ref your marketplace follows and cannot switch it. - Plugins and scripts that pass
--shape agentmust move to--detail agentin step with the CLI. A call with--shape agentfails on 0.10, and one with--detail agentfails on 0.9.
Fixes worth naming
akm syncfetches and merges what another host pushed before it pushes. It used to exit 70 once another host had pushed.- The 02:00 nightly
akm improveno longer loses its night to the consolidate task's lock. The shipped consolidate task passes--timeout-ms 3600000; a copy set up from the 0.9 template keeps the 2-hour budget, so add the flag to it. - Command tasks (
uses: commands/...) get the 6-hour unattended default timeout. - A transient reflect failure no longer uses up the feedback that planned it.
- A run killed by its budget watchdog leaves a record and commits what it wrote.
- The extract per-session lock is reclaimed only from a dead holder.
- Memory inference writes to the default bundle and no longer reverts an edit made to the parent memory during the model call.
- The consolidate pair judge no longer treats a later date alone as a
replacement: a note replaces another only when both are about the same named
thing. On the eval,
gpt-oss:120bunsafe retirements went from 1, 2, 1 to 0, 0, 0 over three runs. - A gateway that answers 5xx
format_ignoredno longer fails every schema call, and a call recovered by the retry counts as one successful call in the usage rows. akm proposal revertof a retirement works after the 30-day archive purge.akm searchno longer warns "no embedding provider is configured" on a default install.- A signal to
akm agentnow ends the CLI harness it started. - A negative whose exact fix was applied (
--replace/--with,--superseded-byor--outdated) no longer demotes the corrected asset inakm searchandakm curate(#1249).akm proposal revertof the fix makes it count again; a fix the accept refused, and every negative without a fix, still count. One known edge, deferred to 0.10.x: feedback times are whole seconds, so a refused fix recorded in the same second as an accepted one on the same asset is treated as acted on (one vote on one asset). akm bundle renamecarries the bundle's recorded feedback and improve state to the new name (#1250). It left them under the old one, so after a rename no feedback counted in ranking for the bundle's assets and improve stopped reading it.akm health:plugin-versionfollows the channel the marketplace clone follows, so a Claude Code plugin onnextis no longer reported stale against the 0.9 stable release (#1263); acrontabrefusal in a process started with no-new-privileges (an agent sandbox, a container) names that cause (#1263); and the OpenCode 1 plugin check reads the cache folder of the spec your OpenCode config names (#1265).akm feedbackfails with exit 78 (DATA_DIR_NOT_WRITABLE) when it cannot store the feedback, as in 0.9.32. It printed"ok": trueand dropped the row.- Zod moves to 4.6.7, closing GHSA-mrhx-c7xc-m3w5 (memory exhaustion validating
a large array; #1264). It shows only in config validation: the messages are
Zod 4's (an unknown enum value reads
Invalid option: expected one of ...), and an integer above 2^53 - 1 in a config file is rejected.
For the rules each improve process follows in 0.10, see
the improvement loop and the
improve workflow reference. For the
entry behind each item, run akm help migrate <build number> (for example
akm help migrate 0.10.26101201) or read the
CHANGELOG.