{"slug": "sleep-cycle-memory-for-agents-capture-while-awake-distill-while-asleep", "title": "Sleep-cycle memory for agents: capture while awake, distill while asleep", "summary": "Sleep, a new memory system for coding agents, adds a reviewable memory cycle to Pi, OmO and Claude Code that captures observations during a session, consolidates them into provisional memory afterward, and requires explicit human approval before any memory becomes permanent. The tool ships as the npm package pi-sleep-agent (version 0.1.0) and requires Python 3.10 or newer plus the Claude Code CLI for model-backed consolidation and replay; its installer runs the test suite first and creates backups before configuration changes. Sleep redacts secrets, quarantines hostile text, and blocks machine-generated prompts from claiming user provenance, with a nightly pass that mines repeated preferences without a model call and measures memory effects by replaying the same task with memory off and on.", "body_md": "**Give your coding agents useful memory without giving memory control.**\n\nCapture while agents work. Consolidate when they stop. Promote only what you approve.\n\nSleep adds a reviewable memory cycle to Pi, OmO, and Claude Code. It records useful observations during a session, turns them into provisional memory after the session, and keeps permanent memory behind an explicit human approval step.\n\n- **Automatic capture.** Hooks and the Pi extension collect useful observations while you work.\n- **Budgeted consolidation.** Sleep runs only after the record and time gates pass.\n- **Review before permanence.** New memories stay provisional until you promote or refuse them.\n- **Nightly dream cycle.** Mine repeated preferences, consolidate recent observations, and measure memory effects while you are away.\n- **Measured replay.** Run the same task with memory off and on before deciding whether a memory helps.\n- **Repeated preference detection.**`mine` finds instructions you gave in multiple sessions without a model call.\n- **Project isolation.** A project's provisional memory is injected only into that project.\n- **Safety gates.** Secrets are redacted, hostile text is quarantined, and machine-generated prompts cannot claim user provenance.\n\nRequirements:\n\n- Python 3.10 or newer\n- Claude Code CLI for model-backed consolidation and replay\n- Pi, OmO, Claude Code, or any combination of them\n\n```\n./install.sh --dry-run     # show every change without writing\n./install.sh               # install the shared skill and Claude Code hooks\n./install.sh --extension   # also install the Pi/OmO extension\n./install.sh --launchd     # also schedule the nightly pass on macOS\n```\n\nThe installer runs the test suite first, creates backups before configuration changes, and is safe to run again.\n\nPi and OmO require Sleep's user-installed extension for automatic integration:\n\n```\n./install.sh --extension\n```\n\nThe installer links this repository's `extension/` directory to:\n\n```\n~/.omo/agent/extensions/sleep\n```\n\nThe extension loads on the next Pi or OmO session and performs three jobs:\n\n- captures user messages and relevant tool activity into T0,\n- injects matching T1 provisional memory into the agent context,\n- wakes the sleep policy after the agent settles.\n\nVerify that it loaded:\n\n```\nomo -p 'hi' >/dev/null 2>&1\ntail -4 ~/.sleep/logs/extension.log\n```\n\nThe log should contain `session_start`, `publish`, and `agent_settled` entries.\n\nWithout this extension, the Sleep CLI still works when you run commands manually, and Claude Code can still use its own hooks. Pi and OmO, however, will not capture sessions, inject provisional memory, or trigger sleep automatically.\n\nSleep also ships as the npm package `pi-sleep-agent`, so Pi and OmO can use\n\nthe extension without cloning the repository. Install it through the `pi install`\n\npackage flow:\n\n```\npi install npm:pi-sleep-agent\n# or, for a specific published version\npi install npm:pi-sleep-agent@0.1.0\n```\n\nThe package contains the extension (`pi.extensions`), the Sleep skill\n\n(`pi.skills`), and the Python runtime behind it, so the CLI works from the\n\ninstalled package too. Pi manages the package under its own directory; do not\n\nguess that path. The extension resolves its own runtime from the package and\n\nrecords it in the log, so the verification below proves it loaded the installed\n\ncopy rather than a checkout:\n\n```\nomo -p 'hi' >/dev/null 2>&1\ntail -4 ~/.sleep/logs/extension.log     # session_start, publish, agent_settled\n```\n\nThose three log lines are the proof that the packaged extension loaded and its\n\nPython runtime ran. If they do not appear, reload the extension (`pi install` it\n\nagain, or restart the session); do not dig under the package directory and guess\n\na path.\n\nVerify the tarball contract locally without publishing:\n\n```\nnpm run pack:check     # what npm pack would ship, as JSON\nnpm run smoke:package  # install the tarball into an isolated Pi home and prove it loads\n```\n\nTo remove Sleep and restore the backed-up configuration:\n\n```\n./uninstall.sh\n```\n\nCheck the installation:\n\n```\n./sleep.py status -v\n./sleep.py doctor\n./sleep.py sleep --dry-run\n```\n\nCapture a useful observation manually when needed:\n\n```\n./sleep.py capture   --text \"The staging gateway requires X-Route: blue.\"   --kind fact   --source user\n```\n\nRun a consolidation pass:\n\n```\n./sleep.py sleep --dry-run\n./sleep.py sleep --force\n```\n\nReview the resulting candidate before making it permanent:\n\n```\n./sleep.py status -v\n./sleep.py show <candidate-id>\n./sleep.py promote <candidate-id> --dry-run\n./sleep.py promote <candidate-id>\n```\n\nReject an incorrect candidate without deleting its audit trail:\n\n```\n./sleep.py refuse <candidate-id> --note \"Incorrect for the current deployment.\"\n```\n\nAfter installation, normal sessions need no extra commands:\n\n1. The integration captures observations into the temporary T0 buffer.\n2. The sleep gate waits for at least 3 records and 6 hours since the previous pass.\n3. A model condenses the buffer into provisional T1 candidates.\n4. Provisional candidates can appear as clearly marked background context in matching projects.\n5. You inspect candidates and choose whether to promote them into permanent T2 memory.\n\n``` php\nsession activity -> T0 buffer -> gated sleep -> T1 provisional memory\n                                                   |\n                                             review or replay\n                                                   |\n                                             explicit promote\n                                                   |\n                                             T2 permanent memory\n```\n\nDream is Sleep's unattended reflection phase. It does not update model weights and it never writes permanent memory on its own.\n\nA dream pass performs three steps:\n\n1. **Mine.** Find instructions you repeated across separate sessions in the same project. This step is deterministic and makes no model call.\n2. **Consolidate.** When the sleep gate passes, ask the configured model to turn recent T0 observations into provisional T1 candidates.\n3. **Replay.** When replay is due, run selected tasks with provisional memory off and on, then write a comparison report.\n\nEvery result stays reviewable. Candidates remain in T1 until you explicitly run `promote`.\n\nPreview the complete dream pass without model calls or writes:\n\n```\n./sleep.py nightly --dry-run\n```\n\nRun it now:\n\n```\n./sleep.py nightly --force\n```\n\nRun the two dream components separately when you want more control:\n\n```\n./sleep.py mine --dry-run\n./sleep.py mine\n\n./sleep.py replay --limit 3              # show the replay plan\n./sleep.py replay --run --limit 3 --budget 0.10\n```\n\n`--budget` is the maximum cost per task across both replay arms. Dream reports are written under `$SLEEP_HOME/reports/` and never trigger promotion automatically.\n\n| Command | Purpose | \n|---|---|\n| `./sleep.py status -v` | Show buffer, candidate, quarantine, and permanent-memory status | \n| `./sleep.py sleep --dry-run` | Check whether the sleep gate would run | \n| `./sleep.py sleep --force` | Run consolidation now | \n| `./sleep.py show <id>` | Inspect a candidate and its rendered context | \n| `./sleep.py promote <id>` | Move an approved candidate to permanent memory | \n| `./sleep.py refuse <id> --note \"...\"` | Record that a candidate is incorrect | \n| `./sleep.py replay --run --limit 3` | Compare selected tasks with memory off and on | \n| `./sleep.py mine --dry-run` | Find preferences repeated across sessions | \n| `./sleep.py nightly --dry-run` | Preview the unattended nightly workflow | \n| `./sleep.py doctor` | Find duplicate or overlapping memory records | \n| `./sleep.py inject --project \"$PWD\"` | Print provisional context for the current project | \n\nRun `./sleep.py <command> --help` for command-specific options.\n\n| Agent | Integration | \n|---|---|\n| Claude Code | `UserPromptSubmit` ,`PostToolUse` ,`Stop` , and`PreCompact` hooks | \n| Pi / OmO | Required user-installed extension: `./install.sh --extension` | \n\nBoth integrations share `$SLEEP_HOME`, so candidates reviewed from one client are visible to the other when the project scope matches.\n\nInteractive runs inherit your current environment. Scheduled macOS runs read additional values from `$SLEEP_HOME/env`, which defaults to `~/.sleep/env`.\n\n```\nmkdir -p ~/.sleep\ntouch ~/.sleep/env\nchmod 600 ~/.sleep/env\n```\n\nThe file accepts `KEY=VALUE` lines. Common settings are:\n\n```\nANTHROPIC_API_KEY=...\nANTHROPIC_BASE_URL=...\nANTHROPIC_MODEL=...\nSLEEP_MODEL=...\n```\n\nAn explicit `--model` wins over `SLEEP_MODEL`, which wins over `ANTHROPIC_MODEL`. Existing process environment variables win over values in the file.\n\nBefore enabling the schedule, test the same path manually:\n\n```\n./sleep.py nightly --dry-run\n./sleep.py sleep --force --budget 0.10\n```\n\nSleep separates memory into three tiers:\n\n| Tier | Meaning | Who writes it | \n|---|---|---|\n| T0 | Temporary session observations | Hooks, extension, or `capture` | \n| T1 | Provisional memory shown as unverified background | Consolidation and `mine` | \n| T2 | Permanent memory | Only an explicit `promote` command | \n\nAdditional safeguards:\n\n- Model output is always stamped as agent-generated and cannot mark itself user-confirmed.\n- Provisional memory is rendered as background, not as an instruction.\n- Secret-like values are replaced with redaction markers.\n- Prompt-injection and exfiltration shapes are moved to quarantine.\n- Mixed-project buffers fail closed instead of assigning facts to the wrong project.\n- Replay reports results but never promotes memory automatically.\n- Every model call has an explicit budget limit.\n\nAll runtime data lives under `$SLEEP_HOME`, which defaults to `~/.sleep`:\n\n```\nbuffer/         temporary T0 records\ncandidates/     provisional T1 records\nreports/        replay reports\nlogs/           hook and nightly logs\n.quarantine/    rejected unsafe input\nstate.json      sleep and replay timestamps\nenv             optional scheduled-run environment\n```\n\nUseful logs:\n\n```\n~/.sleep/logs/hook-fires.log\n~/.sleep/logs/hook.log\n~/.sleep/logs/nightly.log\n```\n\nUse another home for testing or for a separate memory pool:\n\n```\nSLEEP_HOME=/tmp/my-sleep ./sleep.py status -v\n```\n\n**Nothing was captured**\n\n```\n./sleep.py status -v\n./sleep.py doctor\n```\n\nCheck `~/.sleep/logs/hook-fires.log`. If it is empty, the integration did not fire. If it contains events but the buffer is empty, the events were ignored or quarantined.\n\n**Sleep keeps skipping**\n\nThe default gate requires 3 records and a 6-hour interval. Inspect the decision with:\n\n```\n./sleep.py sleep --dry-run\n```\n\nUse `--force` only when you intentionally want a model call.\n\n**The scheduled pass cannot reach the model**\n\nConfirm that `~/.sleep/env` exists, has mode `0600`, and contains the same provider settings used by your interactive shell. Then run `./sleep.py sleep --force` before relying on launchd.\n\n**A candidate appears in the wrong context**\n\nRun `./sleep.py show <id>` and check its `cwd`. Mixed-project batches are kept in T0 and return an error instead of producing candidates.", "url": "https://wpnews.pro/news/sleep-cycle-memory-for-agents-capture-while-awake-distill-while-asleep", "canonical_source": "https://github.com/aydinnyunus/sleep", "published_at": "2026-11-01 11:52:49+00:00", "updated_at": "2026-11-01 12:20:10.173437+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "ai-safety"], "entities": ["Sleep", "Pi", "OmO", "Claude Code", "pi-sleep-agent", "Python 3.10"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/sleep-cycle-memory-for-agents-capture-while-awake-distill-while-asleep", "markdown": "https://wpnews.pro/news/sleep-cycle-memory-for-agents-capture-while-awake-distill-while-asleep.md", "text": "https://wpnews.pro/news/sleep-cycle-memory-for-agents-capture-while-awake-distill-while-asleep.txt", "jsonld": "https://wpnews.pro/news/sleep-cycle-memory-for-agents-capture-while-awake-distill-while-asleep.jsonld"}}