v1.16.0

Gentleman-Programming/engramv1.16.0May 28, 2026by Alan-TheGentleman

Upgrading?

Release notes summary

A major release focusing on security hardening (HTTP auth, constant-time comparisons), CLI enhancements (delete sub-commands), TUI improvements (clipboard copy), search capabilities (cross-project, case-insensitive), and cloud/Pi configuration updates.

Key Highlights

  • Opt-in HTTP auth for destructive endpoints (`ENGRAM_HTTP_TOKEN`)
  • CLI `engram delete` now supports sub-commands
  • TUI clipboard shortcut (`c` key) added
  • Cross-project personal search and case-insensitive legacy project matching

New Features

  • Optional local auth for destructive HTTP endpoints
  • Constant-time token comparisons
  • Obsidian exporter path traversal fix
  • TUI clipboard copy via OSC 52
  • Cross-project search (`all_projects: true`)
  • Configurable timestamp display (`ENGRAM_TIMEZONE`)
  • Cloud allowlist wildcard support
  • Pi setup hardening
  • Wholesale docs refresh

Full Release Notes

Engram v1.16.0 lands a broad, high-impact wave of fixes and features: opt-in HTTP auth and constant-time token comparisons, new CLI delete sub-commands, a TUI clipboard shortcut, cross-project personal search, case-insensitive legacy project matching, a cloud allowlist wildcard, Pi setup hardening, and a wholesale docs refresh. Multiple external contributors and issue reporters drove this release.

## Highlights

### Security

- **Optional local auth for destructive HTTP endpoints** (`ENGRAM_HTTP_TOKEN`): when set, `DELETE /sessions/{id}`, `DELETE /observations/{id}`, `DELETE /prompts/{id}`, `GET /export`, `POST /import`, and `POST /projects/migrate` require `Authorization: Bearer <token>`. Unset = open (zero-config preserved). Constant-time compare via `hmac.Equal`.
- **Constant-time token comparisons**: bearer and admin token checks in `internal/cloud/auth` and `cloudserver` use `hmac.Equal` instead of `==`/`!=`, eliminating the timing-oracle.
- **Obsidian exporter path traversal**: `internal/obsidian/exporter.go` sanitizes project and type components before `filepath.Join` and adds a post-join containment check, rejecting any path that escapes the export root.

### CLI

- **`engram delete`** now supports sub-commands: `delete observation <id>`, `delete session <id>`, `delete prompt <id>`, and `delete project <name>`. All accept `--hard`. The legacy `engram delete <obs_id>` form still works.
- **`store.DeleteProject`** atomic cascade: orphans `memory_relations`, removes observations (soft or hard), prompts, and sessions (hard only — the FK constraint blocks session removal while soft-deleted observations still reference them).

### TUI

- **`c` keybinding copies the highlighted observation to the clipboard** via OSC 52 on Recent Observations, Search Results, Observation Detail, and Session Detail. Works over SSH, no system deps.

### Search and scopes

- **`mem_search` accepts `all_projects: true`** to search every project at once instead of the resolved one.
- **`scope=personal` without an explicit project** now searches personal observations across all projects (`mem_search`, `mem_context`).
- **`global` is a valid scope** alongside `project` and `personal` (was silently coerced to `project`).
- **Legacy mixed-case project data is now searchable**: store queries use `LOWER(project) = ?` so observations stored as `Ebook2Audio` are found when queried as `ebook2audio` — the MCP path normalizes; the CLI was the only path that happened to work before.
- **Configurable timestamp display**: `ENGRAM_TIMEZONE` sets the display timezone for the TUI and the cloud dashboard. Falls back to system local; UTC is preserved in storage.

### Cloud

- **`ENGRAM_CLOUD_ALLOWED_PROJECTS` accepts `*`** to allow every project (per-project enforcement bypassed). Useful for dev and internal deploys.
- **`sync --cloud` sends the Authorization header** when only `cloud.json` carries the token: `resolveCloudRuntimeConfig` no longer zeroes the file token before reading the env var.
- **`cloud status` detects a dead local daemon** with a 1-second probe and prints actionable guidance; the launchd unit template is documented.

### MCP

- **`handleSessionSummary` hardened**: it now respects the process-level project override (`ENGRAM_PROJECT` / `engram mcp --project`) consistent with every other write tool, and rejects empty or whitespace-only content before `AddObservation`. This fixes stuck `sync_mutation` rows that blocked `cloud upgrade`.

### Windows

- **`CLAUDE_PLUGIN_ROOT` is escape-quoted** in every `hooks.json` command entry, so all Claude Code hooks fire on profile paths containing spaces (e.g. `C:\Users\John Doe\...`).

### Pi

- **`engram setup pi` pins `npmCommand`** to a mise-stable form (`["mise","exec","node@X.Y.Z","--","npm"]`) when mise is detected and no command is configured, preventing duplicate installs when Node drifts. Existing values are preserved.
- **Pi status bar maps `ambiguous_project`** to an actionable label instead of the generic `error`.

### Docs

- Wholesale sync: the `DOCS.md` environment-variables table went from 3 to 17 rows; `printUsage()` env block synced with code; CLI reference tables in `README.md` and `docs/ARCHITECTURE.md` now include `doctor`, `conflicts`, `delete`, and `projects prune`; Codex troubleshooting for "MCP Transport closed" was added; the new `ENGRAM_HTTP_TOKEN`, `ENGRAM_TIMEZONE`, `scope=personal` cross-project behavior, `global` scope, `*` cloud wildcard, and Pi `npmCommand` pinning are all documented.

## Contribution highlights

Thanks to the external contributors and issue reporters who shaped this release:

- **@carlosmoradev** shipped #408 (`all_projects` flag for `mem_search`), #346 (configurable timezone), and #410 (install-from-source version-stamp docs).
- **@jlsevillano** shipped #337 (dead-daemon detection in `cloud status` and launchd documentation).
- Issue reports that drove targeted fixes: #180 (Obsidian path traversal), #200 (HTTP auth), #350 (constant-time compare), #260 (cloud wildcard), #146 (MCP search empty for legacy data), #391 (personal-scope filter), #403, #413, #393 (`handleSessionSummary` gaps), #122 (`global` scope), #343 (`sync --cloud` auth header), #209, #218, #219 (CLI delete), #141 (TUI copy), #420 (Windows hooks quoting), #385 (Pi `npmCommand`), #384 (Pi status bar), #167 (Codex docs).

## Pi companion notes

No new `gentle-engram` npm package was published in this release. The current Pi companion remains `gentle-engram@0.1.7`; this release updates the main Engram binary, the Pi setup logic in `engram setup pi`, and the Pi documentation.

## Changelog

- #443 `docs(codex): add troubleshooting for MCP Transport closed error` (closes #167)
- #442 `fix(plugin): quote CLAUDE_PLUGIN_ROOT in hooks for paths with spaces` (closes #420)
- #441 `feat(store,cli): cascade DeleteProject + engram delete session|prompt|project` (closes #218, #219)
- #439 `fix(pi): show actionable status for ambiguous project errors` (closes #384)
- #436 `docs: bring docs up to date with recently merged features` (closes #435)
- #434 `feat(cli): add engram delete command to remove observations` (closes #209)
- #433 `feat(tui): add clipboard copy keybinding via OSC 52` (closes #141)
- #432 `fix(pi): pin npmCommand to stable mise node spec` (closes #385)
- #431 `feat(cloud): wildcard support for ENGRAM_CLOUD_ALLOWED_PROJECTS` (closes #260)
- #430 `fix(cloud): fall back to cloud.json token when ENGRAM_CLOUD_TOKEN is unset` (closes #343)
- #429 `security(server): add optional local auth for destructive HTTP endpoints` (closes #200)
- #428 `fix(store): handle global scope in normalizeScope` (closes #122)
- #427 `fix(store): use case-insensitive project filter for legacy mixed-case data` (closes #146)
- #426 `fix(security): replace timing-unsafe token comparisons with hmac.Equal` (closes #350)
- #425 `fix(mcp): skip project filter for scope=personal with no explicit project` (closes #391)
- #424 `fix(mcp): harden handleSessionSummary process override and empty-content guard` (closes #403, #413, #393)
- #423 `fix(obsidian): prevent path traversal in exporter file path construction` (closes #180)
- #410 `docs: clarify version stamp PATH gotcha and Claude Code schema error` (closes #67)
- #408 `feat(mcp): add all_projects flag to mem_search` (closes #303)
- #346 `feat(timeutil): support configurable timezone for timestamp display` (closes #169)
- #337 `feat(cloud): detect dead local daemon in cloud status and document launchd unit` (closes #279)

Related Repositories