openreflex 0.3.0__tar.gz → 0.3.2__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 (41) hide show
  1. {openreflex-0.3.0/src/openreflex.egg-info → openreflex-0.3.2}/PKG-INFO +90 -57
  2. {openreflex-0.3.0 → openreflex-0.3.2}/README.md +89 -56
  3. {openreflex-0.3.0 → openreflex-0.3.2}/pyproject.toml +1 -1
  4. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/__init__.py +1 -1
  5. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/engine.py +37 -1
  6. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/hooks.py +2 -1
  7. openreflex-0.3.2/src/openreflex/mcp_server.py +355 -0
  8. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/store.py +5 -0
  9. {openreflex-0.3.0 → openreflex-0.3.2/src/openreflex.egg-info}/PKG-INFO +90 -57
  10. {openreflex-0.3.0 → openreflex-0.3.2}/tests/test_hooks.py +27 -0
  11. {openreflex-0.3.0 → openreflex-0.3.2}/tests/test_mcp_metrics_benchmark.py +23 -5
  12. openreflex-0.3.0/src/openreflex/mcp_server.py +0 -280
  13. {openreflex-0.3.0 → openreflex-0.3.2}/LICENSE +0 -0
  14. {openreflex-0.3.0 → openreflex-0.3.2}/setup.cfg +0 -0
  15. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/__main__.py +0 -0
  16. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/benchmark.py +0 -0
  17. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/cli.py +0 -0
  18. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/control.py +0 -0
  19. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/decision.py +0 -0
  20. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/detect.py +0 -0
  21. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/install.py +0 -0
  22. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/integrations/opencode.ts +0 -0
  23. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/learning.py +0 -0
  24. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/metrics.py +0 -0
  25. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/models.py +0 -0
  26. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/policies/default.toml +0 -0
  27. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/policy.py +0 -0
  28. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/privacy.py +0 -0
  29. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/project.py +0 -0
  30. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex/routing.py +0 -0
  31. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex.egg-info/SOURCES.txt +0 -0
  32. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex.egg-info/dependency_links.txt +0 -0
  33. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex.egg-info/entry_points.txt +0 -0
  34. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex.egg-info/requires.txt +0 -0
  35. {openreflex-0.3.0 → openreflex-0.3.2}/src/openreflex.egg-info/top_level.txt +0 -0
  36. {openreflex-0.3.0 → openreflex-0.3.2}/tests/test_engine.py +0 -0
  37. {openreflex-0.3.0 → openreflex-0.3.2}/tests/test_install_cli.py +0 -0
  38. {openreflex-0.3.0 → openreflex-0.3.2}/tests/test_policy_recap.py +0 -0
  39. {openreflex-0.3.0 → openreflex-0.3.2}/tests/test_reliability_lifecycle.py +0 -0
  40. {openreflex-0.3.0 → openreflex-0.3.2}/tests/test_routing_control.py +0 -0
  41. {openreflex-0.3.0 → openreflex-0.3.2}/tests/test_stress.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openreflex
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: Muscle memory for AI coding agents: learns from every task, advises the next one, and flags failure loops live
5
5
  Author: vishnu-77
6
6
  License-Expression: MIT
@@ -35,19 +35,18 @@ Dynamic: license-file
35
35
 
36
36
  <a href="https://openreflex.cc" target="_blank">
37
37
  <picture>
38
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/openreflex-logo-dark.svg">
39
- <img alt="OpenReflex" src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/openreflex-logo-light.svg" width="380" height="auto">
38
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/openreflex-banner-dark.svg">
39
+ <img alt="OpenReflex: muscle memory for AI coding agents" src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/openreflex-banner-light.svg" width="720" height="auto">
40
40
  </picture>
41
41
  </a>
42
42
 
43
- ### OpenReflex: muscle memory for AI coding agents
44
-
45
- <a href="https://openreflex.cc">Website</a> · <a href="https://github.com/vishnu-77/openreflex">GitHub</a> · <a href="https://pypi.org/project/openreflex/">PyPI</a> · <a href="https://github.com/vishnu-77/openreflex/issues">Issues</a> · <a href="https://buymeacoffee.com/vishnuprashanth">Buy me a coffee</a>
43
+ <a href="https://openreflex.cc">Website</a> · <a href="https://openreflex.cc/docs">Docs</a> · <a href="docs/walkthrough.md">Walkthrough</a> · <a href="https://pypi.org/project/openreflex/">PyPI</a> · <a href="https://github.com/vishnu-77/openreflex/issues">Issues</a> · <a href="https://buymeacoffee.com/vishnuprashanth">Buy me a coffee</a>
46
44
 
47
45
  [![PyPI](https://img.shields.io/pypi/v/openreflex?style=flat-square&labelColor=black&color=286a70)](https://pypi.org/project/openreflex/)
48
46
  [![Python](https://img.shields.io/pypi/pyversions/openreflex?style=flat-square&labelColor=black&color=7cc9c8)](https://pypi.org/project/openreflex/)
49
47
  [![CI](https://img.shields.io/github/actions/workflow/status/vishnu-77/openreflex/ci.yml?branch=main&style=flat-square&labelColor=black&label=CI)](https://github.com/vishnu-77/openreflex/actions/workflows/ci.yml)
50
48
  [![License](https://img.shields.io/badge/license-MIT-white?style=flat-square&labelColor=black)](https://github.com/vishnu-77/openreflex/blob/main/LICENSE)
49
+ [![Glama score](https://glama.ai/mcp/servers/vishnu-77/openreflex/badges/score.svg)](https://glama.ai/mcp/servers/vishnu-77/openreflex)
51
50
 
52
51
  </div>
53
52
 
@@ -62,28 +61,33 @@ before: the approach, the files that mattered, and the fix for the error you hit
62
61
  You install it once and keep working normally. Everything stays on your machine in a local SQLite database.
63
62
  There is no account, no service, and no telemetry.
64
63
 
64
+ <p align="center">
65
+ <a href="docs/walkthrough.md">
66
+ <img alt="Recording of a real Claude Code session with OpenReflex: OpenReflex reports one similar past task and adds 162 context tokens, Claude finds and fixes the coupon bug, runs the tests, records the verified outcome through OpenReflex's MCP tool, and OpenReflex shows the completion recap with the path taken, cost and regret" src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/docs/screenshots/claude-code-session.gif" width="860">
67
+ </a>
68
+ <br>
69
+ <sub>A real Claude Code session, recorded from the terminal and sped up. OpenReflex had seen one similar task in this repository, so it adds 162 tokens of context before the first tool call; after the fix, Claude records the outcome through OpenReflex's MCP tool. The step-by-step walkthrough is in <a href="docs/walkthrough.md">docs/walkthrough.md</a>.</sub>
70
+ </p>
71
+
65
72
  ## Why OpenReflex
66
73
 
67
74
  - **It remembers what worked.** Before a substantial task, OpenReflex retrieves similar past tasks and injects a
68
75
  compact Execution Context: a suggested approach with alternatives, the files that were changed, and lessons
69
76
  such as which edit resolved a recurring error.
70
77
  - **It catches loops while they happen.** Repeated failing commands, identical retries, stalled progress, and
71
- runaway context growth raise a single, specific alert with an alternative path, never a stream of nags.
78
+ runaway context growth raise one alert that says whether to continue, pivot to another approach, or stop and
79
+ check in with you, never a stream of nags.
72
80
  - **It learns after every task.** OpenReflex infers the outcome from real verification (a test or build that
73
81
  passed or failed after the last edit), estimates Execution Regret against the alternatives, and extracts lessons.
74
82
  - **It is private by design.** Only coarse, project-relative metadata is stored. File contents, commands, tool
75
83
  output, and transcripts never are, and capture is off until you approve a project.
76
84
 
77
- ```
78
- before a task during a task after a task
79
- ┌──────────────────────┐ ┌──────────────────────────┐ ┌───────────────────────┐
80
- │ retrieve experience │ │ watch tool calls │ │ infer outcome │
81
- │ score candidate paths│ → │ flag loops and stalls │ → │ estimate regret │
82
- │ inject context │ │ suggest an alternative │ │ extract lessons │
83
- └──────────────────────┘ └──────────────────────────┘ └───────────────────────┘
84
- ▲ │
85
- └──────────────────── Experience Graph ◄─────────────────┘
86
- ```
85
+ <p align="center">
86
+ <picture>
87
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/how-it-works-dark.svg">
88
+ <img alt="Before a task: retrieve similar experience, score candidate paths, inject context and a budget. During a task: watch every tool call, flag loops and stalls, advise continue, pivot or stop. After a task: infer the outcome from checks, estimate Execution Regret, extract lessons. Lessons feed the Experience Graph for the next task." src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/how-it-works-light.svg" width="860">
89
+ </picture>
90
+ </p>
87
91
 
88
92
  ## Quick start
89
93
 
@@ -95,6 +99,19 @@ cd your-project
95
99
  openreflex install claude-code # writes hooks + MCP config and enables this project
96
100
  ```
97
101
 
102
+ ```
103
+ OPENREFLEX / CONNECT
104
+ agent claude-code
105
+ project D:\demo\shop
106
+ config updated 2 files
107
+ D:\demo\shop\.claude\settings.json
108
+ D:\demo\shop\.mcp.json
109
+ memory enabled
110
+ storage local
111
+
112
+ [ok] reflex active
113
+ ```
114
+
98
115
  Then work as usual. After a few tasks:
99
116
 
100
117
  ```bash
@@ -107,37 +124,16 @@ openreflex doctor # installation checks and rece
107
124
 
108
125
  OpenReflex installs per project with `openreflex install <agent>`, or as a plugin.
109
126
 
110
- <table>
111
- <tbody>
112
- <tr>
113
- <td align="center" valign="bottom" width="25%"><strong>Claude&nbsp;Code</strong><br><sub>Plugin&nbsp;or&nbsp;hooks&nbsp;+&nbsp;MCP</sub></td>
114
- <td align="center" valign="bottom" width="25%"><strong>Codex</strong><br><sub>Plugin&nbsp;or&nbsp;hooks&nbsp;+&nbsp;MCP</sub></td>
115
- <td align="center" valign="bottom" width="25%"><strong>Cursor</strong><br><sub>Hooks&nbsp;+&nbsp;MCP</sub></td>
116
- <td align="center" valign="bottom" width="25%"><strong>OpenCode</strong><br><sub>Plugin&nbsp;+&nbsp;MCP</sub></td>
117
- </tr>
118
- </tbody>
119
- </table>
120
-
121
- | Agent | Install |
122
- |---|---|
123
- | Claude Code | `claude plugin marketplace add vishnu-77/openreflex` and `claude plugin install openreflex@openreflex`, or `openreflex install claude-code` |
124
- | Codex | `codex plugin marketplace add vishnu-77/openreflex`, or `openreflex install codex`, then trust the hooks once in `/hooks` |
125
- | Cursor | `openreflex install cursor` |
126
- | OpenCode | `openreflex install opencode` |
127
-
128
- With a plugin install, enable each project with `openreflex approve`. Claude Code and Codex are verified in live
129
- sessions; the Cursor and OpenCode integrations follow each agent's documented hook protocol.
130
-
131
- ## See it work
127
+ | Agent | Connects through | Install | Verified |
128
+ |---|---|---|---|
129
+ | **Claude Code** | Plugin, or hooks + MCP | `claude plugin marketplace add vishnu-77/openreflex` then `claude plugin install openreflex@openreflex`, or `openreflex install claude-code` | Live sessions |
130
+ | **Codex** | Plugin, or hooks + MCP | `codex plugin marketplace add vishnu-77/openreflex`, or `openreflex install codex`, then trust the hooks once in `/hooks` | Live sessions |
131
+ | **Cursor** | Hooks + MCP | `openreflex install cursor` | Protocol and fuzz tests |
132
+ | **OpenCode** | Plugin + MCP | `openreflex install opencode` | Protocol and fuzz tests |
132
133
 
133
- A real Claude Code session in a repository where OpenReflex has seen one similar task before. The
134
- `UserPromptSubmit` line shows the past experience found and the context added; the `Stop` line shows the verified
135
- outcome, the path taken and the cost.
136
-
137
- ![Claude Code session with OpenReflex](https://raw.githubusercontent.com/vishnu-77/openreflex/main/docs/screenshots/claude-code-session-2.png)
138
-
139
- The full walkthrough, with both sessions, the exact context the model received and the CLI output, is in
140
- [docs/walkthrough.md](docs/walkthrough.md).
134
+ With a plugin install, enable each project with `openreflex approve`. Per-agent guides:
135
+ [Claude Code](https://openreflex.cc/claude-code), [Codex](https://openreflex.cc/codex), [Cursor](https://openreflex.cc/cursor),
136
+ [OpenCode](https://openreflex.cc/opencode).
141
137
 
142
138
  ## How it works
143
139
 
@@ -177,10 +173,27 @@ Set optional limits for every task with `OPENREFLEX_BUDGET`, for example `calls=
177
173
  Routing, scoring, budget and recap settings come from a versioned policy: the packaged defaults, overridden by
178
174
  `~/.openreflex/config.toml` and then by `.openreflex.toml` in the project.
179
175
 
180
- Agents can also query OpenReflex directly through its MCP server: `get_execution_context` (optionally with
181
- `max_tool_calls`, `max_minutes`, `max_context_tokens`), `choose_path`, `check_progress`, `explain_decision`,
182
- `get_execution_trace`, `get_reflex_score`, `record_outcome`, `search_experience`, `explain_node`,
183
- `project_insights`, and `approve_project`.
176
+ Agents can also query OpenReflex directly through its MCP server.
177
+
178
+ <details>
179
+ <summary><strong>The 12 MCP tools</strong></summary>
180
+
181
+ | Tool | What it does |
182
+ |---|---|
183
+ | `get_execution_context` | Plan a task: similar past tasks, the suggested strategy with alternatives, a budget, likely files, lessons. Optional `max_tool_calls`, `max_minutes`, `max_context_tokens`. |
184
+ | `check_progress` | Whether more work on the current path is worth it: continue, pivot or stop. |
185
+ | `choose_path` | Declare the strategy being followed when it differs from the suggestion. |
186
+ | `record_outcome` | Record a verified outcome (tests passed, user confirmed, or failure) and learn from it. |
187
+ | `explain_decision` | Why the latest recommendation was made: Reflex Score, signals, confidence, next-best route. |
188
+ | `get_execution_trace` | The decision timeline of the most recent task. |
189
+ | `get_reflex_score` | The latest Reflex Score and its components as JSON. |
190
+ | `search_experience` | Past tasks in the project by description similarity, with their lessons. |
191
+ | `explain_node` | One Experience Graph node and its relations. |
192
+ | `get_project_insights` | What has been recorded, reused and learned in the project. |
193
+ | `approve_project` | Enable capture, only when the user explicitly asks. |
194
+ | `forget_experience` | Delete one past task's memory, only when the user explicitly asks. |
195
+
196
+ </details>
184
197
 
185
198
  ## CLI
186
199
 
@@ -199,12 +212,26 @@ Agents can also query OpenReflex directly through its MCP server: `get_execution
199
212
 
200
213
  ## Privacy
201
214
 
202
- - Stored per tool call: tool name, a coarse category (`read`, `edit`, `search`, `test`, ...), a fingerprint of the
203
- arguments, project-relative file paths, status, duration, output size, and a masked one-line error signature.
204
- - Never stored: file contents, command text, tool output, transcripts, or paths outside the project.
205
- - Prompts are kept as task descriptions (up to 1,000 characters) with secrets such as API keys and tokens redacted.
206
- - Data lives in `~/.openreflex/projects/<hash>/experience.sqlite3`. Set `OPENREFLEX_HOME` to move it,
207
- `OPENREFLEX_DISABLE=1` to turn capture off everywhere, or run `openreflex forget --yes` to delete a project's data.
215
+ | Stored | Never stored |
216
+ |---|---|
217
+ | Tool name and a coarse category (`read`, `edit`, `search`, `test`, ...) | File contents |
218
+ | A fingerprint of the arguments | Command text |
219
+ | Project-relative file paths | Tool output |
220
+ | Pass or fail, duration, output size | Transcripts and model output |
221
+ | A masked one-line error signature | Paths outside the project |
222
+ | The prompt as a task description (up to 1,000 characters, secrets redacted) | Anything sent to a server: there is none |
223
+
224
+ Data lives in `~/.openreflex/projects/<hash>/experience.sqlite3`. Set `OPENREFLEX_HOME` to move it,
225
+ `OPENREFLEX_DISABLE=1` to turn capture off everywhere, `openreflex forget --yes` to delete a project's data, or ask
226
+ your agent to `forget_experience` a single task.
227
+
228
+ ## Research
229
+
230
+ OpenReflex is also a research project in budget-aware execution: instead of treating success as a yes or no, it
231
+ studies how agents choose execution paths, spend tool calls and context, respond to uncertainty, and whether more
232
+ computation still adds value. The loop is experience retrieval, Pareto path selection, budget-aware execution and
233
+ counterfactual regret. The [Researcher view](https://openreflex.cc/?view=research) on the site explains the idea,
234
+ lets you step through one reflex forming in the graph, and places it next to related work.
208
235
 
209
236
  ## Community & Contributing
210
237
 
@@ -222,6 +249,12 @@ Agents can also query OpenReflex directly through its MCP server: `get_execution
222
249
  <img src="https://contrib.rocks/image?repo=vishnu-77/openreflex" alt="Contributors">
223
250
  </a>
224
251
 
252
+ OpenReflex is listed in the [MCP Registry](https://registry.modelcontextprotocol.io) as `io.github.vishnu-77/openreflex` and on Glama:
253
+
254
+ <a href="https://glama.ai/mcp/servers/vishnu-77/openreflex">
255
+ <img src="https://glama.ai/mcp/servers/vishnu-77/openreflex/badges/card.svg" alt="OpenReflex MCP server: quality and maintenance score on Glama" width="380">
256
+ </a>
257
+
225
258
  ## License
226
259
 
227
260
  OpenReflex is released under the [MIT License](https://github.com/vishnu-77/openreflex/blob/main/LICENSE).
@@ -3,19 +3,18 @@
3
3
 
4
4
  <a href="https://openreflex.cc" target="_blank">
5
5
  <picture>
6
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/openreflex-logo-dark.svg">
7
- <img alt="OpenReflex" src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/openreflex-logo-light.svg" width="380" height="auto">
6
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/openreflex-banner-dark.svg">
7
+ <img alt="OpenReflex: muscle memory for AI coding agents" src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/openreflex-banner-light.svg" width="720" height="auto">
8
8
  </picture>
9
9
  </a>
10
10
 
11
- ### OpenReflex: muscle memory for AI coding agents
12
-
13
- <a href="https://openreflex.cc">Website</a> · <a href="https://github.com/vishnu-77/openreflex">GitHub</a> · <a href="https://pypi.org/project/openreflex/">PyPI</a> · <a href="https://github.com/vishnu-77/openreflex/issues">Issues</a> · <a href="https://buymeacoffee.com/vishnuprashanth">Buy me a coffee</a>
11
+ <a href="https://openreflex.cc">Website</a> · <a href="https://openreflex.cc/docs">Docs</a> · <a href="docs/walkthrough.md">Walkthrough</a> · <a href="https://pypi.org/project/openreflex/">PyPI</a> · <a href="https://github.com/vishnu-77/openreflex/issues">Issues</a> · <a href="https://buymeacoffee.com/vishnuprashanth">Buy me a coffee</a>
14
12
 
15
13
  [![PyPI](https://img.shields.io/pypi/v/openreflex?style=flat-square&labelColor=black&color=286a70)](https://pypi.org/project/openreflex/)
16
14
  [![Python](https://img.shields.io/pypi/pyversions/openreflex?style=flat-square&labelColor=black&color=7cc9c8)](https://pypi.org/project/openreflex/)
17
15
  [![CI](https://img.shields.io/github/actions/workflow/status/vishnu-77/openreflex/ci.yml?branch=main&style=flat-square&labelColor=black&label=CI)](https://github.com/vishnu-77/openreflex/actions/workflows/ci.yml)
18
16
  [![License](https://img.shields.io/badge/license-MIT-white?style=flat-square&labelColor=black)](https://github.com/vishnu-77/openreflex/blob/main/LICENSE)
17
+ [![Glama score](https://glama.ai/mcp/servers/vishnu-77/openreflex/badges/score.svg)](https://glama.ai/mcp/servers/vishnu-77/openreflex)
19
18
 
20
19
  </div>
21
20
 
@@ -30,28 +29,33 @@ before: the approach, the files that mattered, and the fix for the error you hit
30
29
  You install it once and keep working normally. Everything stays on your machine in a local SQLite database.
31
30
  There is no account, no service, and no telemetry.
32
31
 
32
+ <p align="center">
33
+ <a href="docs/walkthrough.md">
34
+ <img alt="Recording of a real Claude Code session with OpenReflex: OpenReflex reports one similar past task and adds 162 context tokens, Claude finds and fixes the coupon bug, runs the tests, records the verified outcome through OpenReflex's MCP tool, and OpenReflex shows the completion recap with the path taken, cost and regret" src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/docs/screenshots/claude-code-session.gif" width="860">
35
+ </a>
36
+ <br>
37
+ <sub>A real Claude Code session, recorded from the terminal and sped up. OpenReflex had seen one similar task in this repository, so it adds 162 tokens of context before the first tool call; after the fix, Claude records the outcome through OpenReflex's MCP tool. The step-by-step walkthrough is in <a href="docs/walkthrough.md">docs/walkthrough.md</a>.</sub>
38
+ </p>
39
+
33
40
  ## Why OpenReflex
34
41
 
35
42
  - **It remembers what worked.** Before a substantial task, OpenReflex retrieves similar past tasks and injects a
36
43
  compact Execution Context: a suggested approach with alternatives, the files that were changed, and lessons
37
44
  such as which edit resolved a recurring error.
38
45
  - **It catches loops while they happen.** Repeated failing commands, identical retries, stalled progress, and
39
- runaway context growth raise a single, specific alert with an alternative path, never a stream of nags.
46
+ runaway context growth raise one alert that says whether to continue, pivot to another approach, or stop and
47
+ check in with you, never a stream of nags.
40
48
  - **It learns after every task.** OpenReflex infers the outcome from real verification (a test or build that
41
49
  passed or failed after the last edit), estimates Execution Regret against the alternatives, and extracts lessons.
42
50
  - **It is private by design.** Only coarse, project-relative metadata is stored. File contents, commands, tool
43
51
  output, and transcripts never are, and capture is off until you approve a project.
44
52
 
45
- ```
46
- before a task during a task after a task
47
- ┌──────────────────────┐ ┌──────────────────────────┐ ┌───────────────────────┐
48
- │ retrieve experience │ │ watch tool calls │ │ infer outcome │
49
- │ score candidate paths│ → │ flag loops and stalls │ → │ estimate regret │
50
- │ inject context │ │ suggest an alternative │ │ extract lessons │
51
- └──────────────────────┘ └──────────────────────────┘ └───────────────────────┘
52
- ▲ │
53
- └──────────────────── Experience Graph ◄─────────────────┘
54
- ```
53
+ <p align="center">
54
+ <picture>
55
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/how-it-works-dark.svg">
56
+ <img alt="Before a task: retrieve similar experience, score candidate paths, inject context and a budget. During a task: watch every tool call, flag loops and stalls, advise continue, pivot or stop. After a task: infer the outcome from checks, estimate Execution Regret, extract lessons. Lessons feed the Experience Graph for the next task." src="https://raw.githubusercontent.com/vishnu-77/openreflex/main/assets/how-it-works-light.svg" width="860">
57
+ </picture>
58
+ </p>
55
59
 
56
60
  ## Quick start
57
61
 
@@ -63,6 +67,19 @@ cd your-project
63
67
  openreflex install claude-code # writes hooks + MCP config and enables this project
64
68
  ```
65
69
 
70
+ ```
71
+ OPENREFLEX / CONNECT
72
+ agent claude-code
73
+ project D:\demo\shop
74
+ config updated 2 files
75
+ D:\demo\shop\.claude\settings.json
76
+ D:\demo\shop\.mcp.json
77
+ memory enabled
78
+ storage local
79
+
80
+ [ok] reflex active
81
+ ```
82
+
66
83
  Then work as usual. After a few tasks:
67
84
 
68
85
  ```bash
@@ -75,37 +92,16 @@ openreflex doctor # installation checks and rece
75
92
 
76
93
  OpenReflex installs per project with `openreflex install <agent>`, or as a plugin.
77
94
 
78
- <table>
79
- <tbody>
80
- <tr>
81
- <td align="center" valign="bottom" width="25%"><strong>Claude&nbsp;Code</strong><br><sub>Plugin&nbsp;or&nbsp;hooks&nbsp;+&nbsp;MCP</sub></td>
82
- <td align="center" valign="bottom" width="25%"><strong>Codex</strong><br><sub>Plugin&nbsp;or&nbsp;hooks&nbsp;+&nbsp;MCP</sub></td>
83
- <td align="center" valign="bottom" width="25%"><strong>Cursor</strong><br><sub>Hooks&nbsp;+&nbsp;MCP</sub></td>
84
- <td align="center" valign="bottom" width="25%"><strong>OpenCode</strong><br><sub>Plugin&nbsp;+&nbsp;MCP</sub></td>
85
- </tr>
86
- </tbody>
87
- </table>
88
-
89
- | Agent | Install |
90
- |---|---|
91
- | Claude Code | `claude plugin marketplace add vishnu-77/openreflex` and `claude plugin install openreflex@openreflex`, or `openreflex install claude-code` |
92
- | Codex | `codex plugin marketplace add vishnu-77/openreflex`, or `openreflex install codex`, then trust the hooks once in `/hooks` |
93
- | Cursor | `openreflex install cursor` |
94
- | OpenCode | `openreflex install opencode` |
95
-
96
- With a plugin install, enable each project with `openreflex approve`. Claude Code and Codex are verified in live
97
- sessions; the Cursor and OpenCode integrations follow each agent's documented hook protocol.
98
-
99
- ## See it work
95
+ | Agent | Connects through | Install | Verified |
96
+ |---|---|---|---|
97
+ | **Claude Code** | Plugin, or hooks + MCP | `claude plugin marketplace add vishnu-77/openreflex` then `claude plugin install openreflex@openreflex`, or `openreflex install claude-code` | Live sessions |
98
+ | **Codex** | Plugin, or hooks + MCP | `codex plugin marketplace add vishnu-77/openreflex`, or `openreflex install codex`, then trust the hooks once in `/hooks` | Live sessions |
99
+ | **Cursor** | Hooks + MCP | `openreflex install cursor` | Protocol and fuzz tests |
100
+ | **OpenCode** | Plugin + MCP | `openreflex install opencode` | Protocol and fuzz tests |
100
101
 
101
- A real Claude Code session in a repository where OpenReflex has seen one similar task before. The
102
- `UserPromptSubmit` line shows the past experience found and the context added; the `Stop` line shows the verified
103
- outcome, the path taken and the cost.
104
-
105
- ![Claude Code session with OpenReflex](https://raw.githubusercontent.com/vishnu-77/openreflex/main/docs/screenshots/claude-code-session-2.png)
106
-
107
- The full walkthrough, with both sessions, the exact context the model received and the CLI output, is in
108
- [docs/walkthrough.md](docs/walkthrough.md).
102
+ With a plugin install, enable each project with `openreflex approve`. Per-agent guides:
103
+ [Claude Code](https://openreflex.cc/claude-code), [Codex](https://openreflex.cc/codex), [Cursor](https://openreflex.cc/cursor),
104
+ [OpenCode](https://openreflex.cc/opencode).
109
105
 
110
106
  ## How it works
111
107
 
@@ -145,10 +141,27 @@ Set optional limits for every task with `OPENREFLEX_BUDGET`, for example `calls=
145
141
  Routing, scoring, budget and recap settings come from a versioned policy: the packaged defaults, overridden by
146
142
  `~/.openreflex/config.toml` and then by `.openreflex.toml` in the project.
147
143
 
148
- Agents can also query OpenReflex directly through its MCP server: `get_execution_context` (optionally with
149
- `max_tool_calls`, `max_minutes`, `max_context_tokens`), `choose_path`, `check_progress`, `explain_decision`,
150
- `get_execution_trace`, `get_reflex_score`, `record_outcome`, `search_experience`, `explain_node`,
151
- `project_insights`, and `approve_project`.
144
+ Agents can also query OpenReflex directly through its MCP server.
145
+
146
+ <details>
147
+ <summary><strong>The 12 MCP tools</strong></summary>
148
+
149
+ | Tool | What it does |
150
+ |---|---|
151
+ | `get_execution_context` | Plan a task: similar past tasks, the suggested strategy with alternatives, a budget, likely files, lessons. Optional `max_tool_calls`, `max_minutes`, `max_context_tokens`. |
152
+ | `check_progress` | Whether more work on the current path is worth it: continue, pivot or stop. |
153
+ | `choose_path` | Declare the strategy being followed when it differs from the suggestion. |
154
+ | `record_outcome` | Record a verified outcome (tests passed, user confirmed, or failure) and learn from it. |
155
+ | `explain_decision` | Why the latest recommendation was made: Reflex Score, signals, confidence, next-best route. |
156
+ | `get_execution_trace` | The decision timeline of the most recent task. |
157
+ | `get_reflex_score` | The latest Reflex Score and its components as JSON. |
158
+ | `search_experience` | Past tasks in the project by description similarity, with their lessons. |
159
+ | `explain_node` | One Experience Graph node and its relations. |
160
+ | `get_project_insights` | What has been recorded, reused and learned in the project. |
161
+ | `approve_project` | Enable capture, only when the user explicitly asks. |
162
+ | `forget_experience` | Delete one past task's memory, only when the user explicitly asks. |
163
+
164
+ </details>
152
165
 
153
166
  ## CLI
154
167
 
@@ -167,12 +180,26 @@ Agents can also query OpenReflex directly through its MCP server: `get_execution
167
180
 
168
181
  ## Privacy
169
182
 
170
- - Stored per tool call: tool name, a coarse category (`read`, `edit`, `search`, `test`, ...), a fingerprint of the
171
- arguments, project-relative file paths, status, duration, output size, and a masked one-line error signature.
172
- - Never stored: file contents, command text, tool output, transcripts, or paths outside the project.
173
- - Prompts are kept as task descriptions (up to 1,000 characters) with secrets such as API keys and tokens redacted.
174
- - Data lives in `~/.openreflex/projects/<hash>/experience.sqlite3`. Set `OPENREFLEX_HOME` to move it,
175
- `OPENREFLEX_DISABLE=1` to turn capture off everywhere, or run `openreflex forget --yes` to delete a project's data.
183
+ | Stored | Never stored |
184
+ |---|---|
185
+ | Tool name and a coarse category (`read`, `edit`, `search`, `test`, ...) | File contents |
186
+ | A fingerprint of the arguments | Command text |
187
+ | Project-relative file paths | Tool output |
188
+ | Pass or fail, duration, output size | Transcripts and model output |
189
+ | A masked one-line error signature | Paths outside the project |
190
+ | The prompt as a task description (up to 1,000 characters, secrets redacted) | Anything sent to a server: there is none |
191
+
192
+ Data lives in `~/.openreflex/projects/<hash>/experience.sqlite3`. Set `OPENREFLEX_HOME` to move it,
193
+ `OPENREFLEX_DISABLE=1` to turn capture off everywhere, `openreflex forget --yes` to delete a project's data, or ask
194
+ your agent to `forget_experience` a single task.
195
+
196
+ ## Research
197
+
198
+ OpenReflex is also a research project in budget-aware execution: instead of treating success as a yes or no, it
199
+ studies how agents choose execution paths, spend tool calls and context, respond to uncertainty, and whether more
200
+ computation still adds value. The loop is experience retrieval, Pareto path selection, budget-aware execution and
201
+ counterfactual regret. The [Researcher view](https://openreflex.cc/?view=research) on the site explains the idea,
202
+ lets you step through one reflex forming in the graph, and places it next to related work.
176
203
 
177
204
  ## Community & Contributing
178
205
 
@@ -190,6 +217,12 @@ Agents can also query OpenReflex directly through its MCP server: `get_execution
190
217
  <img src="https://contrib.rocks/image?repo=vishnu-77/openreflex" alt="Contributors">
191
218
  </a>
192
219
 
220
+ OpenReflex is listed in the [MCP Registry](https://registry.modelcontextprotocol.io) as `io.github.vishnu-77/openreflex` and on Glama:
221
+
222
+ <a href="https://glama.ai/mcp/servers/vishnu-77/openreflex">
223
+ <img src="https://glama.ai/mcp/servers/vishnu-77/openreflex/badges/card.svg" alt="OpenReflex MCP server: quality and maintenance score on Glama" width="380">
224
+ </a>
225
+
193
226
  ## License
194
227
 
195
228
  OpenReflex is released under the [MIT License](https://github.com/vishnu-77/openreflex/blob/main/LICENSE).
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "openreflex"
7
- version = "0.3.0"
7
+ version = "0.3.2"
8
8
  description = "Muscle memory for AI coding agents: learns from every task, advises the next one, and flags failure loops live"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1,3 +1,3 @@
1
1
  """Ambient, local execution intelligence."""
2
2
 
3
- __version__ = "0.3.0"
3
+ __version__ = "0.3.2"
@@ -216,6 +216,36 @@ class Engine:
216
216
  raise ValueError("No execution to record an outcome for")
217
217
  return self._finalize(execution, status=status, evidence=redact(evidence, 500), verified=True)
218
218
 
219
+ def forget_experience(self, experience_id: str) -> dict[str, int]:
220
+ """Delete one past task and everything learned from it; returns how many nodes of each kind were removed."""
221
+ with self.store.transaction():
222
+ experience = self.store.get(experience_id) if self.store.exists(experience_id) else None
223
+ if not isinstance(experience, Experience):
224
+ raise ValueError("Unknown experience id")
225
+ removed: Counter = Counter()
226
+
227
+ def drop(node) -> None:
228
+ removed[type(node).__name__] += 1
229
+ self.store.delete(node.id)
230
+
231
+ for execution in self.store.list("Execution", "task_id", experience.task_id):
232
+ for call in self.store.list("ToolCall", "execution_id", execution.id, limit=5000):
233
+ drop(call)
234
+ for outcome in self.store.find("Outcome", execution_id=execution.id):
235
+ drop(outcome)
236
+ for item in self.store.find("Experience", execution_id=execution.id):
237
+ for lesson in self.store.list("Lesson", "experience_id", item.id):
238
+ drop(lesson)
239
+ drop(item)
240
+ self.store.forget_execution(execution.id)
241
+ drop(execution)
242
+ for kind in ("Context", "CandidatePath"):
243
+ for node in self.store.list(kind, "task_id", experience.task_id):
244
+ drop(node)
245
+ if self.store.exists(experience.task_id):
246
+ drop(self.store.get(experience.task_id))
247
+ return dict(removed)
248
+
219
249
  def preview(self, description: str) -> str:
220
250
  task = Task(description=redact(description, 1000), task_class=classify(description), session_id="preview",
221
251
  agent="preview", started_at=self.clock())
@@ -227,7 +257,13 @@ class Engine:
227
257
  budget_for(paths[0], limits, self.policy), self.policy)
228
258
 
229
259
  def decision_snapshots(self, execution_id: str | None = None) -> list[DecisionSnapshot]:
230
- execution = self.store.get(execution_id) if execution_id else self.current_execution(max_age=float("inf"))
260
+ """Snapshots of the given execution, or of the most recent one that made decisions. Activity without a
261
+ captured prompt (a resumed session, a tool call before any prompt) must not hide the latest explanation."""
262
+ if execution_id:
263
+ execution = self.store.get(execution_id)
264
+ else:
265
+ decided = [e for e in self.store.list("Execution", limit=200) if e.decision_history]
266
+ execution = max(decided, key=lambda e: e.started_at, default=None)
231
267
  if execution is None:
232
268
  return []
233
269
  return [DecisionSnapshot.from_dict(item) for item in execution.decision_history]
@@ -212,7 +212,8 @@ def handle(agent: str, name: str, payload: dict, engine_factory=Engine) -> str:
212
212
  agent = detect_agent(agent, payload)
213
213
  name = name or payload.get("hook_event_name") or payload.get("event") or ""
214
214
  event = normalize(agent, name, payload)
215
- if event.kind == "ignored" or not event.session:
215
+ # A tool event that names no tool is malformed; recording it would create a nameless call and a phantom task.
216
+ if event.kind == "ignored" or not event.session or (event.kind in ("tool_start", "tool_end") and not event.tool):
216
217
  return render(agent, name, None)
217
218
  project = project_root(event.cwd)
218
219
  if not approval(project):