Immutable. This exact content is served forever at /api/v1/blob/e0f65a80190dc2e0.
# codemem ## Public repository safety Assume this repository is public and everything you write (code, docs, tests, and commit messages) will be published. - Never add proprietary/internal references (private domains/hostnames, internal project codenames, employee emails, vendor/customer confidential identifiers, etc.). - Never add secrets (API keys, tokens, passwords, private keys), even as examples. Use obvious placeholders instead. - Keep local artifacts out of git (`.venv/`, `.tmp/`, `*.sqlite`, logs, caches). - If you discover sensitive content already tracked or in git history: stop and propose a remediation plan (remove from tree + consider history rewrite). If you are about to run commands, default to the TypeScript toolchain (`pnpm ...`). Use `uv run ...` only when you are explicitly working on the legacy Python backend (`codemem/`, `tests/`, pytest/ruff, or Python release metadata). ## Execution Contract - Treat work as incomplete until the requested change is implemented, the smallest relevant validation has run, and any remaining gaps are called out explicitly as blocked or deferred. - Do not stop at analysis, a partial fix, or "here's what I would do" unless the user explicitly asked for plan-only work. - Before acting, check prerequisites first: read the file you will change, inspect nearby tests/docs when behavior or public usage changes, and resolve dependency outputs from earlier steps before continuing. - If a lookup/search result is empty or suspiciously narrow, try at least one fallback query or adjacent source before concluding that nothing relevant exists. - Before finalizing, verify: requirements are met, claims are grounded in repo/tool output, requested format is satisfied, and the smallest relevant test/lint/build/doc check has passed. - For substantial work, send short progress updates at phase changes only: what changed or was learned, and the next step. Do not narrate routine tool calls. - For commits, pushes, issue updates, server restarts, or maintenance commands, briefly state the intended action first, then confirm the outcome and validation afterward. ## Releases Release checklist: 1. Create a release branch + PR (no direct pushes to `main`) 2. Update version: - `packages/core/package.json` - `packages/cli/package.json` - `packages/opencode-plugin/package.json` - `packages/mcp-server/package.json` - `packages/viewer-server/package.json` - `packages/core/src/index.ts` - `packages/core/src/index.test.ts` - `packages/cli/.opencode/plugins/codemem.js` - `packages/opencode-plugin/.opencode/plugins/codemem.js` - `.claude-plugin/marketplace.json` (metadata version and codemem plugin entry version; MCP args are unpinned) - `plugins/claude/.claude-plugin/plugin.json` (metadata version only; MCP args are unpinned) 3. Regenerate lockfiles/artifacts and commit the results: - JS: run `pnpm install` and commit lockfile/artifact changes when applicable - Viewer UI bundle/assets: built via `pnpm build` 4. Ensure JS installs use the public npm registry (avoid private registries/mirrors) - Keep `.opencode/.npmrc` with `registry=https://registry.npmjs.org/` 5. Wait for CI to pass, then squash-merge the PR 6. After the release PR merges, switch to updated `main` and verify `HEAD` is the merged release commit - Run `git checkout main` - Run `git pull --rebase` - Run `git status --short --branch` and confirm the worktree is clean - Run `git show --stat --summary HEAD` and confirm the release version/artifact changes are present on `main` 7. Tag the merge commit on `main` as `vX.Y.Z` and push the tag - Never tag the release branch commit directly - Never create/push the release tag while checked out on `release/*` - Never assume the release branch tip and merged `main` commit are interchangeable; verify before tagging - The `Release` workflow triggers on `v*` tags and publishes the GitHub Release artifacts. 8. Do not immediately bump `main` to the next unreleased version with the current shared versioning model - `main` also carries live marketplace/plugin metadata and pinned CLI version references - A post-release bump on `main` can point live install paths at a package version that is not published yet - Keep next-version bumps in a later release-prep branch/PR unless versioning is explicitly decoupled first ## Stack - Node: >=24 - Package manager: pnpm (workspace at root) - Build: Vite 8 (library mode, Rolldown-powered) - Tests: vitest - Lint/format: biome - Packages: `packages/core`, `packages/mcp-server`, `packages/viewer-server`, `packages/cli` - Storage: SQLite (path configurable) ### Legacy Python (reference-only) - Python backend code remains in `codemem/` and `tests/` for migration/reference work. - Use `uv run ...` only when explicitly touching legacy Python surfaces. **Publish model:** root `package.json` is workspace-only (`private: true`). The published CLI package is `codemem` from `packages/cli`. The published OpenCode plugin package is `@codemem/opencode-plugin` from `packages/opencode-plugin`. ## Quick Commands ### TypeScript default workflow - Install JS deps: `pnpm install` - Build all TS packages: `pnpm build` - Run tests: `pnpm run test` - Lint: `pnpm run lint` - Typecheck: `pnpm run tsc` - Run TS CLI from source: `pnpm run codemem --help` ### Legacy Python setup (only when required) - Install dev deps + create venv: `uv sync` - Run commands via the venv (no activate): `uv run codemem --help` - Activate (fish): `source .venv/bin/activate.fish` - Activate (bash/zsh): `source .venv/bin/activate` ### Legacy Python build / install - Editable install (if you want `codemem` on PATH): `uv pip install -e .` - No-install run from this repo: `uv run codemem stats` - One-off run via uvx: `uvx --from . codemem stats` ### TypeScript runtime commands (preferred) - CLI help: `pnpm run codemem --help` - Viewer help: `pnpm run codemem serve --help` - Serve viewer (start): `pnpm run codemem serve start` - Serve viewer (background): `pnpm run codemem serve --background` - Serve viewer (restart): `pnpm run codemem serve restart` - MCP server: `pnpm run codemem mcp` - Claude hook ingest (stdin JSON): `pnpm run codemem claude-hook-ingest` - Stats: `pnpm run codemem stats` - Raw-event backlog: `pnpm run codemem db raw-events-status` ### Legacy Python runtime commands (only when explicitly required) - CLI help: `uv run codemem --help` - Viewer help: `uv run codemem serve --help` - Serve viewer: `uv run codemem serve` - Serve viewer (background): `uv run codemem serve --background` - Serve viewer (restart): `uv run codemem serve --restart` - MCP server: `uv run codemem mcp` - Ingest (stdin JSON): `uv run codemem ingest` - Stats: `uv run codemem stats` ### Tests (pytest) - Run all tests: `uv run pytest` - Run a single file: `uv run pytest tests/test_store.py` - Run a single test: `uv run pytest tests/test_store.py::test_store_roundtrip` - Run by substring match: `uv run pytest -k "roundtrip and store"` - `uv run pytest tests/test_store.py::test_deactivate_low_signal_observations` - Pytest default opts are in `pyproject.toml` (`addopts = "-q"`). ### Lint / Format (ruff) - Lint: `uv run ruff check codemem tests` - Format (check only): `uv run ruff format --check codemem tests` - Auto-fix lint + format: `uv run ruff check --fix codemem tests` then `uv run ruff format codemem tests` Ruff config (from `pyproject.toml`): - line length: 100 - target: py311 - lint selects: E, W, F, I, UP, B, SIM - ignores: E501 (formatter), B008 (Typer default args) ### Coverage (optional) - `uv run pytest --cov=codemem --cov-report=term` ## Frontend Development Viewer UI is in `packages/ui` and served by `packages/viewer-server`. ### Viewer UI - Source: `packages/ui/src/` - Dev loop: edit UI files, run `pnpm build`, then restart viewer if needed ### OpenCode plugin - Source: `packages/opencode-plugin/.opencode/plugins/codemem.js` - Rules: - ESM only (`import`/`export`) - must never crash OpenCode (no uncaught exceptions) - avoid blocking hooks; defer heavy work to background CLI calls ## Repo Map - `packages/core/src/`: core store/search/ingest/sync logic - `packages/viewer-server/src/`: viewer API server - `packages/ui/src/`: viewer frontend - `packages/mcp-server/src/`: MCP server tools - `packages/cli/src/`: CLI commands - `packages/opencode-plugin/.opencode/plugins/codemem.js`: OpenCode plugin entrypoint - `codemem/`, `tests/`: legacy Python backend/tests (reference only) ## Runtime Commands - CLI entrypoint: `codemem` - MCP server: `codemem mcp` (or `codemem-mcp`) - Claude hook ingest (stdin JSON): `codemem claude-hook-ingest` - Viewer: `codemem serve start|stop|restart` (or `codemem serve --background`) - Export/Import: `codemem export-memories`, `codemem import-memories` - Store maintenance: `codemem db prune-memories` (use `--dry-run` first) ## Environment Variables - `CODEMEM_DB`: sqlite path (example: `~/.codemem/mem.sqlite`) - `CODEMEM_PLUGIN_LOG`: set to `1` to enable plugin logging ## CLI Design - Follow `docs/cli-design-conventions.md` for all CLI command additions and modifications - Key rules: max 2 nesting levels, positional args for primary nouns, flags for config/modifiers, `--json` on all data-returning commands, structured error output, no uncaught throws from action handlers - Shared flags (`--db-path`, `--config`, `--json`) should use option-builder helpers, not copy-paste ## Code Style ### Python - Version: Python >=3.11,<3.15 (see `pyproject.toml`) - Always use `from __future__ import annotations` (project convention; most files already do) - Formatting: let `ruff format` do the wrapping; don't fight it - Imports: - Let ruff/isort order imports - Prefer relative imports within `codemem` (as existing code does) - Types: - Prefer built-in generics (`list[str]`, `dict[str, Any]`) and `collections.abc` (`Iterable`, `Sequence`) - Use `Path` for filesystem paths; accept `Path | str` at public boundaries and normalize early - Use `TypedDict` for "event-like" dict payloads when shape matters - Naming: - `snake_case` for functions/vars, `PascalCase` for classes, `UPPER_SNAKE_CASE` for constants - Private helpers start with `_`; keep module surfaces small and explicit - Error handling: - Validate at boundaries (env vars, config, CLI inputs, network payloads) - Avoid bare `except:`; log exceptions with context (`logger.warning(..., exc_info=exc)` or `logger.exception(...)`) - CLI: prefer user-friendly messages + non-zero exits (Typer patterns) - Keep failure paths safe/deterministic (no partial DB writes without intent) ### JavaScript (OpenCode plugin) - ESM modules (`import`/`export`) - The plugin must never crash OpenCode: - Guard risky code paths; swallow/record errors where needed - Avoid blocking work in hooks; defer heavy work to background CLI calls - Keep helper functions small and testable; prefer pure transformations ## Memory Quality - Don't store raw tool logs as memories - Filter low-signal tool events (`read`, `edit`, `glob`, `grep`, etc.) - Prefer typed memory kinds: `discovery`, `change`, `feature`, `bugfix`, `refactor`, `decision`, `exploration` - Use `exploration` for attempts/experiments that were tried but not shipped (preserves "why not") - Session summaries/observations are OFF by default; only enable via config ## Configuration - Default config file: `~/.config/codemem/config.json` - Env vars override config values when present - Default DB path is configurable; `CODEMEM_DB=~/.codemem/mem.sqlite` is a common override - Avoid hardcoding user paths in code; use config/env and normalize with `Path(...).expanduser()` ## Testing Guidance - Prefer fast unit tests in `packages/**` via vitest (avoid network; mock external calls) - Use targeted test runs for touched files, then broader runs as needed - Legacy Python tests in `tests/` are for reference/migration surfaces ## Plugin / Viewer Notes - Plugin must be defensive: no uncaught exceptions in hooks; avoid blocking work - Viewer UI comes from `packages/ui` and `packages/viewer-server`; restart viewer to see runtime changes - Docs: - `docs/architecture.md` (data flow, flush strategy) - `docs/user-guide.md` (viewer usage, troubleshooting) ## Quick Debug Checklist - Plugin logging: `CODEMEM_PLUGIN_LOG=1` then check `~/.codemem/plugin.log` - Missing sessions: confirm plugin + viewer use the same DB path (`CODEMEM_DB`) - Flush/backlog issues: look for viewer logs and `codemem db raw-events-status` output ## When Changing Behavior - If you change plugin behavior, update `README.md` (and relevant docs under `docs/`) - If you change memory kinds, also update: - `packages/core/src/store.ts` (kind handling and persistence) - `packages/mcp-server/src/index.ts` (`memory_schema` tool) - `packages/ui/src/tabs/feed.ts` (UI kind presentation) - relevant vitest coverage in `packages/**` ## PR Hygiene - Always use `.github/PULL_REQUEST_TEMPLATE.md` for every PR. - Replace all template placeholder text before requesting review. - Complete all checklist sections accurately: - Type of Change - Testing - Checklist - Apply this to every PR in a stack (base PR and each follow-up PR). - Keep PR titles/bodies and commit messages free of private inspiration references or other non-public context. ## Releases - Release versions are prepared on a release branch + PR, then tagged only after that PR is merged to `main`. - Before tagging: - `git checkout main` - `git pull --rebase` - verify the merged release commit is at `HEAD` - verify the worktree is clean - Tag from `main` only: `git tag vX.Y.Z` then `git push origin vX.Y.Z` - Do not tag from `release/*` branches. - Do not immediately bump `main` to the next unreleased version with the current shared marketplace/package versioning model. ## Do / Don't - Do keep changes small and deterministic; prefer adding tests when behavior changes - Do validate inputs at boundaries; keep DB writes intentional - Don't add new heavy dependencies without a clear need - Don't let the plugin throw uncaught exceptions or block OpenCode hooks <!-- BEGIN BEADS INTEGRATION --> ## Issue Tracking with bd (beads) **IMPORTANT**: This project uses **bd (beads)** for ALL issue tracking. Do NOT use markdown TODOs, task lists, or other tracking methods. ### Why bd? - Dependency-aware: Track blockers and relationships between issues - Git-friendly: Dolt-powered version control with native sync - Agent-optimized: JSON output, ready work detection, discovered-from links - Prevents duplicate tracking systems and confusion ### Quick Start **Check for ready work:** ```bash bd ready --json ``` **Create new issues:** ```bash bd create "Issue title" --description="Detailed context" -t bug|feature|task -p 0-4 --json bd create "Issue title" --description="What this issue is about" -p 1 --deps discovered-from:bd-123 --json ``` **Claim and update:** ```bash bd update <id> --claim --json bd update bd-42 --priority 1 --json ``` **Complete work:** ```bash bd close bd-42 --reason "Completed" --json ``` ### Issue Types - `bug` - Something broken - `feature` - New functionality - `task` - Work item (tests, docs, refactoring) - `epic` - Large feature with subtasks - `chore` - Maintenance (dependencies, tooling) ### Priorities - `0` - Critical (security, data loss, broken builds) - `1` - High (major features, important bugs) - `2` - Medium (default, nice-to-have) - `3` - Low (polish, optimization) - `4` - Backlog (future ideas) ## Issue Tracking This project uses **bd (beads)** for issue tracking. Run `bd prime` for workflow context, or install hooks (`bd hooks install`) for auto-injection. **Quick reference:** - `bd ready` - Find unblocked work - `bd create "Title" --type task --priority 2` - Create issue - `bd close <id>` - Complete work - `bd dolt push` - Push beads to remote **Agent rules:** - Use `bd` for task tracking; do not create markdown TODO lists - Prefer `--json` for programmatic commands - Link discovered follow-up work with `discovered-from` when relevant For full workflow details: `bd prime`