---
name: echo-memory
description: Use Jason's ECHO Obsidian vault as persistent memory in Codex. Use whenever Jason asks to remember, save, note, log, capture, recall, load profile/context, check prior notes, triage the ECHO inbox, run vault health, or pick up previous work. Also use proactively at the start of substantive work sessions to load context and at the end to log outcomes. Do not use for unrelated local-file lookup, email lookup, timed reminders, generic second-brain advice, memory meaning RAM, or another person's vault.
---

# ECHO Memory

Use the **ECHO** Obsidian vault as Jason's persistent memory across Codex sessions. The vault is accessed through the Obsidian Local REST API at `https://echoapi.alwisp.com`.

This Codex port keeps the existing ECHO vault contract, routing map, scaffold, and safety rules, but the executable runtime is Python-first so it works in Codex on Windows without `/bin/bash`.

## Required Environment

Set `ECHO_KEY` in the environment before any live vault operation. The plugin intentionally does not ship a bearer token.

Optional environment variables:

- `ECHO_BASE`: defaults to `https://echoapi.alwisp.com`
- `ECHO_TODAY`: overrides today's date for deterministic writes and health checks
- `ECHO_VERIFY`: defaults to `1`; read-back verifies `put`
- `ECHO_LOCK_TTL`: defaults to `900` seconds

## Runtime

Prefer the bundled Python client for every vault read or write:

```bash
python skills/echo-memory/scripts/echo.py get _agent/memory/semantic/operator-preferences.md
python skills/echo-memory/scripts/echo.py append inbox/captures/inbox.md "- 2026-06-19: Jason wants this captured."
python skills/echo-memory/scripts/echo.py patch _agent/context/current-context.md replace heading "Current Context::Scope" scope.md
python skills/echo-memory/scripts/echo.py scope show
python skills/echo-memory/scripts/echo.py scope set "Converting ECHO memory into a Codex plugin"
```

The client centralizes auth injection, HTTP status checks, one bounded retry on transient 5xx/transport errors, idempotent append, read-back verification after `put`, frontmatter patching, advisory lock operations, and scope switching.

On Windows/PowerShell, prefer ASCII text in inline command arguments. For multiline markdown or text containing non-ASCII punctuation, write a UTF-8 temp file and pass the file path to `put` or `patch`; shell pipelines can down-convert characters before the client receives them.

Use these scripts for operational flows:

- `scripts/echo.py`: validated API client
- `scripts/bootstrap.py`: idempotent vault setup/repair from bundled `scaffold/`
- `scripts/migrate.py`: dry-run by default; use `--apply` for schema moves/deletes
- `scripts/vault_lint.py`: read-only vault health invariant checker
- `scripts/closeout.py`: writes the daily Agent Log entry, session log, and heartbeat pointer
- `scripts/routing.json`: canonical machine-readable routing manifest

## Load Memory

At the start of any substantive work session, load memory. Issue the independent reads in parallel when practical:

1. `_agent/echo-vault.md`: bootstrap marker and schema version
2. `_agent/memory/semantic/operator-preferences.md`: Jason profile/preferences
3. `_agent/context/current-context.md`: active scope and scope history
4. `_agent/heartbeat/last-session.md`, then the pointed session log if present
5. `journal/daily/YYYY-MM-DD.md`: today's note; 404 is acceptable
6. `inbox/captures/inbox.md`: inbox depth probe; 404 is acceptable

After loading, reconcile in one short line:

- If old inbox captures exist, surface the count and ask whether to triage.
- If the recorded scope diverges from the current request, switch it before working with `scope set`.

Do not read the whole vault. Search targeted project or topic names when needed.

## Save Memory

Write when Jason asks to remember, save, note, log, capture, or when a durable fact, preference, commitment, decision, or session outcome should persist.

Rules:

- Route writes through `references/routing-map.md`; if no destination fits, capture to `inbox/captures/inbox.md`.
- Search first before creating any slug-addressed note. Search both the slug and human title.
- Read before append. `append` does this automatically and skips exact duplicate lines.
- Preserve `created:` when merging. Bump `updated:` only for substantive changes.
- Write in third person about Jason.
- Never store secrets or API keys in a vault note.
- Never put `[[wikilinks]]` in frontmatter; use the body `## Related` section.
- Do not delete notes unless Jason explicitly asks and the destructive action is clearly safe.

After any substantive memory write, run the closeout workflow unless Jason explicitly says not to log it. This is separate from routing: ordinary writes update their canonical notes, and closeout records that the session happened.

```bash
python skills/echo-memory/scripts/closeout.py \
  --slug "brief-session-topic" \
  --goal "What this session was for." \
  --actions "What was changed or recorded." \
  --next-step "What to do first next time." \
  --daily-line "One-line Agent Log entry." \
  --related "[[path/to/relevant-note]]"
```

The helper ensures `journal/daily/YYYY-MM-DD.md`, appends under `## Agent Log`, writes `_agent/sessions/YYYY-MM-DD-HHMM-<slug>.md`, and updates `_agent/heartbeat/last-session.md`.

## Triage Inbox

For "triage ECHO inbox", read `inbox/captures/inbox.md`, identify dated captures older than about 7 days that have not been routed, and offer to route them. For accepted items, write to the canonical destination and append an audit line to `inbox/processing-log/YYYY-MM-DD.md`. Do not delete the original capture unless Jason explicitly asks.

## Vault Health

For "ECHO health" or monthly maintenance, run:

```bash
ECHO_TODAY=<current-date> python skills/echo-memory/scripts/vault_lint.py
```

Exit codes:

- `0`: clean
- `1`: violations found
- `2`: vault unreachable
- `3`: not bootstrapped

Summarize findings by category. Do not auto-fix without Jason's go-ahead.

## Bootstrap And Migrate

If `_agent/echo-vault.md` is missing, run a dry run first:

```bash
python skills/echo-memory/scripts/bootstrap.py --dry-run
```

Then run without `--dry-run` only if Jason wants the vault bootstrapped or repaired. The bootstrap is additive and probe-before-write.

If the marker schema is older than this plugin, run:

```bash
python skills/echo-memory/scripts/migrate.py
```

That prints a dry-run plan. Use `--apply` only with explicit approval for moves/deletes.

## References

- Durable operating contract: `references/operating-contract.md`
- Bootstrap/repair/migration details: `references/bootstrap.md`
- Vault layout and frontmatter: `references/vault-layout.md`
- Canonical routing map: `references/routing-map.md`
- REST API reference: `references/api-reference.md`
- Session log template: `references/session-log-template.md`
