4.0 KiB
Changelog
1.4.2
Fixed — CoWork sandbox plugin-path resolution
In a remote CoWork sandbox, ${CLAUDE_PLUGIN_ROOT} can resolve to a host path the
sandbox can't reach (e.g. /var/folders/…), while the plugin is actually mounted under
…/mnt/.remote-plugins/…. Every python3 "${CLAUDE_PLUGIN_ROOT}/…" invocation then
failed until the agent manually located the real path. (Root cause is the harness env
var, not the plugin — the scripts always used the variable correctly, never a hardcoded
path — but the plugin now self-heals.)
- SKILL.md and all eight slash commands resolve the scripts path with a fallback:
prefer
${CLAUDE_PLUGIN_ROOT}, else locate the copy under/sessions/*/mnt/.remote-plugins/*/skills/echo-memory/scripts/. Reused via$ECHO/$LINT/$SWEEP/$SDIR; on a normal host the primary path always wins, so behaviour is unchanged. echo-health/echo-sweepallowed-toolsbroadened to match the resolved (variable-dir) invocation and thels/dirnameresolver steps.
1.4.1
Fixed — baked credentials now win unconditionally
A per-user baked artifact could still be prompted for credentials on install. The
baked DEFAULT_* tier was lowest priority, so a stale ECHO_* env var or a
leftover/placeholder ~/.claude/echo-memory/config.json shadowed the baked key —
even an unedited "<placeholder>" value won over it, flipping is_configured() to
false and triggering the first-run "ask the operator" flow despite valid baked creds.
echo_config.load()now treats a complete baked set (endpoint + key both present) as authoritative: it wins over env vars and the config file and cannot be shadowed. The generic (unbaked) plugin keeps its env → file → first-run flow.- Added
baked_complete();source()reportsbaked-in (plugin)for that tier.
Security — untracked leaked baked artifacts
- Two labeled baked artifacts (
echo-memory-1.4.0-jason.plugin,echo-memory-1.4.0-gretchen.plugin), each carrying a live vault bearer token, had been committed at the repo root. They are nowgit rm --cached-removed and.gitignoregainsecho-memory-*-*.pluginso labeled builds can't be re-committed (the version-only pointerecho-memory.pluginandecho-memory-<ver>.pluginstay tracked). Tokens remain in prior history — rotate if the repo was ever shared.
1.4.0
Added — per-user baked-key builds (CoWork zero-touch)
The plugin is the only thing reliably mounted into a CoWork session (the sandbox's
~/.claude is synthetic, not your real one), so the config now can travel inside
the artifact. echo_config gains a lowest-priority fallback tier — the
DEFAULT_OWNER / DEFAULT_BASE / DEFAULT_KEY constants — empty in source, so
the committed tree still ships zero credentials.
build.py --bake-key --from <config.json> [--label <name>]substitutes a single user's owner/endpoint/key into those constants, producing a per-user artifact that needs no config file and no per-session paste. Values may also come from--owner/--endpoint/--keyorECHO_OWNER/ECHO_BASE/ECHO_KEY.- Baked builds default to
dist/(gitignored) and never touch the sharedecho-memory.pluginpointer. build.py --strip-keynow force-blanks the same constants (guaranteed token-free).config show/doctorreport[baked-in default]when a field resolves from the baked tier.
Changed — artifact hygiene
.gitignoreexcludesdist/and the filled-inecho-memory.config.json, where baked builds and the key file are meant to live. A baked artifact carries a vault key and must be delivered directly to that one user, never committed, pushed, or published. (Note: labeled baked artifacts built at the repo root were not yet guarded — see 1.4.1.)
Resolution order (unchanged for hosts)
env → $ECHO_CONFIG file → canonical ~/.claude/echo-memory/config.json →
baked DEFAULT_*. On a normal desktop the empty defaults mean behaviour is
identical to 1.3.x; the baked tier only matters in per-user artifacts.