Skip to content

feat(cli): opt-in project memory - #11921

Merged
johnnyeric merged 3 commits into
mainfrom
johnnyeric/kilo-memory-cli
Jul 6, 2026
Merged

feat(cli): opt-in project memory#11921
johnnyeric merged 3 commits into
mainfrom
johnnyeric/kilo-memory-cli

Conversation

@johnnyeric

@johnnyeric johnnyeric commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Context

Adds opt-in project memory to the CLI so Kilo can persist durable project facts, corrections, environment notes, and session digests, then inject or recall them in later turns. The diff keeps reusable memory behavior in packages/kilo-memory and limits shared opencode changes to narrow wiring hooks.

Implementation

The memory package owns the core behavior: schemas, storage/state, capture planning/parsing, redaction/rejection, recall/indexing, Effect services, HTTP API types, and the concrete recall/save tool logic.

The opencode Kilo-owned paths add host integration: TUI memory commands, sidebar/dialog/palette UI, HTTP handlers, memory runtime wiring, session prompt injection/pinning, tool registration, and thin wrappers for kilo_memory_recall / kilo_memory_save.

Shared opencode files are only small annotated hooks for prompt injection, TUI registration, memory tool visibility, HTTP API registration, permission rendering, and Effect layer provisioning. SDK/OpenAPI files are generated from the new memory endpoints.

Screenshots / Video

  • Video shows memory recall only happens after memory is enabled
memory.mov
  • Memory help /memory
Screenshot 2026-07-06 at 12 48 46
  • Memory status /memory status
Screenshot 2026-07-06 at 12 49 34

How to Test

Manual/local verification

Agent-run checks:

  • packages/kilo-memory: bun run typecheck
  • packages/kilo-memory: bun test
  • packages/opencode: bun run typecheck
  • packages/opencode: bun test test/kilocode/memory/memory-ports.test.ts test/kilocode/memory/memory-integration.test.ts
  • packages/opencode: bun test test/kilocode/cli/cmd/tui/memory-command.test.ts
  • packages/opencode: bun test test/kilocode/tool/memory-recall.test.ts test/kilocode/tool/memory-save.test.ts
  • packages/opencode: bun test test/kilocode/server/httpapi-memory.test.ts
  • packages/opencode: bun test test/kilocode/memory/memory-recall-tool.test.ts before test relocation
  • packages/opencode: bun test test/kilocode/memory/memory-save-tool.test.ts test/kilocode/memory/memory-core.test.ts before test relocation
  • git diff --check
  • pre-push hook: bun turbo typecheck --filter=!@kilocode/kilo-jetbrains
  • pre-push hook: bun turbo typecheck --filter=@kilocode/kilo-jetbrains

Reviewer test steps

  1. Start the CLI in a test repo.
  2. Run /memory enable and confirm memory status/sidebar appears.
  3. Run /memory remember <project fact> and confirm the saved-memory toast appears.
  4. Ask a later question that should use saved project memory and confirm kilo_memory_recall can return the fact.
  5. Run /memory auto off, then /memory auto status, and confirm auto-save state changes.
  6. Run /memory disable and confirm memory is no longer injected or available to recall.

Checklist

  • Issue linked above, or exception explained
  • Tests/verification described
  • Screenshots/video included for visual changes, or marked N/A
  • Changeset considered for user-facing changes
  • I personally reviewed the diff and can explain the changes, including any AI-assisted work.

@johnnyeric johnnyeric changed the title feat(memory): opt-in project memory feat(cli): opt-in project memory Jul 3, 2026
@johnnyeric
johnnyeric force-pushed the johnnyeric/kilo-memory-cli branch 3 times, most recently from cdbf820 to 5a76b43 Compare July 3, 2026 15:52
@johnnyeric
johnnyeric marked this pull request as ready for review July 3, 2026 15:54

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5a76b43bba

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .changeset/kilo-memory-cli.md
Comment thread packages/kilo-memory/src/recall/topics.ts Outdated
Comment thread packages/opencode/src/config/config.ts Outdated
Comment thread packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-memory.tsx Outdated
Comment thread packages/opencode/src/kilocode/cli/cmd/tui/component/memory-sidebar.tsx Outdated
Comment thread packages/opencode/src/kilocode/memory/ports.ts Outdated
Comment thread packages/kilo-memory/src/capture/ops.ts Outdated
Comment thread packages/kilo-memory/src/effect/capture.ts Outdated
Comment thread packages/kilo-memory/src/capture/diff.ts
Comment thread packages/kilo-memory/src/capture/operations.ts
Comment thread packages/opencode/test/kilocode/server/httpapi-memory.test.ts Outdated
NJ-2020 pushed a commit to NJ-2020/kilocode that referenced this pull request Jul 4, 2026
Comment thread packages/kilo-memory/src/capture/redact.ts Outdated
Comment thread packages/kilo-memory/src/capture/reject.ts Outdated
Comment thread packages/kilo-memory/src/capture/ops.ts Outdated
Comment thread packages/kilo-memory/src/effect/capture.ts
Comment thread packages/kilo-memory/src/effect/service.ts Outdated
Comment thread packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-memory.tsx Outdated
Comment thread packages/opencode/src/kilocode/cli/cmd/tui/permissions.tsx
Comment thread packages/opencode/src/kilocode/server/httpapi/groups/memory.ts Outdated
Comment thread packages/opencode/src/kilocode/tool/registry.ts
@kilo-code-bot

kilo-code-bot Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Incremental review against previous review commit b98e0d67747cfa6b42564c1c6eab0a6ce5a78f82, diffing 1 file / 1 changed line. This adds the missing lastSessionSavedAt key to the expected stats-key assertion in the HTTP API memory test, matching the lastSessionSavedAt field added to the stats schema/contract in the prior commit.

  • packages/opencode/test/kilocode/server/httpapi-memory.test.ts: expectStats()'s expected key list now includes lastSessionSavedAt alongside the existing stat keys. Since the assertion compares sorted key arrays, array order doesn't matter — the fix correctly keeps the test in sync with the schema.

No new issues found in the changed line. The one previously-flagged comment on this file ("This assert is duplicated or wrong", anchored at original line 254) is unrelated to this 1-line change — it targets a different location in the file, is already marked outdated (line: null), and has an "Addressed" reply from the author.

Files Reviewed (incremental diff: 1 file)
  • packages/opencode/test/kilocode/server/httpapi-memory.test.ts
Previous Review Summaries (7 snapshots, latest commit b98e0d6)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit b98e0d6)

Status: No Issues Found | Recommendation: Merge

Incremental review against previous review commit 78c98ac64d9451544de2e91aee72840ca8a5785e, diffing 11 files / ~91 changed lines (2 files are generated SDK/OpenAPI artifacts). This adds a new handoff autosave status representing a digest-only save (no typed facts) so the UI can distinguish "nothing happened" from "a session summary was captured."

  • packages/kilo-memory/src/schema.ts: new stats.lastSessionSavedAt: number | null field, following the existing nullable()/default-object pattern used by every other stat.
  • packages/kilo-memory/src/effect/service.ts: commit() now sets lastSessionSavedAt to now only when input.digest is true, otherwise leaves it untouched — mirrors the existing lastTypedConsolidationAt handling for input.typed.
  • packages/kilo-memory/src/effect/httpapi.ts: lastSessionSavedAt added to the MemoryContract stats schema and required-fields lists, and threaded through the stats-to-wire mapping with a ?? 0 fallback consistent with sibling fields.
  • packages/kilo-memory/src/autosave-status.ts: summarize() gains a handoff branch — reported when there's no typed consolidation yet but a digest was saved, or when the digest is newer than or equal to the last typed consolidation and no facts were saved on that pass. The existing saved (typed, count > 0) check still takes precedence, which is correct since lastOperationCount is unconditionally rewritten on every commit (digest or typed), so a stale saved reading through a later digest-only commit isn't possible.
  • packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-memory.tsx and memory-sidebar.tsx: both UI consumers of MemoryAutosaveStatus.summarize were updated with a handoff case ("session handoff" / "session handoff saved · "); no consumer was missed.
  • Tests (core.test.ts, decisions.test.ts, effect-capture.test.ts) were updated/extended to cover the new field's defaults, parsing, and the new handoff transitions (digest-only, and typed-with-no-ops-but-newer-digest cases), exercising the real summarize()/commit() implementations rather than duplicating the logic.
  • packages/sdk/openapi.json and packages/sdk/js/src/v2/gen/types.gen.ts are the expected generated-artifact diffs for the new contract field.

No new issues found in the changed lines. The one active inline comment on a file touched by this diff (dialog-memory.tsx line 358, "Structured summary and raw tail... no label") is unrelated to the lines changed in this incremental diff and already has an "Addressed" reply from the author.

Files Reviewed (incremental diff: 11 files)
  • packages/kilo-memory/src/schema.ts
  • packages/kilo-memory/src/effect/service.ts
  • packages/kilo-memory/src/effect/httpapi.ts
  • packages/kilo-memory/src/autosave-status.ts
  • packages/kilo-memory/test/core.test.ts
  • packages/kilo-memory/test/decisions.test.ts
  • packages/kilo-memory/test/effect-capture.test.ts
  • packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-memory.tsx
  • packages/opencode/src/kilocode/cli/cmd/tui/component/memory-sidebar.tsx
  • packages/sdk/openapi.json (generated)
  • packages/sdk/js/src/v2/gen/types.gen.ts (generated)

Previous review (commit 78c98ac)

Status: No Issues Found | Recommendation: Merge

Incremental review against previous review commit 967fefe44f4efaed8aa0e53ce1d895ead93594e2, diffing 4 files / ~110 changed lines in packages/kilo-memory/. This is a small hardening pass that directly targets the 5 issues from the previous review round (2 WARNING, 3 SUGGESTION), all of which are now confirmed fixed against current code:

  • packages/kilo-memory/src/effect/capture.ts: the template-echo check now tests the raw, pre-fallback-substitution model summary (raw) instead of the post-substitution parsedDigest.summary, so a legitimate empty-summary response no longer gets misclassified as template_echo. A new explicit empty_digest reason now covers that case instead. A FALLBACK_RETRY_MS (60s) backoff was added so a fresh fallback digest is no longer retried against the model on every subsequent turn close — only once the fallback is older than the backoff window. Verified via two new tests (fresh fallback digest waits before retrying the digest model, empty digest output falls back and records empty_digest) that exercise the actual code path.
  • packages/kilo-memory/src/storage/sessions.ts: the Fallback: true marker scan is now scoped to lines.slice(0, idx) (the header block before ## Summary), matching where the marker is actually written, instead of scanning the whole file body.
  • packages/kilo-memory/src/capture/parse.ts: the misleading // already redacted trailing comment (on a line that performs the redaction) was replaced with an accurate comment.
  • packages/kilo-memory/test/effect-capture.test.ts: the secret-truncation-boundary test now sizes its padding off MemorySchema.maxStoredDigestSummary (4000) and reads back with the same bound, instead of a stale hardcoded 480/458, so the comment and assertions match the boundary the write path actually uses.

No new issues found in the changed lines.

Files Reviewed (incremental diff: 4 files)
  • packages/kilo-memory/src/capture/parse.ts
  • packages/kilo-memory/src/effect/capture.ts
  • packages/kilo-memory/src/storage/sessions.ts
  • packages/kilo-memory/test/effect-capture.test.ts

Previous review (commit 967fefe)

Status: 5 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 3

Incremental review against previous review commit a551bb982070b154e162e8af0825582e5b42688c, diffing 26 files / ~521 changed lines (kilo-owned packages/kilo-memory/ and packages/opencode/src/kilocode/ paths only). This diff is a hardening pass that fixes/verifies several previously-flagged secret-redaction concerns: MemoryOperations.secret() is now exported and used to filter secret-like add ops out of the persisted decisions log (memory.ts/memory-notice.ts/capture/outcome.ts), model-emitted skip text and remove-audit queries are now redacted before truncation, error messages are redacted before logging, and tool schema fields (text/key/sessionID) now have upper bounds. All of these fixes were verified against the actual persisted/audit code paths and hold up.

Two new issues were found in the newly-added "fallback digest" / "template echo" detection logic and one test:

Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-memory/src/effect/capture.ts 317 Template-echo detection checks the post-fallback-substitution summary, so a legitimate empty-summary response (no prior digest) gets misclassified as template_echo/fallback:true
packages/kilo-memory/test/effect-capture.test.ts 160 Test comment claims to validate a 480-char truncation boundary that isn't the boundary actually used by the write path (maxStoredDigestSummary = 4000); assertions pass for a trivial reason

SUGGESTION

File Line Issue
packages/kilo-memory/src/effect/capture.ts 163 No backoff cap once a digest enters fallback state — repeated failures ignore the interval throttle indefinitely and keep dropping prior context
packages/kilo-memory/src/capture/parse.ts 169 // already redacted trailing comment is misleading — this line performs the redaction, it doesn't confirm prior redaction
packages/kilo-memory/src/storage/sessions.ts 102 Fallback: true marker is scanned across the whole file body instead of being scoped to the header block
Files Reviewed (incremental diff: 26 files)
  • packages/kilo-memory/src/capture/digest-text.ts
  • packages/kilo-memory/src/capture/operations.ts
  • packages/kilo-memory/src/capture/outcome.ts
  • packages/kilo-memory/src/capture/parse.ts - 1 issue
  • packages/kilo-memory/src/capture/plan.ts
  • packages/kilo-memory/src/effect/capture.ts - 2 issues
  • packages/kilo-memory/src/effect/index.ts
  • packages/kilo-memory/src/effect/service.ts
  • packages/kilo-memory/src/effect/turn.ts
  • packages/kilo-memory/src/memory-notice.ts
  • packages/kilo-memory/src/memory.ts
  • packages/kilo-memory/src/prompts/session-digest.txt
  • packages/kilo-memory/src/recall/indexer.ts
  • packages/kilo-memory/src/recall/recall.ts
  • packages/kilo-memory/src/recall/shared.ts
  • packages/kilo-memory/src/schema.ts
  • packages/kilo-memory/src/storage/sessions.ts - 1 issue
  • packages/kilo-memory/src/tool.ts
  • packages/kilo-memory/test/capture.test.ts
  • packages/kilo-memory/test/core.test.ts
  • packages/kilo-memory/test/effect-capture.test.ts - 1 issue
  • packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-memory.tsx
  • packages/opencode/src/kilocode/cli/cmd/tui/component/memory-sidebar.tsx
  • packages/opencode/src/kilocode/memory/turn.ts
  • packages/opencode/test/kilocode/tool/memory-recall.test.ts
  • packages/opencode/test/kilocode/tool/memory-save.test.ts

Fix these issues in Kilo Cloud

Previous review (commit a551bb9)

Status: No Issues Found | Recommendation: Merge

Incremental review against previous review commit cd881dde7981a509e8ac8e910f66cd01b84ebde9. That commit is no longer an ancestor of current HEAD a551bb982070b154e162e8af0825582e5b42688c (branch was rebased/force-pushed again), but a tree diff between the two resolves cleanly to 4 files and matches the same effective change set.

All 4 previously flagged SUGGESTIONs are resolved in this diff:

  • packages/kilo-memory/src/marker-meta.ts: dead source !== "metadata" branch removed.
  • packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-memory.tsx: saved() no longer makes a redundant fallback computation; the duplicated "header" and "Sources" JSX blocks are now extracted into shared MemoryHeaderInfo/MemorySourcesInfo components used by both DialogMemoryStatus and DialogMemory.
  • packages/opencode/src/kilocode/cli/cmd/tui/memory-command.ts: a new test now exercises the bare /memory"help" dispatch branch, asserting input.usage() is called.

Additionally, memory-command.ts's edit() now trims $VISUAL/$EDITOR before checking it's set, resolving a previously open review thread about whitespace-only env values bypassing the "not set" guard.

No new issues found in the changed lines.

Files Reviewed (incremental diff: 4 files)
  • packages/kilo-memory/src/marker-meta.ts
  • packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-memory.tsx
  • packages/opencode/src/kilocode/cli/cmd/tui/memory-command.ts
  • packages/opencode/test/kilocode/cli/cmd/tui/memory-command.test.ts

Previous review (commit cd881dd)

Status: 4 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 4

Incremental review against the previous review commit 914ebf5f2d274a7a319c5eb633b2dc2bf9f4fd7e. That commit is no longer an ancestor of current HEAD cd881dde7981a509e8ac8e910f66cd01b84ebde9 (branch was rebased/force-pushed), but a tree diff between the two still resolves cleanly to 17 files, all under packages/kilo-memory/ and packages/opencode/src/kilocode/, and matches the same effective change set (refactor(memory): shared client helpers, capture hardening, /memory UX rework).

All new findings are low-severity SUGGESTIONs; no correctness bugs, security issues, or unhandled error paths were found in the changed lines. Highlights:

  • kilo-memory/src/marker-meta.ts: a defensive source !== "metadata" check has no current producer that would ever trigger it — likely dead code.
  • dialog-memory.tsx: saved() computes MemoryAutosaveStatus.summarize() but both ternary branches resolve to the same underlying stat, making the call redundant; the new DialogMemoryStatus component also duplicates the header/root and "Sources" JSX blocks already present in DialogMemory byte-for-byte.
  • memory-command.ts: the new "help" dispatch branch (split out of the old "inspect" kind) has no test asserting it actually calls input.usage() for a bare /memory command.

Verified as correct / no new issues in this diff:

  • kilo-memory/src/decisions.ts, autosave-status.ts: new audit/status summarizers correctly omit raw skipped[].text and reuse the already-redacted MemoryAudit.audit() write path — no secret leakage into the new TUI-facing summaries.
  • kilo-memory/src/commands.ts: catalog-driven MEMORY_COMMAND_CATALOG/MEMORY_USAGE derivation, on/offenable/disable mapping, and the inspecthelp/show split are all consistent with the updated memory-command.ts consumer and covered by updated fixtures/tests.
  • dialog-memory.tsx: the previously-flagged hardcoded "startup context on" text is now correctly conditional on autoInject in both dialog variants.
  • memory-sidebar.tsx, memory-prompt.tsx: delegate cleanly to the new shared MemoryAutosaveStatus.summarize; existing catch block already logs via errorMessage.
  • memory-command.ts, memory-meta.ts: "auto" operation refactor and delegation to MemoryMarkerMeta.fromParts preserve prior behavior; new "status" dispatch test covers the intended no-network-call behavior.
  • memory/marker.ts, plugins/memory-palette.tsx: field-rename (files/sources) and memory.showmemory.help palette rework are applied consistently within these files.
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/kilo-memory/src/marker-meta.ts 47 Dead defensive branch — no producer ever writes source=metadata
packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-memory.tsx 26 saved()'s summarize() call is redundant — both ternary branches resolve to the same value
packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-memory.tsx 205 "Sources" block (and header above it) duplicated byte-for-byte between DialogMemoryStatus and DialogMemory
packages/opencode/src/kilocode/cli/cmd/tui/memory-command.ts 93 No test exercises the new "help" kind branch
Files Reviewed (incremental diff: 17 files)
  • packages/kilo-memory/package.json
  • packages/kilo-memory/src/autosave-status.ts
  • packages/kilo-memory/src/commands.ts
  • packages/kilo-memory/src/decisions.ts
  • packages/kilo-memory/src/index.ts
  • packages/kilo-memory/src/marker-meta.ts - 1 issue
  • packages/kilo-memory/test/command-cases.json
  • packages/kilo-memory/test/commands.test.ts
  • packages/kilo-memory/test/decisions.test.ts
  • packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-memory.tsx - 2 issues
  • packages/opencode/src/kilocode/cli/cmd/tui/component/memory-prompt.tsx
  • packages/opencode/src/kilocode/cli/cmd/tui/component/memory-sidebar.tsx
  • packages/opencode/src/kilocode/cli/cmd/tui/memory-command.ts - 1 issue
  • packages/opencode/src/kilocode/cli/cmd/tui/memory-meta.ts
  • packages/opencode/src/kilocode/memory/marker.ts
  • packages/opencode/src/kilocode/plugins/memory-palette.tsx
  • packages/opencode/test/kilocode/cli/cmd/tui/memory-command.test.ts

Fix these issues in Kilo Cloud

Previous review (commit 914ebf5)

Status: No Issues Found | Recommendation: Merge

Overview

Incremental review against the previous review commit 4cee27bc6b873b25e2c49bbd16598e85f55ca734 (valid ancestor of current HEAD 914ebf5f2d274a7a319c5eb633b2dc2bf9f4fd7e). The incremental diff touches 11 files, all in packages/kilo-memory/ and packages/opencode/src/kilocode/.

Changes verified as correct, tested fixes / refactors with no new issues:

  • capture/operations.ts, capture/outcome.ts: adds MemoryOperations.id() as the single canonical id builder (file/heading/slugified-key), and switches the exact-key upsert check in duplicateOps to use it instead of a raw, unnormalized template string. Confirmed this now correctly matches the id format already used for stored inventory items (MemoryShared.source's ${file}:${section}:${key}), fixing the case/whitespace mismatch from the prior trimming-inconsistency suggestion. Covered by a new test (capture.test.ts).
  • capture/parse.ts: salvageTyped now throws when the decoded root has no operations array (previously silently treated as an empty batch). Verified the sole caller (effect/capture.ts) already wraps this call in Effect.try + Effect.catch, logging a parse_error and returning a safe fallback — no unhandled failure path introduced. Covered by a new test.
  • kilo-memory/src/tool.ts, opencode/.../memory/marker.ts, and both touched test files: renames tool-metadata field files -> sources (to avoid colliding with opencode's apply_patch-specific stripPartMetadata handling of metadata.files). Verified every producer/consumer of this field was updated consistently (marker.ts, memory-integration.test.ts, memory-recall.test.ts), and confirmed no memory-specific UI reads the old metadata.files key elsewhere in the tree — remaining metadata.files references in the codebase all belong to the unrelated apply_patch tool.
  • tool.ts: input.memory.status({root}).state calls replaced with a direct input.memory.state({root}); confirmed state is an existing, separate MemoryService interface method (not a renamed one), so this is a simplification, not a behavior change.
  • TUI dedup (dialog-memory.tsx, memory-sidebar.tsx, memory-command.ts): local msg()/route()/relative-time/token-compaction helpers replaced with shared errorMessage (@/util/error), a single exported route() in memory-command.ts, relativeTime (existing shared TUI util), and Locale.number. This addresses the previously open review comments about ad-hoc error formatting and duplicated route() helpers, and reduces kilocode-owned code duplication without touching shared upstream files.

Two previously-flagged items from the prior review remain open and untouched by this diff (confirmed unchanged at their current lines), so they are left on their existing threads rather than re-reported:

  • packages/opencode/src/kilocode/memory/ports.ts (line 23): output()'s plain-text branch still forwards unredacted assistant text to the consolidation model call.
  • packages/opencode/src/kilocode/cli/cmd/tui/memory-command.ts (line 53): whitespace-only $VISUAL/$EDITOR still bypasses the !editor guard.
Files Reviewed (incremental diff: 11 files)
  • packages/kilo-memory/src/capture/operations.ts
  • packages/kilo-memory/src/capture/outcome.ts
  • packages/kilo-memory/src/capture/parse.ts
  • packages/kilo-memory/src/tool.ts
  • packages/kilo-memory/test/capture.test.ts
  • packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-memory.tsx
  • packages/opencode/src/kilocode/cli/cmd/tui/component/memory-sidebar.tsx
  • packages/opencode/src/kilocode/cli/cmd/tui/memory-command.ts
  • packages/opencode/src/kilocode/memory/marker.ts
  • packages/opencode/test/kilocode/memory/memory-integration.test.ts
  • packages/opencode/test/kilocode/tool/memory-recall.test.ts

Previous review (commit 4cee27b)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Branch history was rewritten again since the last review (the prior base 4ef1eacd7 is no longer a valid ref against current HEAD 4cee27bc6), so per the fallback rule this review re-examined the full PR diff against main's merge base (confirmed via local git diff mainref..pr11921head, matching gh pr diff --name-only's 91-file list). Cross-checked against GitHub's live comment/review state (81 prior comments, all with Addressed/discussion replies).

Of the previously-open items carried from the last review round (topics.ts corpus threshold, redact.ts plural-keyword regression, redact.ts colon-separated low-entropy secrets, reject.ts clause-boundary punctuation, parse.ts salvageText empty-field precedence, indexer.ts redundant covered() computation + uncapped coveredDigests, httpapi.ts payload length caps, memory-save.ts misleading config-file copy), all were independently re-verified against the current code and are now genuinely fixed.

One previously-flagged item is only partially fixed: packages/opencode/src/kilocode/memory/ports.ts's chat-transcript redaction gap (existing thread, line 23) — text() (user turns) now correctly redacts via MemoryRedact.text(), but output()'s plain-text branch (used for TurnView.assistant, i.e. the model's own prior replies) still forwards raw, unredacted text to the memory-consolidation model call. Flagging for continued tracking on the existing thread rather than duplicating.

One new issue was found in this round, in a file not previously reviewed in depth: the new /memory edit command's whitespace-only-$EDITOR guard gap in memory-command.ts.

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 1
Issue Details (click to expand)

WARNING

File Line Issue
packages/opencode/src/kilocode/memory/ports.ts 23 (existing thread) output()'s plain-text branch still forwards unredacted assistant text into TurnView.assistant for the consolidation model call; only text() (user side) was fixed

SUGGESTION

File Line Issue
packages/opencode/src/kilocode/cli/cmd/tui/memory-command.ts 60 Whitespace-only $VISUAL/$EDITOR passes the !editor guard, then splitCommand returns [], so the memory file path itself becomes cmd[0] and is spawned as the "editor"
Files Reviewed (full PR: 91 files)
  • packages/kilo-memory/src/capture/*.ts, effect/*.ts, recall/*.ts, schema.ts, storage/paths.ts, tool.ts, memory.ts — all previously-flagged items verified fixed in current code (redaction ordering/coverage, regex boundaries, byte-safe truncation, stats gating, corpus threshold, indexer dedup/cap)
  • packages/opencode/src/kilocode/memory/ports.ts — 1 issue partially unresolved (see WARNING above); let reason/let source style suggestion remains open on existing thread (unaddressed, not re-reported)
  • packages/opencode/src/kilocode/memory/{runtime,turn,events,marker}.ts — no new issues; lifecycle/subscription cleanup and error logging verified correct
  • packages/opencode/src/kilocode/tool/{memory-save,memory-recall,registry}.ts, packages/opencode/src/tool/registry.ts — no new

[Snapshot truncated.]

Additional previous summary content was truncated to keep this comment within platform limits.


Reviewed by claude-sonnet-5-20260630 · Input: 26 · Output: 4.9K · Cached: 578.9K

Review guidance: REVIEW.md from base branch main

@johnnyeric
johnnyeric force-pushed the johnnyeric/kilo-memory-cli branch from 61543e1 to 7219abb Compare July 5, 2026 13:44
Comment thread packages/kilo-memory/src/storage/paths.ts Outdated
Comment thread packages/opencode/src/kilocode/cli/cmd/tui/memory-command.ts Outdated
@johnnyeric
johnnyeric force-pushed the johnnyeric/kilo-memory-cli branch 4 times, most recently from 26ac254 to 380231c Compare July 5, 2026 14:52
Comment thread packages/kilo-memory/src/capture/redact.ts Outdated
Comment thread packages/kilo-memory/src/capture/reject.ts Outdated
Comment thread packages/kilo-memory/src/capture/parse.ts Outdated
Comment thread packages/kilo-memory/src/recall/indexer.ts Outdated
Comment thread packages/kilo-memory/src/effect/httpapi.ts Outdated
Comment thread packages/kilo-memory/src/effect/capture.ts Outdated
Comment thread packages/opencode/src/kilocode/tool/memory-save.ts
Comment thread packages/opencode/src/tool/registry.ts Outdated
@johnnyeric
johnnyeric force-pushed the johnnyeric/kilo-memory-cli branch from 380231c to 70cb07c Compare July 5, 2026 15:40
Comment thread packages/kilo-memory/src/recall/topics.ts Outdated
@johnnyeric
johnnyeric force-pushed the johnnyeric/kilo-memory-cli branch 2 times, most recently from 4e33bca to 8fcb796 Compare July 5, 2026 16:04
@johnnyeric
johnnyeric force-pushed the johnnyeric/kilo-memory-cli branch 2 times, most recently from cf5b764 to c2a50e0 Compare July 5, 2026 16:15
…gration

Add project memory: the standalone @kilocode/kilo-memory effect layer plus the
opencode CLI/server/TUI integration. Memory is disabled by default, so it is a
no-op until enabled (no behavior change when off).

Capture (turn-close consolidation): per-op parse salvage, secret redaction that
skips the offending op instead of aborting the batch, supersede-only auto-updates
(never model-driven deletes), correction-aware echo handling, non-LLM fallback
digests on interrupted/error turns, a shared interval throttle with idle-flush.

Recall + injection: keyword tokenizer with camelCase/compound splitting, light
stemming, and an English-first stopword filter (Unicode-aware; non-English falls
back to plain token-overlap), a live relevance floor, a budget-reserved startup
index, a session-digest catalog, and per-session prompt-cache pinning of the
injected memory block.

Surfaces: kilo_memory_save / kilo_memory_recall tools, the memory HTTP API
(contract schemas live in the package), and a status-focused TUI sidebar showing
auto-save, loaded context, and active recall, plus the /memory dialog.
@johnnyeric
johnnyeric force-pushed the johnnyeric/kilo-memory-cli branch 5 times, most recently from 4ef1eac to 08bcde9 Compare July 5, 2026 16:58
- C1: bump @kilocode/kilo-memory in the changeset
- C2: redact secrets before they hit the audit log (skip + salvage paths);
  redact before truncating in salvageTyped so a secret straddling the
  500-char cap can't leak an unmatched fragment; opText -> salvageText
- C3: de-abbreviate savedOperations, "changes" wording, ops.ts -> operations.ts
- C4: log.warn on the remaining silent-catch fallbacks (turn diff, memory
  context injection, tool-visibility check)
- C5: relocate memory storage from ~/.kilo to Global.Path.data, delete the
  now-dead needsDependencyInstall guard, add /memory status (root path) and
  /memory edit ($VISUAL/$EDITOR + auto-rebuild)
- C6: replace the hardcoded English stopword list with corpus-derived
  ubiquitous-term filtering (df across the user's own entries) and the
  English suffix stemmer with suffix-tolerant term matching, so recall
  noise-filtering works in any language
- C8: delete the CORRECTION_INTENT English regex; echo turns now run typed
  capture (digest stays echo-gated), bounded by the interval throttle, with
  the typed prompt as the language-agnostic content filter
- C9: exclude generated paths (dist/build/coverage/*.gen.*/*.map/snapshots)
  from the durable-diff churn fallback so generated churn can't burn a
  consolidation call
- C11: fix duplicated assert in httpapi-memory test; assert the error body
- kilo-code-bot batch: clause-boundary regex fix, byte-safe catalog
  truncation, max-length guards on remember/correct/forget payloads (text,
  query, key, sessionID), trim consistency in reconcile, param-shadowing
  rename, missing doc entry for kilo_memory_recall, dead-code removal,
  dialog UI fixes, memoryEnabledCache eviction bound, dedicated Configure
  schema, recall permission renderer, covered-session pointer cap, redact
  chat transcript before the consolidation model call, split configProtected
  metadata from disableAlways so memory-save prompts don't show config-file
  copy, drop unused MemoryService.layer provide from tool registry
- redact colon-separated low-entropy secrets too (password: hunterx),
  accepting the prose false-positive tradeoff (secret: enabled) in favor of
  not missing a real secret
- rename lastConsolidatedAt -> lastTypedConsolidationAt to make its narrow
  scope (typed-consolidation throttle clock) explicit; regen openapi/SDK
- drop now-dead home/config fields from MemoryPaths.Host after the data-dir
  relocation; add Process.splitCommand for quoted $EDITOR/$VISUAL paths with
  spaces, used by /memory edit and the pre-existing Editor.open utility
@johnnyeric
johnnyeric force-pushed the johnnyeric/kilo-memory-cli branch from 08bcde9 to 4cee27b Compare July 5, 2026 17:05
Comment thread packages/opencode/src/kilocode/cli/cmd/tui/memory-command.ts
@johnnyeric
johnnyeric force-pushed the johnnyeric/kilo-memory-cli branch from 914ebf5 to cd881dd Compare July 5, 2026 18:05
Comment thread packages/kilo-memory/src/marker-meta.ts Outdated
Comment thread packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-memory.tsx Outdated
Comment thread packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-memory.tsx Outdated
Comment thread packages/opencode/src/kilocode/cli/cmd/tui/memory-command.ts
@johnnyeric
johnnyeric force-pushed the johnnyeric/kilo-memory-cli branch from cd881dd to a551bb9 Compare July 5, 2026 18:33
@johnnyeric
johnnyeric force-pushed the johnnyeric/kilo-memory-cli branch 2 times, most recently from 1223d2c to 967fefe Compare July 5, 2026 19:45
Comment thread packages/kilo-memory/src/effect/capture.ts Outdated
Comment thread packages/kilo-memory/src/effect/capture.ts Outdated
Comment thread packages/kilo-memory/src/capture/parse.ts Outdated
Comment thread packages/kilo-memory/src/storage/sessions.ts Outdated
Comment thread packages/kilo-memory/test/effect-capture.test.ts Outdated
@johnnyeric
johnnyeric force-pushed the johnnyeric/kilo-memory-cli branch from 967fefe to 78c98ac Compare July 5, 2026 22:52
@johnnyeric
johnnyeric force-pushed the johnnyeric/kilo-memory-cli branch from 78c98ac to b98e0d6 Compare July 6, 2026 12:12
…X rework

- extract client-side derivations into kilo-memory so both frontends share
  one implementation: MemoryDecisions.summarize (decision-log summary),
  MemoryAutosaveStatus.summarize (autosave-status semantics), and
  MemoryMarkerMeta (marker wire contract encode/decode)
- match exact-key upserts via the canonical stored id (slugged key,
  normalized section) so a re-emitted spaced/uppercase key updates the
  entry instead of falling to fuzzy dedupe
- salvageTyped throws on valid JSON without an operations array so the
  caller's fallback path records a parse error instead of a silent
  zero-op success
- rename memory tool metadata files -> sources (stripPartMetadata rewrites
  tool-part metadata.files assuming apply_patch records, mangling string[])
- read state instead of status for tool enabled checks; dedupe TUI helpers
  (errorMessage, shared route(), Locale.number, relativeTime)
- /memory UX: bare /memory opens a help modal driven by a structured
  command catalog in kilo-memory; /memory on|off become the canonical
  toggle verbs (enable/disable kept as quiet aliases); /memory status opens
  a clean overview dialog (root path, autosave, startup context, source
  counts, index size) instead of a toast; /memory show is the single full
  audit view (inspect removed)
@johnnyeric
johnnyeric force-pushed the johnnyeric/kilo-memory-cli branch from b98e0d6 to 91de774 Compare July 6, 2026 12:23
@johnnyeric
johnnyeric merged commit b976b5a into main Jul 6, 2026
27 checks passed
@johnnyeric
johnnyeric deleted the johnnyeric/kilo-memory-cli branch July 6, 2026 15:45
t7tran pushed a commit to t7tran/kilocode that referenced this pull request Aug 14, 2026
t7tran pushed a commit to t7tran/kilocode that referenced this pull request Aug 14, 2026
* feat(memory): opt-in project memory — capture, recall, CLI + TUI integration

Add project memory: the standalone @kilocode/kilo-memory effect layer plus the
opencode CLI/server/TUI integration. Memory is disabled by default, so it is a
no-op until enabled (no behavior change when off).

Capture (turn-close consolidation): per-op parse salvage, secret redaction that
skips the offending op instead of aborting the batch, supersede-only auto-updates
(never model-driven deletes), correction-aware echo handling, non-LLM fallback
digests on interrupted/error turns, a shared interval throttle with idle-flush.

Recall + injection: keyword tokenizer with camelCase/compound splitting, light
stemming, and an English-first stopword filter (Unicode-aware; non-English falls
back to plain token-overlap), a live relevance floor, a budget-reserved startup
index, a session-digest catalog, and per-session prompt-cache pinning of the
injected memory block.

Surfaces: kilo_memory_save / kilo_memory_recall tools, the memory HTTP API
(contract schemas live in the package), and a status-focused TUI sidebar showing
auto-save, loaded context, and active recall, plus the /memory dialog.

* fix(memory): address PR review feedback

- C1: bump @kilocode/kilo-memory in the changeset
- C2: redact secrets before they hit the audit log (skip + salvage paths);
  redact before truncating in salvageTyped so a secret straddling the
  500-char cap can't leak an unmatched fragment; opText -> salvageText
- C3: de-abbreviate savedOperations, "changes" wording, ops.ts -> operations.ts
- C4: log.warn on the remaining silent-catch fallbacks (turn diff, memory
  context injection, tool-visibility check)
- C5: relocate memory storage from ~/.kilo to Global.Path.data, delete the
  now-dead needsDependencyInstall guard, add /memory status (root path) and
  /memory edit ($VISUAL/$EDITOR + auto-rebuild)
- C6: replace the hardcoded English stopword list with corpus-derived
  ubiquitous-term filtering (df across the user's own entries) and the
  English suffix stemmer with suffix-tolerant term matching, so recall
  noise-filtering works in any language
- C8: delete the CORRECTION_INTENT English regex; echo turns now run typed
  capture (digest stays echo-gated), bounded by the interval throttle, with
  the typed prompt as the language-agnostic content filter
- C9: exclude generated paths (dist/build/coverage/*.gen.*/*.map/snapshots)
  from the durable-diff churn fallback so generated churn can't burn a
  consolidation call
- C11: fix duplicated assert in httpapi-memory test; assert the error body
- kilo-code-bot batch: clause-boundary regex fix, byte-safe catalog
  truncation, max-length guards on remember/correct/forget payloads (text,
  query, key, sessionID), trim consistency in reconcile, param-shadowing
  rename, missing doc entry for kilo_memory_recall, dead-code removal,
  dialog UI fixes, memoryEnabledCache eviction bound, dedicated Configure
  schema, recall permission renderer, covered-session pointer cap, redact
  chat transcript before the consolidation model call, split configProtected
  metadata from disableAlways so memory-save prompts don't show config-file
  copy, drop unused MemoryService.layer provide from tool registry
- redact colon-separated low-entropy secrets too (password: hunterx),
  accepting the prose false-positive tradeoff (secret: enabled) in favor of
  not missing a real secret
- rename lastConsolidatedAt -> lastTypedConsolidationAt to make its narrow
  scope (typed-consolidation throttle clock) explicit; regen openapi/SDK
- drop now-dead home/config fields from MemoryPaths.Host after the data-dir
  relocation; add Process.splitCommand for quoted $EDITOR/$VISUAL paths with
  spaces, used by /memory edit and the pre-existing Editor.open utility

* refactor(memory): shared client helpers, capture hardening, /memory UX rework

- extract client-side derivations into kilo-memory so both frontends share
  one implementation: MemoryDecisions.summarize (decision-log summary),
  MemoryAutosaveStatus.summarize (autosave-status semantics), and
  MemoryMarkerMeta (marker wire contract encode/decode)
- match exact-key upserts via the canonical stored id (slugged key,
  normalized section) so a re-emitted spaced/uppercase key updates the
  entry instead of falling to fuzzy dedupe
- salvageTyped throws on valid JSON without an operations array so the
  caller's fallback path records a parse error instead of a silent
  zero-op success
- rename memory tool metadata files -> sources (stripPartMetadata rewrites
  tool-part metadata.files assuming apply_patch records, mangling string[])
- read state instead of status for tool enabled checks; dedupe TUI helpers
  (errorMessage, shared route(), Locale.number, relativeTime)
- /memory UX: bare /memory opens a help modal driven by a structured
  command catalog in kilo-memory; /memory on|off become the canonical
  toggle verbs (enable/disable kept as quiet aliases); /memory status opens
  a clean overview dialog (root path, autosave, startup context, source
  counts, index size) instead of a toast; /memory show is the single full
  audit view (inspect removed)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants