Skip to content

Add optional digest companion app (recent-memory summaries to Slack/Discord)#59

Merged
imonroe merged 2 commits into
mainfrom
claude/ob1-digest-app
Jun 4, 2026
Merged

Add optional digest companion app (recent-memory summaries to Slack/Discord)#59
imonroe merged 2 commits into
mainfrom
claude/ob1-digest-app

Conversation

@imonroe
Copy link
Copy Markdown
Owner

@imonroe imonroe commented Jun 4, 2026

Summary

Adds an optional digest companion app that periodically posts a summary of recently added memories to a Slack or Discord channel — a lightweight way to resurface what you've been capturing. Adapts the OB1 / Open Brain daily/weekly digest recipe (backlog issue #50) to this server.

It's a separate, port-less CapRover app built from digest/, mirroring the existing backup/ app's cron-container pattern (so it can't destabilize the stateless main API).

How it works

Each scheduled run: fetch recent memories (REST) → filter to the look-back window → summarize (Claude, optional) → post to webhook.

  • No LLM required: if ANTHROPIC_API_KEY is unset, the digest is a plain bulleted list (zero added cost). If set, it's one Claude call per run.
  • Slack & Discord: webhook format auto-detected from the URL (text vs content), overridable.
  • Self-contained: depends only on httpx (already pinned); nothing from app/ or the main image.
  • Schedule is env-driven (DIGEST_CRON, default daily 08:00 UTC); DIGEST_RUN_ON_START=true triggers an immediate run to verify config.

Files

  • digest/digest.py — pure, unit-testable helpers (parse_timestamp, memory_text, filter_recent, summarize_with_claude, build_digest with graceful fallback, format_payload/detect_format, fetch_memories, deliver) plus main().
  • digest/entrypoint.sh — snapshots env for cron (crond jobs don't inherit it), builds /etc/crontabs/root from $DIGEST_CRON, optional run-on-start, streams the log to stdout.
  • digest/Dockerfile (python:3.12-alpine + dcron), requirements.txt, captain-definition.

Tests

  • tests/test_digest.py17 cases: timestamp parsing (Z/naive/bad), filter_recent (recent vs old vs missing-timestamp, updated_at preference), text extraction, prompt/format/detect helpers, and respx-mocked fetch_memories (bearer + limit), deliver, summarize_with_claude (headers + parsing), build_digest (Claude path, no-key fallback, error fallback), and main() wiring (delivers when recent; skips when nothing new).
  • Full suite: 119 passed, ruff clean.
  • Also smoke-tested directly: required-env guard exits non-zero, entrypoint.sh passes sh -n, crontab line generates correctly, and print-mode (no webhook) renders the fallback digest.

Docs

  • User Guide: new "3. Deploy the digest app (optional)" section with full env-var table, cost note, and a docker run example for non-CapRover hosts; plus a troubleshooting row.
  • Developer Guide: project-layout entry. CLAUDE.md: companion-app note.

Architecture notes

No changes to the main app, its invariants, or runtime deps. The digest is a read-only REST consumer in its own container.

Closes #50.

https://claude.ai/code/session_017835DVrvURaYnbQiPQwzue


Generated by Claude Code

…iscord)

A separate, port-less CapRover app (mirrors backup/) that periodically pulls
recent memories from the REST API, optionally summarizes them with Claude, and
posts the result to a Slack or Discord incoming webhook. Adapts the OB1
project's daily/weekly digest recipe to this server.

- digest/digest.py: pure, unit-testable helpers (parse_timestamp, filter_recent,
  build_digest with Claude-or-plain-list fallback, webhook formatting) + a main()
  that wires fetch -> filter -> summarize -> deliver. Self-contained (httpx only).
- digest/entrypoint.sh: snapshots env for cron, builds the crontab from
  $DIGEST_CRON (default daily 08:00 UTC), optional run-on-start, streams the log.
- digest/Dockerfile (python:3.12-alpine + dcron), requirements.txt, captain-definition.
- tests/test_digest.py: 17 cases (pure helpers + respx-mocked fetch/summarize/
  deliver + main wiring for deliver and empty-skip paths).
- docs: USER_GUIDE deploy section (env table, cost note, docker run) +
  troubleshooting row; DEVELOPER_GUIDE layout; CLAUDE.md companion-app note.

Closes #50.

https://claude.ai/code/session_017835DVrvURaYnbQiPQwzue
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new optional digest/ companion cron container that periodically fetches recent memories via the existing REST API, optionally summarizes them with Anthropic Claude, and posts the result to a Slack/Discord webhook (plus docs + tests to support deployment and behavior).

Changes:

  • Introduces the standalone digest/ CapRover app (Dockerfile, entrypoint cron wiring, and digest.py helpers + main()).
  • Adds a dedicated pytest suite for the digest behavior (pure helpers + respx-mocked network behavior).
  • Updates user/developer documentation to describe deploying and operating the new digest companion app.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
digest/digest.py Implements digest fetching/filtering/summarization/delivery logic and env-driven main().
digest/entrypoint.sh Cron container entrypoint: snapshots env, writes crontab, optional run-on-start, tails log.
digest/Dockerfile Builds minimal Python + dcron Alpine image for the digest companion app.
digest/requirements.txt Pins digest app runtime dependency (httpx).
digest/captain-definition CapRover build descriptor for the digest app.
digest/__init__.py Marks digest/ as a package for test imports.
tests/test_digest.py Adds unit/integration-style tests (helpers + HTTP interactions via respx).
docs/USER_GUIDE.md Documents optional digest deployment/configuration and troubleshooting.
docs/DEVELOPER_GUIDE.md Updates project layout documentation to include digest/.
CLAUDE.md Notes the new digest companion app in the repo overview.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread digest/entrypoint.sh Outdated
Comment thread digest/digest.py
Comment thread digest/digest.py
Comment thread docs/USER_GUIDE.md Outdated
Comment thread docs/DEVELOPER_GUIDE.md Outdated
- digest.py: the REST list endpoint caps limit at 100, but DIGEST_MAX_MEMORIES
  defaulted to 200 — every run with defaults would 422. Default to 100 and clamp
  via a new _int_env() helper that also handles unparseable values gracefully.
  Update the module docstring accordingly.
- entrypoint.sh: env vars can contain spaces (DIGEST_CRON, DIGEST_TITLE) and
  quotes, which broke the raw `printenv` env file when sourced by the cron job.
  Emit single-quote-escaped `export` lines instead, and chmod 600 the file since
  it holds MEM0_API_KEY.
- tests: _int_env clamp/default/bad-value cases + main() requests limit<=100.
- docs: USER_GUIDE DIGEST_MAX_MEMORIES row (default 100, server cap noted);
  DEVELOPER_GUIDE digest layout bullets de-swapped and clarified.

https://claude.ai/code/session_017835DVrvURaYnbQiPQwzue
@imonroe imonroe merged commit cecd0b7 into main Jun 4, 2026
1 check passed
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.

Daily / weekly digest companion app (email or Slack summary of recent memories)

3 participants