OpenReflex
Muscle memory for AI coding agents.
Ambient execution intelligence for AI coding agents. Install it once and keep working normally. It records how each task actually went (strategy, tool calls, failures, what fixed them, which files mattered). Before the next similar task it hands the agent a short Execution Context. While a task runs, it steps in only when the evidence says re-planning is worthwhile.
Everything runs locally in SQLite. There is no service, no account, and no network access.
install once -> work normally -> OpenReflex learns continuously
Install (under 2 minutes)
pipx install openreflex # or: uv tool install openreflex (puts `openreflex` on PATH)
cd your-project
openreflex install claude-code # or codex | cursor | opencode; also enables the project
install writes project-level hook and MCP config for one agent, merging with any existing files, and approves
the project. Use --dry-run to preview the changes.
Plugin install (no project files)
| Agent | How |
|---|---|
| Claude Code | claude plugin marketplace add vishnu-77/openreflex then claude plugin install openreflex@openreflex, then openreflex approve in each project |
| Codex | codex plugin marketplace add vishnu-77/openreflex (reads .agents/plugins/marketplace.json), enable the plugin, trust its hooks once in /hooks, then openreflex approve |
| Cursor | copy plugins/openreflex to ~/.cursor/plugins/local/openreflex, then openreflex approve |
Nothing is captured in a project until it is approved. An unapproved project shows a one-line notice at most
once a day. To stop capture, run openreflex revoke. To delete a project's data, run openreflex forget --yes.
How it works
agent hooks ──► openreflex hook <agent> <event> ──► Engine ──► Experience Graph (SQLite)
prompt normalize payload per agent │
tool start (hooks.py) ├─ before: retrieve experience, score 3 candidate
tool end │ paths, render Execution Context
compaction ├─ during: detect failure loops, repeated calls,
stop │ stagnation, context growth, over-budget
└─ after: infer outcome + chosen path, estimate
agent ◄── additionalContext / alerts ◄──────────────────── Execution Regret, extract lessons
agent ──► MCP tools (get_execution_context, choose_path, record_outcome, search_experience, ...)
Experience Graph. The nodes are Task, Context, CandidatePath, Execution, ToolCall, Outcome,
Experience, and Lesson. They are connected by used, caused, failed_with, resolved_by, and
recommended_for:
Task -caused-> Execution -used-> Context -used-> Experience
CandidatePath -recommended_for-> Task Lesson -recommended_for-> Task
Execution -failed_with-> ToolCall -resolved_by-> ToolCall (the edit that fixed it)
Execution -caused-> Outcome -caused-> Experience -caused-> Lesson
Before a task. A prompt counts as substantial if it has at least 5 words and isn't a follow-up like "yes, continue". For those prompts, OpenReflex:
- Retrieves similar past experiences.
- Scores
inspect-first,test-first, andincrementalon success probability, time, tool calls, context cost, risk, uncertainty, and reversibility. Each score is a Beta-style blend of a prior and observed outcomes. - Injects a context of at most 1,400 characters: the suggested path, alternatives, likely relevant files, and lessons.
Nothing is injected when there is no relevant experience, so a new project costs zero context tokens.
During a task. Each alert kind fires at most once per execution, with a 3-minute cooldown. Stagnation is only judged after implementation has started, so exploratory reading does not trigger it. An alert names a concrete alternative path and any known fix for the current error.
After a task. The Stop hook finalizes the execution. Later turns reopen it and finalize it again, so the
same task keeps one experience. Outcome and chosen path come from record_outcome/choose_path when the agent
calls them. Otherwise they are inferred: only a check that passed or failed after the last edit counts as
evidence. Execution Regret is the best alternative's expected utility minus the chosen path's realized
utility. It is withheld (not guessed) when the outcome is unknown.
Agent integrations
| Prompt context | Tool capture | Failure signal | Alerts delivered via | Turn end | |
|---|---|---|---|---|---|
| Claude Code | UserPromptSubmit additionalContext |
Pre/PostToolUse | PostToolUseFailure |
PostToolUse additionalContext | Stop |
| Codex | UserPromptSubmit additionalContext |
Pre/PostToolUse | parsed from tool_response |
PostToolUse additionalContext | Stop |
| Cursor | deferred to first postToolUse* |
pre/postToolUse | postToolUseFailure |
postToolUse additional_context |
stop |
| OpenCode | system-prompt transform (plugin) | tool.execute.before/after | message.part.updated error |
appended to tool output | session.idle |
* Cursor's beforeSubmitPrompt cannot inject context, so the context is held until the first tool result.
Cursor can also run Claude Code hook configs. Those calls are attributed to Cursor and de-duplicated.
Claude Code is verified in live sessions (see Testing). The Codex, Cursor, and OpenCode adapters follow each agent's documented hook protocol (checked September 2026) and are tested with protocol-shaped and fuzzed payloads, but have not yet run inside live sessions of those agents.
A hook always exits 0 and never blocks. Errors go to ~/.openreflex/logs/errors.log, which
openreflex doctor shows. Measured on Windows: median 381 ms per hook process, where bare Python startup
is about 255 ms. Sixteen parallel tool-call hooks were stored with no lost writes.
Privacy
- Stored per tool call: tool name, a coarse category (
read/edit/search/test/...), a SHA-256 fingerprint of the arguments, project-relative file paths, status, duration, output size, and a masked one-line error signature. Paths outside the project, file contents, command text, tool output, and transcripts are never stored. - Prompts are stored as task descriptions, at most 1,000 characters, with secrets (API keys, tokens, bearer headers, private keys) redacted.
- Data lives in
~/.openreflex/projects/<hash>/experience.sqlite3. SetOPENREFLEX_HOMEto relocate it, orOPENREFLEX_DISABLE=1to turn capture off everywhere.
CLI
| Command | Purpose |
|---|---|
install <agent> [--dry-run] |
Write project hooks + MCP config and approve the project |
approve / revoke |
Enable / disable capture for the current project |
status [--json] |
Capture, reuse, outcome, efficiency, regret and routing metrics |
context "<task>" |
Preview the Execution Context a task would get |
doctor |
Installation checks and recent hook errors |
forget --yes |
Delete the project's data |
benchmark |
Simulated baseline-vs-guided benchmark |
hook <agent> <event> / mcp |
Used by agent configs |
Measuring the success metrics
openreflex status --json reports these per project:
| Plan metric | Field |
|---|---|
| <2-minute activation | activation.seconds_to_first_task (approval → first captured task) |
| >70% first-session capture | activation.first_session_captured |
| >50% weekly active retention | engagement.active_week_ratio |
| >30% tasks benefiting | experience_reuse.benefit_rate |
| 20–30% fewer tool calls, 20% fewer tokens, 15% faster | efficiency_observational.*_change (observational only; confounded by task mix) |
| No success-rate regression | outcomes.success_rate |
| >70% routing agreement | routing.agreement vs. routing.retrospective_best |
| Declining regret | execution_regret.by_class[*].early vs recent |
Cross-project aggregation (retention across projects, fleet-level activation) belongs with M5 sync.
Benchmark (simulated)
openreflex benchmark runs synthetic coding tasks from five task families, in two arms, through the real
engine. Both arms send real hook events and read back the real contexts and alerts; only the guided arm acts on
them. Default run: 150 tasks per arm × 3 seeds.
| Metric | Baseline | Guided | Change | Target |
|---|---|---|---|---|
| Tool calls / task | 13.97 | 9.21 | −34% | −20…−30% |
| Output tokens / task | 13,008 | 8,394 | −36% | −20% |
| Time / task | 349 s | 230 s | −34% | −15% |
| Success rate | 0.687 | 0.809 | +0.12 | ≥ baseline |
| Regret, first → last quarter | 0.107 → 0.103 | 0.079 → 0.036 | declining | |
| Routing agreement (2nd half) | – | 0.698 | > 0.70 (just missed) |
How to read this. These are properties of the simulator, not evidence of real-world gains. Most of the
tool-call and token reduction comes from one assumption: a relevant-files hint cuts search and read calls from
6–9 down to 2–3. Time is modeled as calls × 25 s, so it moves exactly with calls. All assumptions are listed in
SIMULATION_ASSUMPTIONS in benchmark.py and written into the JSON report. What the benchmark does show: the
engine learns family-specific best strategies from noisy outcomes, regret declines, and alerts shorten failure
loops. Routing agreement falls short because candidate evidence is pooled per task class, so families in the
same class that prefer different strategies dilute each other.
Status
| Milestone | State |
|---|---|
| M1: local engine, schemas, telemetry, MCP, agent integration | Done, for four agents |
| M2: retrieval, graph, Execution Context, cross-session memory | Done. Embeddings are offline lexical feature hashing, not a semantic model |
| M3: candidate paths, risk/reward scoring, live inefficiency detection | Done (deterministic) |
| M4: regret, lessons, cross-agent support, benchmark suite | Done. The benchmark is simulated; a real-task A/B harness is still to do |
| M5: learned Trajectory Router, cloud sync, team sharing | Not started |
Suggested next steps, in order:
- Run the Codex, Cursor, and OpenCode integrations in live sessions and fix protocol drift.
- Weight candidate evidence by similarity instead of pooling by task class; this is the cause of the routing-agreement miss.
- Build a real-task A/B harness: the same task set with capture on and off.
- Add a pluggable semantic embedder (keep lexical as the offline default) and a vector index once there are more than ~5k experiences.
- M5.
Testing
| Layer | What runs | Where |
|---|---|---|
| Unit + integration | Engine, adapters for all 4 agents, installers, CLI subprocesses, MCP, metrics, benchmark | CI: Linux, macOS, Windows × Python 3.11–3.13 |
| Stress | 24 parallel hook-process pairs (no lost writes), 3,000-experience retrieval, 400 fuzzed hostile payloads across all agents (only unparseable JSON may be rejected) | CI matrix |
| Packaging | Build sdist + wheel, twine check --strict, install the wheel into a clean venv, smoke-test console script, hooks, status and MCP over stdio |
CI: Linux, macOS, Windows |
| Release | Publish to TestPyPI, then install from TestPyPI on 3 OSes and rerun the smoke test before PyPI | release.yml |
| Live agent | Real headless Claude Code sessions (scripts/live_claude_code.py) |
Local; needs a signed-in claude |
The live Claude Code scenarios assert on the captured graph and on the session transcript, not on model wording:
- plugin-capture: the plugin is loaded with
--plugin-dir; a real bug fix is captured with categorized tool calls, an inferred success, and lessons. - context-injection: a similar task in a new session gets an Execution Context naming the right file, and the transcript shows the model received it.
- failure-loop-alert: repeated failing test runs raise one alert, and the transcript shows it reached the model.
- mcp-tools: the plugin's MCP server starts inside Claude Code and
search_experiencereturns the captured files. - project-install:
openreflex install claude-codeworks without the plugin.
Development
pip install -e ".[dev]"
pytest # unit, integration, stress
ruff check src tests scripts
python scripts/live_claude_code.py # live Claude Code scenarios (real model calls, default haiku)
Layout: engine.py (event → graph), routing.py (retrieval features, candidates, utility), detect.py (live
alerts), learning.py (outcome/strategy inference, regret, lessons), hooks.py (agent adapters),
mcp_server.py, install.py, metrics.py, benchmark.py, integrations/opencode.ts, and
plugins/openreflex (Claude Code / Codex / Cursor plugin; its hook files are checked against install.py
by tests).
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file openreflex-0.1.0.tar.gz.
File metadata
- Download URL: openreflex-0.1.0.tar.gz
- Upload date:
- Size: 58.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d4fa0606daa188eca89bd85520f1ec6926ad0ed9b16d18713e96eac43ba1655a
|
|
| MD5 |
a28c81162b51286d90c4c1dd23c4dd38
|
|
| BLAKE2b-256 |
9fb0c7199c1f1beddf2f8f1645e19fe7beb766c6bbf4123e65539fb2fa171826
|
Provenance
The following attestation bundles were made for openreflex-0.1.0.tar.gz:
Publisher:
release.yml on vishnu-77/openreflex
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
openreflex-0.1.0.tar.gz -
Subject digest:
d4fa0606daa188eca89bd85520f1ec6926ad0ed9b16d18713e96eac43ba1655a - Sigstore transparency entry: 2821384918
- Sigstore integration time:
-
Permalink:
vishnu-77/openreflex@a7a53260f5f46d30ca7d23434cc3c4d74b225cba -
Branch / Tag:
refs/heads/main - Owner: https://github.com/vishnu-77
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a7a53260f5f46d30ca7d23434cc3c4d74b225cba -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file openreflex-0.1.0-py3-none-any.whl.
File metadata
- Download URL: openreflex-0.1.0-py3-none-any.whl
- Upload date:
- Size: 50.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
46371883e76acfc1b56f62c4b82f44e0640e8b017e97a368005ca35131437344
|
|
| MD5 |
246b7becda647f85afb1f2cf15254aee
|
|
| BLAKE2b-256 |
95de6743bf65964939d4d965db8548344a6614d3b7f8c5d696f1726213e03e50
|
Provenance
The following attestation bundles were made for openreflex-0.1.0-py3-none-any.whl:
Publisher:
release.yml on vishnu-77/openreflex
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
openreflex-0.1.0-py3-none-any.whl -
Subject digest:
46371883e76acfc1b56f62c4b82f44e0640e8b017e97a368005ca35131437344 - Sigstore transparency entry: 2821385092
- Sigstore integration time:
-
Permalink:
vishnu-77/openreflex@a7a53260f5f46d30ca7d23434cc3c4d74b225cba -
Branch / Tag:
refs/heads/main - Owner: https://github.com/vishnu-77
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a7a53260f5f46d30ca7d23434cc3c4d74b225cba -
Trigger Event:
workflow_dispatch
-
Statement type: