observational-memory 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. observational_memory-0.1.0/.claude/settings.local.json +20 -0
  2. observational_memory-0.1.0/.github/workflows/ci.yml +38 -0
  3. observational_memory-0.1.0/.github/workflows/claude-code-review.yml +44 -0
  4. observational_memory-0.1.0/.github/workflows/claude.yml +50 -0
  5. observational_memory-0.1.0/.gitignore +23 -0
  6. observational_memory-0.1.0/CLAUDE.md +64 -0
  7. observational_memory-0.1.0/LICENSE +21 -0
  8. observational_memory-0.1.0/Makefile +125 -0
  9. observational_memory-0.1.0/PKG-INFO +481 -0
  10. observational_memory-0.1.0/README.md +449 -0
  11. observational_memory-0.1.0/pyproject.toml +67 -0
  12. observational_memory-0.1.0/scripts/bump_version.py +121 -0
  13. observational_memory-0.1.0/src/observational_memory/__init__.py +3 -0
  14. observational_memory-0.1.0/src/observational_memory/cli.py +989 -0
  15. observational_memory-0.1.0/src/observational_memory/config.py +147 -0
  16. observational_memory-0.1.0/src/observational_memory/hooks/claude/session-end.sh +226 -0
  17. observational_memory-0.1.0/src/observational_memory/hooks/claude/session-start.sh +46 -0
  18. observational_memory-0.1.0/src/observational_memory/llm.py +53 -0
  19. observational_memory-0.1.0/src/observational_memory/observe.py +356 -0
  20. observational_memory-0.1.0/src/observational_memory/prompts/observer.md +81 -0
  21. observational_memory-0.1.0/src/observational_memory/prompts/reflector.md +90 -0
  22. observational_memory-0.1.0/src/observational_memory/reflect.py +297 -0
  23. observational_memory-0.1.0/src/observational_memory/search/__init__.py +72 -0
  24. observational_memory-0.1.0/src/observational_memory/search/backend.py +24 -0
  25. observational_memory-0.1.0/src/observational_memory/search/bm25.py +114 -0
  26. observational_memory-0.1.0/src/observational_memory/search/none.py +18 -0
  27. observational_memory-0.1.0/src/observational_memory/search/parser.py +63 -0
  28. observational_memory-0.1.0/src/observational_memory/search/qmd.py +127 -0
  29. observational_memory-0.1.0/src/observational_memory/transcripts/__init__.py +15 -0
  30. observational_memory-0.1.0/src/observational_memory/transcripts/claude.py +150 -0
  31. observational_memory-0.1.0/src/observational_memory/transcripts/codex.py +208 -0
  32. observational_memory-0.1.0/tests/__init__.py +0 -0
  33. observational_memory-0.1.0/tests/fixtures/claude-transcript.jsonl +12 -0
  34. observational_memory-0.1.0/tests/fixtures/codex-transcript.jsonl +7 -0
  35. observational_memory-0.1.0/tests/test_config.py +102 -0
  36. observational_memory-0.1.0/tests/test_observe.py +207 -0
  37. observational_memory-0.1.0/tests/test_reflect.py +378 -0
  38. observational_memory-0.1.0/tests/test_search.py +310 -0
  39. observational_memory-0.1.0/tests/test_transcripts.py +124 -0
@@ -0,0 +1,20 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(om search:*)",
5
+ "Bash(uv run pytest:*)",
6
+ "Bash(bun:*)",
7
+ "Bash(qmd --help:*)",
8
+ "Bash(qmd status:*)",
9
+ "Bash(qmd embed:*)",
10
+ "Bash(qmd query:*)",
11
+ "Bash(qmd search:*)",
12
+ "Bash(git add:*)",
13
+ "Bash(git commit -m \"$\\(cat <<''EOF''\nAdd qmd-hybrid backend for vector + LLM reranked search\n\nAdds \"qmd-hybrid\" as a new pluggable search backend that uses QMD''s\n`query` command \\(BM25 + vector embeddings + LLM reranking\\) instead of\nplain `search`. Also fixes QMD result parsing to handle qmd:// URLs\nand snippet fallback.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>\nEOF\n\\)\")",
14
+ "Bash(git push:*)",
15
+ "Bash(uv run python:*)",
16
+ "Bash(git commit -m \"$\\(cat <<''EOF''\nAdd OM_SEARCH_BACKEND env var to configure search backend\n\nThe search backend can now be set via OM_SEARCH_BACKEND in the env\nfile \\(~/.config/observational-memory/env\\) or as an environment\nvariable, instead of editing config.py. Default remains bm25.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>\nEOF\n\\)\")",
17
+ "Bash(om:*)"
18
+ ]
19
+ }
20
+ }
@@ -0,0 +1,38 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ test:
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ python-version: ["3.11", "3.12", "3.13"]
16
+ fail-fast: false
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Set up Python ${{ matrix.python-version }}
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+
26
+ - name: Install uv
27
+ uses: astral-sh/setup-uv@v4
28
+
29
+ - name: Install dependencies
30
+ run: uv sync
31
+
32
+ - name: Lint
33
+ run: |
34
+ uv run ruff check .
35
+ uv run ruff format --check .
36
+
37
+ - name: Test
38
+ run: uv run pytest -q
@@ -0,0 +1,44 @@
1
+ name: Claude Code Review
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, ready_for_review, reopened]
6
+ # Optional: Only run on specific file changes
7
+ # paths:
8
+ # - "src/**/*.ts"
9
+ # - "src/**/*.tsx"
10
+ # - "src/**/*.js"
11
+ # - "src/**/*.jsx"
12
+
13
+ jobs:
14
+ claude-review:
15
+ # Optional: Filter by PR author
16
+ # if: |
17
+ # github.event.pull_request.user.login == 'external-contributor' ||
18
+ # github.event.pull_request.user.login == 'new-developer' ||
19
+ # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
20
+
21
+ runs-on: ubuntu-latest
22
+ permissions:
23
+ contents: read
24
+ pull-requests: read
25
+ issues: read
26
+ id-token: write
27
+
28
+ steps:
29
+ - name: Checkout repository
30
+ uses: actions/checkout@v4
31
+ with:
32
+ fetch-depth: 1
33
+
34
+ - name: Run Claude Code Review
35
+ id: claude-review
36
+ uses: anthropics/claude-code-action@v1
37
+ with:
38
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
39
+ plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
40
+ plugins: 'code-review@claude-code-plugins'
41
+ prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
42
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
43
+ # or https://code.claude.com/docs/en/cli-reference for available options
44
+
@@ -0,0 +1,50 @@
1
+ name: Claude Code
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created]
6
+ pull_request_review_comment:
7
+ types: [created]
8
+ issues:
9
+ types: [opened, assigned]
10
+ pull_request_review:
11
+ types: [submitted]
12
+
13
+ jobs:
14
+ claude:
15
+ if: |
16
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
17
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
18
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
19
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ contents: read
23
+ pull-requests: read
24
+ issues: read
25
+ id-token: write
26
+ actions: read # Required for Claude to read CI results on PRs
27
+ steps:
28
+ - name: Checkout repository
29
+ uses: actions/checkout@v4
30
+ with:
31
+ fetch-depth: 1
32
+
33
+ - name: Run Claude Code
34
+ id: claude
35
+ uses: anthropics/claude-code-action@v1
36
+ with:
37
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
38
+
39
+ # This is an optional setting that allows Claude to read CI results on PRs
40
+ additional_permissions: |
41
+ actions: read
42
+
43
+ # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
44
+ # prompt: 'Update the pull request description to include a summary of changes.'
45
+
46
+ # Optional: Add claude_args to customize behavior and configuration
47
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
48
+ # or https://code.claude.com/docs/en/cli-reference for available options
49
+ # claude_args: '--allowed-tools Bash(gh pr:*)'
50
+
@@ -0,0 +1,23 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .venv/
8
+
9
+ # Memory files (generated locally)
10
+ memory/
11
+
12
+ # IDE
13
+ .idea/
14
+ .vscode/
15
+ *.swp
16
+ *.swo
17
+ *~
18
+
19
+ # macOS
20
+ .DS_Store
21
+
22
+ # uv
23
+ uv.lock
@@ -0,0 +1,64 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Build & Test
6
+
7
+ ```bash
8
+ # Makefile targets (preferred)
9
+ make check # lint + test (run before committing)
10
+ make test # tests only
11
+ make lint # ruff check + format check
12
+ make format # auto-format code
13
+ make build # build sdist + wheel
14
+ make clean # remove build artifacts
15
+ make bump-version # bump patch (BUMP=minor|major)
16
+ make publish-test # publish to TestPyPI
17
+ make publish # publish to PyPI (production)
18
+ make install-dev # editable install with dev deps
19
+ make doctor # run om doctor diagnostics
20
+
21
+ # Direct commands
22
+ uv sync # install deps
23
+ uv run pytest # run all tests
24
+ uv run pytest tests/test_transcripts.py # single test file
25
+ uv run pytest -v # verbose
26
+ uv run om status # check local installation status
27
+ uv run om doctor # run diagnostics
28
+ ```
29
+
30
+ ## Architecture
31
+
32
+ Cross-agent observational memory that works at the **user level** (not per-project) across Claude Code and Codex CLI. Two background processes compress conversation transcripts into shared memory files at `~/.local/share/observational-memory/`.
33
+
34
+ ### Data flow
35
+
36
+ ```
37
+ Transcripts (Claude JSONL / Codex sessions)
38
+ → observe.py (LLM compression → observations.md)
39
+ → reflect.py (daily consolidation → reflections.md)
40
+ ```
41
+
42
+ ### Key modules
43
+
44
+ - **`src/observational_memory/transcripts/claude.py`** — Parses Claude Code `.jsonl` transcripts. Each line is a JSON object with `type` (user/assistant/progress), `message.content` (text or array of blocks), `uuid`, `timestamp`.
45
+ - **`src/observational_memory/transcripts/codex.py`** — Parses Codex CLI session files (`*.json` and `*.jsonl`) from `~/.codex/sessions/`.
46
+ - **`src/observational_memory/observe.py`** — Observer: reads transcripts, finds new messages via cursor bookmarks, calls LLM to compress, appends to `observations.md`.
47
+ - **`src/observational_memory/reflect.py`** — Reflector: reads observations + reflections, calls LLM to condense, writes `reflections.md`, trims old observations.
48
+ - **`src/observational_memory/llm.py`** — Thin abstraction over Anthropic and OpenAI APIs. Auto-detects provider from env vars.
49
+ - **`src/observational_memory/config.py`** — All paths, defaults, cursor management. Memory dir follows XDG spec. Search backend is configurable via `OM_SEARCH_BACKEND` env var.
50
+ - **`src/observational_memory/cli.py`** — Click CLI (`om` command). Commands: observe, reflect, backfill, search, context, install, uninstall, status, doctor.
51
+ - **`src/observational_memory/search/`** — Pluggable search over memory files. BM25 backend (default, uses `rank-bm25`), QMD backend (optional, shells out to `qmd` CLI — `"qmd"` for keyword search, `"qmd-hybrid"` for hybrid BM25 + vector + LLM reranking), None backend (no-op). Parser splits observations by date, reflections by section. The `reindex()` orchestrator is called automatically after observe/reflect writes.
52
+
53
+ ### Agent integration
54
+
55
+ - **Claude Code**: `SessionStart` injects memory via `additionalContext`; `SessionEnd`, `UserPromptSubmit`, and `PreCompact` hooks trigger checkpoints. In-session checkpoints are throttled by `OM_SESSION_OBSERVER_INTERVAL_SECONDS` and can be disabled with `OM_DISABLE_SESSION_OBSERVER_CHECKPOINTS`.
56
+ - **Codex CLI**: Instructions appended to `~/.codex/AGENTS.md`; cron job for observer.
57
+
58
+ ### API keys
59
+
60
+ API keys live in `~/.config/observational-memory/env` (created by `om install`, chmod 600). The CLI loads this file on startup via `config.load_env_file()`. The Claude hooks and cron jobs also source it. Environment variables take precedence over the file.
61
+
62
+ ### Prompts
63
+
64
+ `src/observational_memory/prompts/observer.md` and `src/observational_memory/prompts/reflector.md` define the LLM system prompts. They are bundled as package data. The priority system (🔴/🟡/🟢) and output format are critical — downstream parsing depends on them.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Intertwine
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,125 @@
1
+ # Makefile for observational-memory
2
+ # Cross-agent shared memory for Claude Code and Codex CLI
3
+
4
+ SHELL := /bin/bash
5
+
6
+ .PHONY: help test lint format check build clean bump-version publish-test publish install-dev doctor
7
+
8
+ # ---------- Colors (portable) ----------
9
+ ifdef NO_COLOR
10
+ RED :=
11
+ GREEN :=
12
+ YELLOW :=
13
+ NC :=
14
+ else
15
+ ESC := $(shell printf '\033')
16
+ RED := $(ESC)[0;31m
17
+ GREEN := $(ESC)[0;32m
18
+ YELLOW := $(ESC)[1;33m
19
+ NC := $(ESC)[0m
20
+ endif
21
+ ECHO = printf "%b\n"
22
+
23
+ # Version bump type (patch, minor, major)
24
+ BUMP ?= patch
25
+
26
+ help:
27
+ @$(ECHO) "$(GREEN)Observational Memory - Development Commands$(NC)"
28
+ @$(ECHO) ""
29
+ @$(ECHO) "$(YELLOW)Quality:$(NC)"
30
+ @$(ECHO) " make test - Run all tests"
31
+ @$(ECHO) " make lint - Run linter checks"
32
+ @$(ECHO) " make format - Auto-format code"
33
+ @$(ECHO) " make check - Run all quality checks (lint + format check + test)"
34
+ @$(ECHO) ""
35
+ @$(ECHO) "$(YELLOW)Building:$(NC)"
36
+ @$(ECHO) " make build - Build sdist and wheel"
37
+ @$(ECHO) " make clean - Remove build artifacts"
38
+ @$(ECHO) ""
39
+ @$(ECHO) "$(YELLOW)Versioning:$(NC)"
40
+ @$(ECHO) " make bump-version - Bump patch version (default)"
41
+ @$(ECHO) " make bump-version BUMP=minor - Bump minor version"
42
+ @$(ECHO) " make bump-version BUMP=major - Bump major version"
43
+ @$(ECHO) ""
44
+ @$(ECHO) "$(YELLOW)Publishing:$(NC)"
45
+ @$(ECHO) " make publish-test - Publish to TestPyPI"
46
+ @$(ECHO) " make publish - Publish to PyPI (production)"
47
+ @$(ECHO) ""
48
+ @$(ECHO) "$(YELLOW)Development:$(NC)"
49
+ @$(ECHO) " make install-dev - Install in editable mode with dev deps"
50
+ @$(ECHO) " make doctor - Run om doctor diagnostics"
51
+
52
+ # Run all tests
53
+ test:
54
+ @$(ECHO) "$(YELLOW)Running tests...$(NC)"
55
+ @uv run pytest -q
56
+ @$(ECHO) "$(GREEN)✓ Tests passed$(NC)"
57
+
58
+ # Run linter checks
59
+ lint:
60
+ @$(ECHO) "$(YELLOW)Running linter...$(NC)"
61
+ @uv run ruff check .
62
+ @uv run ruff format --check .
63
+ @$(ECHO) "$(GREEN)✓ Lint passed$(NC)"
64
+
65
+ # Auto-format code
66
+ format:
67
+ @$(ECHO) "$(YELLOW)Formatting code...$(NC)"
68
+ @uv run ruff check . --fix
69
+ @uv run ruff format .
70
+ @$(ECHO) "$(GREEN)✓ Code formatted$(NC)"
71
+
72
+ # Run all quality checks
73
+ check: lint test
74
+ @$(ECHO) "$(GREEN)✓ All checks passed$(NC)"
75
+
76
+ # Build sdist and wheel
77
+ build: clean
78
+ @$(ECHO) "$(YELLOW)Building package...$(NC)"
79
+ @uv run python -m build
80
+ @$(ECHO) "$(GREEN)✓ Package built$(NC)"
81
+ @ls -lh dist/
82
+
83
+ # Clean build artifacts
84
+ clean:
85
+ @$(ECHO) "$(YELLOW)Cleaning build artifacts...$(NC)"
86
+ @rm -rf dist/ build/ src/*.egg-info
87
+ @find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
88
+ @find . -type d -name ".pytest_cache" -exec rm -rf {} + 2>/dev/null || true
89
+ @find . -type d -name ".ruff_cache" -exec rm -rf {} + 2>/dev/null || true
90
+ @$(ECHO) "$(GREEN)✓ Clean$(NC)"
91
+
92
+ # Bump version
93
+ bump-version:
94
+ @if [ "$(BUMP)" != "patch" ] && [ "$(BUMP)" != "minor" ] && [ "$(BUMP)" != "major" ]; then \
95
+ $(ECHO) "$(RED)Error: BUMP must be 'patch', 'minor', or 'major'$(NC)"; \
96
+ exit 1; \
97
+ fi
98
+ @$(ECHO) "$(YELLOW)Bumping $(BUMP) version...$(NC)"
99
+ @VERSION_CHANGE=$$(uv run python scripts/bump_version.py pyproject.toml $(BUMP)); \
100
+ $(ECHO) "$(GREEN)✓ Version updated: $$VERSION_CHANGE$(NC)"
101
+
102
+ # Publish to TestPyPI
103
+ publish-test: build
104
+ @$(ECHO) "$(YELLOW)Publishing to TestPyPI...$(NC)"
105
+ @uv run twine upload --repository testpypi dist/*
106
+ @$(ECHO) "$(GREEN)✓ Published to TestPyPI$(NC)"
107
+ @$(ECHO) "$(YELLOW)Install with: uv tool install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ observational-memory$(NC)"
108
+
109
+ # Publish to PyPI (production)
110
+ publish: build
111
+ @$(ECHO) "$(RED)⚠️ Publishing to production PyPI!$(NC)"
112
+ @$(ECHO) -n "Continue? [y/N] " && read ans && ( [ "$${ans}" = "y" ] || [ "$${ans}" = "Y" ] )
113
+ @uv run twine upload dist/*
114
+ @$(ECHO) "$(GREEN)✓ Published to PyPI$(NC)"
115
+
116
+ # Install in editable mode with dev dependencies
117
+ install-dev:
118
+ @$(ECHO) "$(YELLOW)Installing in editable mode...$(NC)"
119
+ @uv sync
120
+ @uv pip install -e ".[dev]"
121
+ @$(ECHO) "$(GREEN)✓ Installed$(NC)"
122
+
123
+ # Run diagnostics
124
+ doctor:
125
+ @uv run om doctor