akm-opencode 0.8.2 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +90 -234
- package/index.ts +866 -2599
- package/package.json +10 -8
- package/shared/akm-version.ts +45 -0
- package/shared/feedback-signals.ts +39 -0
- package/shared/memory-events.ts +12 -43
- package/shared/ref-extraction.ts +75 -216
- package/shared/state-files.ts +98 -0
- package/shared/vendor-semver.ts +112 -0
- package/agent/akm-curator.md +0 -66
- package/commands/akm-evolve-session.md +0 -15
- package/commands/akm-improve-asset.md +0 -9
- package/commands/akm-propose-asset.md +0 -8
- package/commands/akm-review-proposals.md +0 -8
- package/commands/akm-workflow-status.md +0 -7
- package/shared/memory-candidates.ts +0 -196
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# akm-opencode
|
|
2
2
|
|
|
3
|
-
OpenCode plugin for
|
|
3
|
+
OpenCode plugin for [AKM](https://github.com/itlackey/akm) `^0.9.0`. It exposes exactly five public tools and uses lifecycle hooks to bring relevant AKM context into a session.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
Add
|
|
7
|
+
Add the plugin to `opencode.json`:
|
|
8
8
|
|
|
9
9
|
```json
|
|
10
10
|
{
|
|
@@ -14,255 +14,111 @@ Add to your OpenCode config (`opencode.json`):
|
|
|
14
14
|
|
|
15
15
|
## Tools
|
|
16
16
|
|
|
17
|
-
The plugin exposes **21 high-value tools**. Long-tail verbs (`add`, `save`, `import`, `clone`, `update`, `remove`, `list`-sources, `registry-search`, `index`-reindex, `config`, `upgrade`, `tasks`, ad-hoc `run`, raw `agent`, vault writes, secret writes/run) are reachable via `akm_help` plus the raw `akm` CLI through the `bash` tool.
|
|
18
|
-
|
|
19
17
|
| Tool | Description |
|
|
20
|
-
|------|-------------|
|
|
21
|
-
| `akm_info` | Show `akm info` output together with the installed `akm-opencode` plugin version and install location |
|
|
22
|
-
| `akm_search` | Search the local stash, the registry, or both. Type filter accepts `skill`, `command`, `agent`, `knowledge`, `lesson`, `memory`, `script`, `task`, `workflow`, `vault`, `secret`, `wiki`, `any`; proposed hits can be included explicitly |
|
|
23
|
-
| `akm_show` | Show a stash asset by its ref |
|
|
24
|
-
| `akm_agent` | Dispatch a stash `agent:*` into OpenCode using the stash prompt and metadata |
|
|
25
|
-
| `akm_cmd` | Execute a stash `command:*` template in OpenCode via SDK session prompting |
|
|
26
|
-
| `akm_remember` | Record a memory in the default stash |
|
|
27
|
-
| `akm_feedback` | Record positive or negative feedback for a stash asset (skipped automatically for `memory:`, `vault:`, `secret:`, `lesson:`, and proposed-quality refs) |
|
|
28
|
-
| `akm_curate` | Curate the stash for a task or topic and return ranked matches the agent can use |
|
|
29
|
-
| `akm_evolve` | Dispatch the AKM curator subagent into a child session, capture the report as a memory, and seed the curator-context cache so it survives compaction |
|
|
30
|
-
| `akm_parent_messages` | Summarize the parent OpenCode session so dispatched stash subagents can inherit upstream context |
|
|
31
|
-
| `akm_session_messages` | Summarize a specific OpenCode session (arbitrary IDs restricted to `akm-curator`) |
|
|
32
|
-
| `akm_vault` | Vault `list` / `show` (key names) / `load` (writes the shell snippet to a temp file path without surfacing values inline). **Values never surface** through tool output |
|
|
33
|
-
| `akm_secret` | Secret `list` / `path` only. Returns refs or the absolute file path for `_FILE`-style consumers without reading contents |
|
|
34
|
-
| `akm_wiki` | Manage wikis (`create`, `register`, `list`, `show`, `pages`, `search`, `stash`, `lint`, `ingest`, `remove`) |
|
|
35
|
-
| `akm_workflow` | Drive workflow runs (`start`, `next`, `complete`, `status`, `list`, `create`, `template`, `resume`) |
|
|
36
|
-
| `akm_proposal` | Operate the v0.8.0 proposal queue (`list` / `show` / `diff` / `accept` / `reject`). Always confirm with the user before `accept`/`reject` — those operations require explicit approval |
|
|
37
|
-
| `akm_improve` | Generate improvement proposals for an existing ref, a whole asset type, or the current stash scope; output lands in the proposal queue only |
|
|
38
|
-
| `akm_propose` | Generate a new-asset proposal via the configured agent CLI; the result is `quality:"proposed"` until accepted |
|
|
39
|
-
| `akm_init` | Initialize AKM's working stash directory and persist `stashDir` in config. This is the agent-safe initialization path; interactive `akm setup` is human-facing |
|
|
40
|
-
| `akm_help` | Discover the right `akm` CLI invocation for non-first-class verbs. Returns a curated quick-reference table plus live `akm <subcommand> --help` output |
|
|
41
|
-
|
|
42
|
-
## Compound-engineering hooks
|
|
43
|
-
|
|
44
|
-
The plugin subscribes to OpenCode lifecycle events so AKM participates in the
|
|
45
|
-
session loop instead of waiting to be called. Every hook is non-blocking and
|
|
46
|
-
fails silently when a compatible `akm` is not resolvable — the TUI is never affected.
|
|
47
|
-
|
|
48
|
-
| Event | What happens |
|
|
49
18
|
| --- | --- |
|
|
50
|
-
|
|
|
51
|
-
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
| **`experimental.session.compacting`** | Pushes hints, curated context, active workflows, and the last curator report into the compaction prompt so they survive transcript shrinking. |
|
|
56
|
-
| **`shell.env`** | Exposes `AKM_PROJECT`, `AKM_PLUGIN_VERSION`, and the resolved `AKM_STASH_DIR` to shell tools so raw shell checks and plain `akm` invocations see the same stash path as the plugin. |
|
|
57
|
-
| **`stop`** / **`session.idle`** / **`session.compacted`** / **`session.deleted`** | Flushes the per-session buffer into a `memory:opencode-session-YYYYMMDD-<sid>` memory so every meaningful session contributes durable context for future searches. The persisted memory now includes compact event/candidate summaries plus explicit file paths to the full-detail plugin state and OpenCode host logs so `akm improve` can inspect deeper evidence when needed. Requires at least two observations before persisting. When `AKM_INDEX_ON_SESSION_END=1`, the hook follows a successful flush with `akm index` so upstream inference/graph passes run immediately. |
|
|
58
|
-
|
|
59
|
-
### Locking down destructive commands
|
|
60
|
-
|
|
61
|
-
Earlier versions of this plugin shipped `permission.ask` and
|
|
62
|
-
`command.execute.before` hooks that tokenized each raw `akm` CLI invocation
|
|
63
|
-
and **denied** a hard-coded list of risky subcommands (vault writes,
|
|
64
|
-
`save --push`, `accept` / `reject` / `revert`, `tasks add` / `tasks run`,
|
|
65
|
-
`upgrade`, `update --all`, etc.) until the user re-approved them inline.
|
|
66
|
-
That gate has been removed in 0.8.0. The tokenized matcher was brittle — it
|
|
67
|
-
produced false positives on commit messages, heredoc bodies, and other
|
|
68
|
-
prose that happened to contain `akm <verb>` substrings — and gating
|
|
69
|
-
destructive shell calls is fundamentally the host platform's job, not a
|
|
70
|
-
plugin's.
|
|
71
|
-
|
|
72
|
-
OpenCode does not currently expose a first-class declarative permission
|
|
73
|
-
DSL equivalent to Claude Code's `permissions.ask` / `permissions.deny`.
|
|
74
|
-
For the verbs that historically tripped the plugin's gate, lock things
|
|
75
|
-
down at the OS level instead:
|
|
76
|
-
|
|
77
|
-
- **Run `akm` under a wrapper script** that prompts (or denies) on the
|
|
78
|
-
destructive subcommands you care about. Put the wrapper earlier on
|
|
79
|
-
`PATH` than the real `akm`. For example:
|
|
80
|
-
|
|
81
|
-
```sh
|
|
82
|
-
#!/usr/bin/env bash
|
|
83
|
-
# ~/bin/akm — wraps the real akm to confirm destructive verbs
|
|
84
|
-
case "$1 $2 $3" in
|
|
85
|
-
"vault set "*|"vault unset "*|"vault load "*|"vault create "*|\
|
|
86
|
-
"save --push"*|"sync "*|"sync"|"remove "*|\
|
|
87
|
-
"accept "*|"reject "*|"revert "*|\
|
|
88
|
-
"proposal accept "*|"proposal reject "*|"proposal revert "*|"proposal drain "*|\
|
|
89
|
-
"tasks add "*|"tasks remove "*|"tasks enable "*|"tasks disable "*|\
|
|
90
|
-
"tasks run "*|"upgrade"*|"update --all"*|"config set "*)
|
|
91
|
-
read -rp "Run 'akm $*' ? [y/N] " ans
|
|
92
|
-
[[ "$ans" == "y" || "$ans" == "Y" ]] || { echo "aborted"; exit 1; } ;;
|
|
93
|
-
esac
|
|
94
|
-
exec /usr/local/bin/akm-real "$@"
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
- **Use OS-level access controls** (`sudo`, `chmod`, mount restrictions,
|
|
98
|
-
AppArmor / SELinux profiles) when running OpenCode in shared or
|
|
99
|
-
sandboxed environments.
|
|
100
|
-
- **Vault and secret writes still bypass the chat turn entirely.** Use the typed
|
|
101
|
-
`akm_vault` tool only for read paths (`list`, `show` of key names,
|
|
102
|
-
`load` when you need a temporary shell-file path without surfacing
|
|
103
|
-
values inline), and the typed `akm_secret` tool only for `list` / `path`.
|
|
104
|
-
To create vaults or set/unset values, or to set/run/remove whole-file
|
|
105
|
-
secrets, run `akm env …` / `akm secret …` directly in the shell so
|
|
106
|
-
secret material never passes through the chat turn.
|
|
107
|
-
|
|
108
|
-
The plugin's typed `akm_*` tools (`akm_vault show`, `akm_proposal accept`,
|
|
109
|
-
etc.) still apply their per-tool `confirm:true` contracts at
|
|
110
|
-
`tool.execute.before`. Only the raw-shell tokenized gate has been removed.
|
|
111
|
-
|
|
112
|
-
### Environment overrides
|
|
19
|
+
| `akm_search` | Search configured bundles or registries. `source` accepts `local`, `registry`, `all`, or a configured bundle name. |
|
|
20
|
+
| `akm_show` | Show a concept by `[bundle//]conceptId[#fragment]`. A fragment selects a Markdown section. |
|
|
21
|
+
| `akm_curate` | Return ranked concepts for a task or topic. |
|
|
22
|
+
| `akm_feedback` | Record positive or negative feedback for a concept. |
|
|
23
|
+
| `akm_remember` | Save durable knowledge as a searchable memory. |
|
|
113
24
|
|
|
114
|
-
|
|
115
|
-
| --- | --- | --- |
|
|
116
|
-
| `AKM_AUTO_CURATE` | `1` | Set to `0` to disable automatic `akm curate` on user messages. Session start no longer auto-curates. |
|
|
117
|
-
| `AKM_LOCAL_BUILD_CLI` | _(unset)_ | Optional absolute path to a locally built AKM CLI entrypoint such as `/abs/path/to/akm/dist/cli.js`. When set, the OpenCode plugin runs that build through Bun before falling back to bundled or PATH-based `akm` binaries. |
|
|
118
|
-
| `AKM_AUTO_FEEDBACK` | `1` | Set to `0` to disable automatic `akm feedback` on tool success/failure. |
|
|
119
|
-
| `AKM_AUTO_HINTS` | `1` | Set to `0` to skip injecting `akm hints` at session start. |
|
|
120
|
-
| `AKM_AUTO_MEMORY` | `1` | Set to `0` to disable automatic session-summary memories. |
|
|
121
|
-
| `AKM_INDEX_ON_SESSION_END` | `0` | Set to `1` to run `akm index` after a session-end memory is captured. |
|
|
122
|
-
| `AKM_CURATE_LIMIT` | `5` | Max curated results injected into context per prompt. |
|
|
123
|
-
| `AKM_CURATE_MIN_CHARS` | `16` | Minimum prompt length before curation runs. |
|
|
124
|
-
| `AKM_CURATE_TIMEOUT` | `8` | Wall-clock seconds for `akm` invocations inside hooks. |
|
|
125
|
-
| `AKM_CONTEXT_BUDGET_CHARS` | `4000` | Max total characters injected into system/compaction context for a single turn. |
|
|
126
|
-
| `AKM_CURATOR_CONTEXT_MAX_CHARS` | `4000` | Max cached curator-report characters re-injected into system/compaction context; the full report is still persisted as memory. |
|
|
127
|
-
| `AKM_MEMORY_CHECKPOINT_EVERY` | `8` | Number of successful asset-touching tool calls between mid-session checkpoint memories. |
|
|
128
|
-
| `AKM_RETROSPECTIVE_FEEDBACK_PATTERN` | `\b(thanks|perfect|worked)\b` | Case-insensitive regex used for lightweight positive retrospective feedback on the most recent refs. |
|
|
129
|
-
| `AKM_RETROSPECTIVE_NEGATIVE_PATTERN` | `\b(wrong|failed|broken|didn't work|did not work|bad)\b` | Case-insensitive regex used for negative retrospective feedback signals. |
|
|
130
|
-
| `AKM_SCOPE_KEYS` | `user,agent,run,channel` | Comma-separated list of scope fields to attach on every `akm_remember`, `akm_curate`, and `akm_feedback` call. Remove a key to opt out of that dimension. |
|
|
131
|
-
| `AKM_PENDING_PROPOSAL_TIMEOUT` | `2` | Seconds allowed for lightweight pending-proposal count checks during context injection. |
|
|
132
|
-
|
|
133
|
-
### Curator agent
|
|
134
|
-
|
|
135
|
-
`akm_evolve` dispatches the native `akm-curator` OpenCode subagent when it is
|
|
136
|
-
available, falling back to `general` with the same curator prompt when needed.
|
|
137
|
-
The curator reviews recent AKM activity (OpenCode app logs, session-summary
|
|
138
|
-
memories, parent-session context, live stash), produces a prioritized action
|
|
139
|
-
list, and persists its latest report as `memory:akm-curator-YYYYMMDD-<sid>` so
|
|
140
|
-
future curator runs can build on it.
|
|
141
|
-
|
|
142
|
-
## AKM v1 workflows
|
|
143
|
-
|
|
144
|
-
The plugin injects a concise AKM workflow instruction pack into context so agents:
|
|
145
|
-
|
|
146
|
-
- search or curate before writing from scratch;
|
|
147
|
-
- show an asset before relying on it;
|
|
148
|
-
- record feedback after the result is known;
|
|
149
|
-
- treat `lesson:*` as first-class durable assets;
|
|
150
|
-
- treat proposed-quality assets as uncurated until accepted;
|
|
151
|
-
- use `akm_help` to route `proposal`, `improve`, `propose`, and `tasks` CLI workflows;
|
|
152
|
-
- require explicit user approval before proposal acceptance/rejection, push saves, source removal, CLI upgrades, update-all, vault value access, or secret-path access.
|
|
153
|
-
|
|
154
|
-
The package also ships OpenCode command docs for common workflows:
|
|
155
|
-
|
|
156
|
-
- `/akm-review-proposals`
|
|
157
|
-
- `/akm-improve-asset`
|
|
158
|
-
- `/akm-propose-asset`
|
|
159
|
-
- `/akm-evolve-session`
|
|
160
|
-
- `/akm-workflow-status`
|
|
161
|
-
|
|
162
|
-
### Registry discovery
|
|
163
|
-
|
|
164
|
-
Search registries with `akm_search` using `source: "registry"` or `source: "both"`. Registry hits include `id`, `installRef`, and `action` fields. Use `installRef` when feeding a result into `akm add` (run via `akm_help` topic="add" or directly through bash); registry-specific IDs are not installable refs.
|
|
165
|
-
|
|
166
|
-
## Agent Dispatch
|
|
167
|
-
|
|
168
|
-
Use `akm_agent` after retrieving an agent ref from `akm_search`.
|
|
169
|
-
|
|
170
|
-
Inputs:
|
|
171
|
-
- `ref` (optional): stash ref like `agent:coach.md`
|
|
172
|
-
- `query` (optional): resolve best matching stash agent when `ref` is omitted
|
|
173
|
-
- `task_prompt` (required): user task to run
|
|
174
|
-
- `dispatch_agent` (optional): OpenCode agent name, or a `provider/model` override like `openai/gpt-5.3-codex` (defaults to `general`)
|
|
175
|
-
- `as_subtask` (optional): create child session (defaults to `true`)
|
|
176
|
-
|
|
177
|
-
At least one of `ref` or `query` is required.
|
|
178
|
-
|
|
179
|
-
Behavior:
|
|
180
|
-
- Loads the stash agent via `akm show`
|
|
181
|
-
- Uses stash `prompt` verbatim as OpenCode `system`
|
|
182
|
-
- Treats `dispatch_agent` values in `provider/model` form as model overrides and keeps a valid OpenCode agent in the `agent` field
|
|
183
|
-
- Applies stash `modelHint` when in `provider/model` format
|
|
184
|
-
- Applies stash `toolPolicy` when it maps to boolean tool flags
|
|
185
|
-
|
|
186
|
-
## Command Execution
|
|
187
|
-
|
|
188
|
-
Use `akm_cmd` to execute stash command templates through the OpenCode SDK.
|
|
189
|
-
|
|
190
|
-
Inputs:
|
|
191
|
-
- `ref` (optional): stash ref like `command:review.md`
|
|
192
|
-
- `query` (optional): resolve best matching stash command when `ref` is omitted
|
|
193
|
-
- `arguments` (optional): raw command arguments for `$ARGUMENTS`, `$1`, `$2`, etc.
|
|
194
|
-
- `dispatch_agent` (optional): OpenCode agent name, or a `provider/model` override like `openai/gpt-5.3-codex` (defaults to current agent)
|
|
195
|
-
- `as_subtask` (optional): create child session (defaults to `false`)
|
|
196
|
-
|
|
197
|
-
At least one of `ref` or `query` is required.
|
|
198
|
-
|
|
199
|
-
## Prerequisites
|
|
200
|
-
|
|
201
|
-
When the plugin loads, it resolves the bundled `akm-cli` dependency installed with the plugin and requires an `akm` version that satisfies `^0.8.0`. It prefers that bundled binary first, falls back to an existing `akm` on PATH only when it also satisfies the same range, and otherwise returns a structured error telling you to reinstall or update the plugin so OpenCode/Bun installs the dependency. It does not run global installers from plugin runtime.
|
|
202
|
-
|
|
203
|
-
```sh
|
|
204
|
-
# macOS / Linux
|
|
205
|
-
curl -fsSL https://raw.githubusercontent.com/itlackey/akm/main/install.sh | bash
|
|
206
|
-
# PowerShell (Windows)
|
|
207
|
-
irm https://raw.githubusercontent.com/itlackey/akm/main/install.ps1 -OutFile install.ps1; ./install.ps1
|
|
208
|
-
```
|
|
25
|
+
`akm_search`, `akm_show`, and `akm_curate` call the bundled AKM read APIs in process. `akm_feedback` and `akm_remember` use the compatible AKM CLI because they mutate AKM state. Failures return structured results and are logged through OpenCode app logging.
|
|
209
26
|
|
|
210
|
-
|
|
211
|
-
dependency automatically.
|
|
27
|
+
Use the `ref` returned by search or curate directly with show or feedback. Concept IDs look like `skills/code-review`, `memories/release-retro`, or `team-playbook//knowledge/deploy#Rollback`.
|
|
212
28
|
|
|
213
|
-
##
|
|
29
|
+
## Lifecycle Hooks
|
|
214
30
|
|
|
215
|
-
The
|
|
31
|
+
The plugin subscribes to OpenCode lifecycle events. Hook failures are logged through OpenCode app logging and do not interrupt the TUI.
|
|
216
32
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
33
|
+
| Event | Behavior |
|
|
34
|
+
| --- | --- |
|
|
35
|
+
| `session.created` | Resolves AKM, warms local data in the background, and prepares hints, an active-workflow summary, and curated context for the session. |
|
|
36
|
+
| `session.updated` | Backfills hints and the workflow summary for a session the plugin has not prepared yet. It does not re-run session-created work. |
|
|
37
|
+
| `chat.message` | Records feedback or memory intent and can schedule non-blocking curation for a substantive prompt. The curate is fire-and-forget: its result is injected on a later turn rather than delaying this one. |
|
|
38
|
+
| `experimental.chat.system.transform` | Injects the AKM guidance and cached curated context into the system prompt. The host rebuilds the system prompt on every request, so these blocks are re-injected each turn — including after a compaction — rather than once per session. |
|
|
39
|
+
| `tool.execute.after` | Tracks concepts used by AKM tools, records deduplicated feedback, and checkpoints session observations. |
|
|
40
|
+
| `shell.env` | Exposes `AKM_PROJECT`, `AKM_PLUGIN_VERSION`, and the resolved `AKM_BUNDLE_DIR` to shell tools. |
|
|
41
|
+
| `session.idle` | Runs interval-gated memory extraction (`AKM_AUTO_MEMORY=0` disables it). Fires after every turn, so it is rate-limited. |
|
|
42
|
+
| `session.compacted` | Records a post-compaction event. |
|
|
43
|
+
| `session.deleted` | Refreshes the local AKM index, then drops all per-session state and the temporary curation file. |
|
|
220
44
|
|
|
221
|
-
|
|
45
|
+
The session observation buffer that retrospective feedback reads from survives every non-terminal event: it is bounded by `AKM_SESSION_BUFFER_MAX_ENTRIES` and dropped only on `session.deleted`. Discarding it at `session.idle` would empty it between turns, so "thanks, that worked" would credit nothing in exactly the sessions that used the most assets.
|
|
222
46
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
├── agents/ # markdown files
|
|
229
|
-
├── knowledge/ # markdown files
|
|
230
|
-
├── memories/ # markdown memory files (akm remember)
|
|
231
|
-
├── lessons/ # first-class durable learnings (lesson:<name>) — often produced by akm improve, accepted via akm proposal accept
|
|
232
|
-
├── tasks/ # scheduled task definitions (task:<name>) managed via akm tasks ...
|
|
233
|
-
├── workflows/ # multi-step procedures (workflow:<name>)
|
|
234
|
-
├── vaults/ # .env secret stores (vault:<name>) — values never surface through structured output
|
|
235
|
-
├── secrets/ # whole-file secrets (secret:<name>) — contents never surface through structured output
|
|
236
|
-
├── wikis/ # per-wiki directories <name>/{schema,index,log}.md + raw/ + pages
|
|
237
|
-
└── .akm/proposals/ # v0.8.0 proposal queue — drafts that never leak into search or commits
|
|
238
|
-
```
|
|
47
|
+
Automatic feedback skips references that AKM reports as ineligible, and a *successful* `akm_show` / `akm_search` / `akm_curate` submits nothing — inspecting a concept is not evidence that it helped, so on OpenCode the positive signal comes from a retrospective confirmation instead. Failures of those same tools still count as negative signal. Same rule as the Claude plugin, which applies it to the `akm` subcommand of a Bash invocation.
|
|
48
|
+
|
|
49
|
+
## Locking down destructive commands
|
|
50
|
+
|
|
51
|
+
The plugin does not gate destructive `akm` commands. The `permission.ask` / `command.execute.before` hook that tokenized each Bash invocation and blocked a hard-coded list of risky `akm` subcommands was removed in 0.8.0: tokenized matching produced false positives on commit messages, heredoc bodies, and any other prose containing an `akm <verb>` substring.
|
|
239
52
|
|
|
240
|
-
|
|
53
|
+
OpenCode has no first-class permission DSL today, so enforce it outside the plugin — wrap `akm` in a confirmation script earlier on `PATH`, or use OS-level access controls.
|
|
241
54
|
|
|
242
|
-
`
|
|
243
|
-
AKM CLI itself guarantees vault values never appear in JSON, the search index,
|
|
244
|
-
`.stash.json`, or any structured output channel. This plugin mirrors that:
|
|
55
|
+
Independently of any such control, agents should treat these verbs as requiring explicit user approval: `proposal accept`, `proposal reject`, `proposal revert`, `sync --push`, `remove`, env/secret writes, `task add` / `task run`, `upgrade`, `update --all`, `config set`.
|
|
245
56
|
|
|
246
|
-
|
|
247
|
-
- `action: "set"` / `"unset"` never echo the value.
|
|
248
|
-
- `action: "load"` wraps `akm vault load` and returns the raw shell text
|
|
249
|
-
as-is. Treat it as opaque and hand it straight to a shell via
|
|
250
|
-
`eval "$(…)"` — do not log it, do not pass it through another tool, and do
|
|
251
|
-
not let the agent inspect it.
|
|
57
|
+
## Environment
|
|
252
58
|
|
|
253
|
-
|
|
254
|
-
refs so usage signals can't leak which sensitive asset was touched.
|
|
59
|
+
Every kill switch below is opt-out and reads the same way: only the literal `0` disables it. Any other value — including `false` — leaves the feature on.
|
|
255
60
|
|
|
256
|
-
|
|
61
|
+
### Core
|
|
62
|
+
|
|
63
|
+
| Variable | Default | Purpose |
|
|
64
|
+
| --- | --- | --- |
|
|
65
|
+
| `AKM_BUNDLE_DIR` | unset | Absolute path to the AKM bundle root. When unset the plugin discovers it once per process by running `akm info`. The resolved value is re-exported to shell tools through the `shell.env` hook. |
|
|
66
|
+
| `AKM_LOCAL_BUILD_CLI` | unset | Absolute path to a locally built AKM CLI entry point. |
|
|
67
|
+
| `AKM_OPENCODE_IGNORE_BUNDLED_CLI` | unset (off) | Set to `1` to drop the bundled AKM CLI from resolution so only an `akm` on `PATH` is considered. Used by the eval harness; also an escape hatch when the bundled dependency is broken. |
|
|
68
|
+
| `AKM_AUTO_CURATE` | `1` | Set to `0` to disable automatic prompt curation. |
|
|
69
|
+
| `AKM_AUTO_FEEDBACK` | `1` | Set to `0` to disable automatic outcome feedback. |
|
|
70
|
+
| `AKM_AUTO_HINTS` | `1` | Set to `0` to skip the per-session `akm hints` call. The missing-bundle warning is deliberately not gated on this: it explains why the stash is empty in the first place. |
|
|
71
|
+
| `AKM_AUTO_MEMORY` | `1` | Set to `0` to disable automatic memory harvesting — the interval-gated `akm proposal extract` on `session.idle`, which is the whole of that harvest here. The Claude plugin honours the same variable for its `SessionEnd` extract, so one setting covers both harnesses. |
|
|
72
|
+
| `AKM_INDEX_ON_SESSION_END` | `1` | Set to `0` to skip the `akm index` refresh. It runs only on `session.deleted` — never on `session.idle`, which fires after every turn. |
|
|
73
|
+
|
|
74
|
+
### Scope
|
|
75
|
+
|
|
76
|
+
| Variable | Default | Purpose |
|
|
77
|
+
| --- | --- | --- |
|
|
78
|
+
| `AKM_SCOPE_KEYS` | `user,agent,run,channel` | Which scope dimensions `akm_remember` forwards to the AKM CLI as flags. It does **not** gate what the plugin records locally — lifecycle events in `events.jsonl` always carry every dimension that has a value. |
|
|
79
|
+
| `AKM_USER_ID` | unset | Value for the `user` dimension. |
|
|
80
|
+
| `AKM_CHANNEL` | unset | Value for the `channel` dimension. |
|
|
81
|
+
| `AKM_REPO` | unset | Repository label recorded on lifecycle events. |
|
|
82
|
+
| `AKM_BRANCH` | unset | Branch label recorded on lifecycle events. |
|
|
83
|
+
|
|
84
|
+
The `agent`, `run`, and `project` dimensions come from OpenCode itself (the active agent, the session ID, and the worktree), so they have no environment variable. `AKM_PROJECT` is *written* by the `shell.env` hook for shell tools to read; the plugin never reads it.
|
|
85
|
+
|
|
86
|
+
### Tuning
|
|
87
|
+
|
|
88
|
+
| Variable | Default | Purpose |
|
|
89
|
+
| --- | --- | --- |
|
|
90
|
+
| `AKM_CURATE_LIMIT` | `5` | Maximum curated results injected per prompt. |
|
|
91
|
+
| `AKM_CURATE_MIN_CHARS` | `16` | Minimum prompt length for automatic curation. |
|
|
92
|
+
| `AKM_CURATE_TIMEOUT` | `8` | Timeout in seconds for AKM calls made by hooks. |
|
|
93
|
+
| `AKM_CONTEXT_BUDGET_CHARS` | `4000` | Maximum length of the AKM text injected into the system prompt on one turn. Past it the block is truncated with a marker. |
|
|
94
|
+
| `AKM_PENDING_PROPOSAL_TIMEOUT` | `2` | Timeout in seconds for the pending-proposal count. Floored at 0.5s. |
|
|
95
|
+
| `AKM_SESSION_BUFFER_MAX_ENTRIES` | `200` | Per-session cap on buffered observations. Oldest entries are dropped first. |
|
|
96
|
+
| `AKM_EXTRACT_MIN_INTERVAL_MS` | `600000` | Minimum gap between `akm proposal extract` runs for one session. `session.idle` fires after every turn, so without this gate extraction would flood. |
|
|
97
|
+
| `AKM_PLUGIN_MAX_LOG_BYTES` | `1048576` | Size cap for each append-only state file under `$XDG_STATE_HOME/akm-opencode`. Past the cap the newest half is retained. |
|
|
98
|
+
| `AKM_AUTO_FEEDBACK_MIN_CONFIDENCE` | `0.6` | Minimum classifier confidence before automatic feedback is actually submitted. Raise it to submit less. |
|
|
99
|
+
| `AKM_RETROSPECTIVE_FEEDBACK_PATTERN` | `\b(thanks\|perfect\|worked)\b` | Case-insensitive regex for "that worked" messages. Retune it for other languages or project jargon. An invalid regex falls back to the default rather than failing the hook. |
|
|
100
|
+
| `AKM_RETROSPECTIVE_NEGATIVE_PATTERN` | `\b(wrong\|failed\|broken\|didn't work\|did not work\|bad)\b` | Case-insensitive regex that vetoes retrospective credit, so a mixed message ("thanks, but it did not work") is skipped rather than misread as praise. Same fallback behavior. |
|
|
101
|
+
|
|
102
|
+
### Redaction
|
|
103
|
+
|
|
104
|
+
These three are read once, when the plugin module is imported, so they must be set in the environment **before** OpenCode starts. Both matchers are off by default because both over-redact on ordinary logs.
|
|
105
|
+
|
|
106
|
+
| Variable | Default | Purpose |
|
|
107
|
+
| --- | --- | --- |
|
|
108
|
+
| `AKM_REDACT_HIGH_ENTROPY` | unset (off) | Set to `1` to redact long base64/hex-shaped strings that look like secrets. |
|
|
109
|
+
| `AKM_REDACT_ENTROPY_MIN_LEN` | `32` | Minimum length for the high-entropy matcher. Values below `32` are clamped to `32`. No effect unless `AKM_REDACT_HIGH_ENTROPY=1`. |
|
|
110
|
+
| `AKM_REDACT_PII` | unset (off) | Set to `1` to redact credit-card-shaped digit runs, US SSNs, and phone numbers. |
|
|
257
111
|
|
|
258
|
-
|
|
259
|
-
- `action: "path"` returns the absolute file path without reading or surfacing contents.
|
|
260
|
-
- `action: "set"`, `"run"`, and `"remove"` are intentionally absent from the typed tool surface. Use raw `akm secret …` through the shell only after explicit user approval.
|
|
112
|
+
## Usage
|
|
261
113
|
|
|
262
|
-
|
|
114
|
+
1. Start with `akm_curate` for task-oriented discovery.
|
|
115
|
+
2. Use `akm_search` when you know the concept name and need its exact ID.
|
|
116
|
+
3. Fetch the full concept with `akm_show` before relying on it.
|
|
117
|
+
4. Record the outcome with `akm_feedback`.
|
|
118
|
+
5. Use `akm_remember` for durable knowledge that should be available to future sessions.
|
|
263
119
|
|
|
264
120
|
## Docs
|
|
265
121
|
|
|
266
122
|
- [AKM CLI](https://github.com/itlackey/akm)
|
|
267
|
-
- [OpenCode
|
|
268
|
-
- [OpenCode
|
|
123
|
+
- [OpenCode plugins](https://opencode.ai/docs/plugins/)
|
|
124
|
+
- [OpenCode custom tools](https://opencode.ai/docs/custom-tools/)
|