openplot 1.0.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 (33) hide show
  1. openplot-1.0.0/PKG-INFO +332 -0
  2. openplot-1.0.0/README.md +304 -0
  3. openplot-1.0.0/pyproject.toml +43 -0
  4. openplot-1.0.0/src/openplot/__init__.py +3 -0
  5. openplot-1.0.0/src/openplot/api/__init__.py +1 -0
  6. openplot-1.0.0/src/openplot/api/schemas.py +132 -0
  7. openplot-1.0.0/src/openplot/cli.py +139 -0
  8. openplot-1.0.0/src/openplot/desktop.py +437 -0
  9. openplot-1.0.0/src/openplot/domain/__init__.py +1 -0
  10. openplot-1.0.0/src/openplot/domain/annotations.py +45 -0
  11. openplot-1.0.0/src/openplot/domain/regions.py +52 -0
  12. openplot-1.0.0/src/openplot/executor.py +726 -0
  13. openplot-1.0.0/src/openplot/feedback.py +141 -0
  14. openplot-1.0.0/src/openplot/mcp_server.py +353 -0
  15. openplot-1.0.0/src/openplot/models.py +408 -0
  16. openplot-1.0.0/src/openplot/release_versioning.py +305 -0
  17. openplot-1.0.0/src/openplot/server.py +11120 -0
  18. openplot-1.0.0/src/openplot/services/__init__.py +1 -0
  19. openplot-1.0.0/src/openplot/services/naming.py +75 -0
  20. openplot-1.0.0/src/openplot/static/assets/MarkdownRenderer-DqMDEmDw.js +2 -0
  21. openplot-1.0.0/src/openplot/static/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
  22. openplot-1.0.0/src/openplot/static/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
  23. openplot-1.0.0/src/openplot/static/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
  24. openplot-1.0.0/src/openplot/static/assets/iconify-xdk4cov8.js +1 -0
  25. openplot-1.0.0/src/openplot/static/assets/index-9qrwxLoh.css +1 -0
  26. openplot-1.0.0/src/openplot/static/assets/index-DhwX5yIi.js +19 -0
  27. openplot-1.0.0/src/openplot/static/assets/lucide-DCaNFHhh.js +1 -0
  28. openplot-1.0.0/src/openplot/static/assets/markdown-BgYhP8km.js +29 -0
  29. openplot-1.0.0/src/openplot/static/assets/openplot-DYqSIMi_.png +0 -0
  30. openplot-1.0.0/src/openplot/static/assets/react-vendor-C4hNv3Lv.js +9 -0
  31. openplot-1.0.0/src/openplot/static/assets/ui-DjPaK12C.js +12 -0
  32. openplot-1.0.0/src/openplot/static/index.html +17 -0
  33. openplot-1.0.0/src/openplot/static/vite.svg +1 -0
@@ -0,0 +1,332 @@
1
+ Metadata-Version: 2.3
2
+ Name: openplot
3
+ Version: 1.0.0
4
+ Summary: Makes plotting and fine-tuning plots easy and interactive.
5
+ Author: Philo Wu
6
+ Author-email: Philo Wu <philo.wu@codeboyphilo.ai>
7
+ Requires-Dist: fastapi>=0.115.0
8
+ Requires-Dist: uvicorn[standard]>=0.30.0
9
+ Requires-Dist: websockets>=13.0
10
+ Requires-Dist: click>=8.1.0
11
+ Requires-Dist: pydantic>=2.0.0
12
+ Requires-Dist: mcp>=1.26.0
13
+ Requires-Dist: numpy>=2.4.2
14
+ Requires-Dist: pandas>=3.0.1
15
+ Requires-Dist: matplotlib>=3.10.8
16
+ Requires-Dist: seaborn>=0.13.2
17
+ Requires-Dist: openpyxl>=3.1.5
18
+ Requires-Dist: pywebview>=5.2 ; sys_platform != 'linux' and extra == 'desktop'
19
+ Requires-Dist: pywebview[qt]>=5.2 ; sys_platform == 'linux' and extra == 'desktop'
20
+ Requires-Dist: pyobjc-core>=11.1 ; sys_platform == 'darwin' and extra == 'desktop'
21
+ Requires-Dist: pyobjc-framework-cocoa>=11.1 ; sys_platform == 'darwin' and extra == 'desktop'
22
+ Requires-Dist: pyobjc-framework-quartz>=11.1 ; sys_platform == 'darwin' and extra == 'desktop'
23
+ Requires-Dist: pyobjc-framework-security>=11.1 ; sys_platform == 'darwin' and extra == 'desktop'
24
+ Requires-Dist: pyobjc-framework-webkit>=11.1 ; sys_platform == 'darwin' and extra == 'desktop'
25
+ Requires-Python: >=3.12
26
+ Provides-Extra: desktop
27
+ Description-Content-Type: text/markdown
28
+
29
+ <p align="center">
30
+ <img src="frontend/openplot.png" alt="OpenPlot" width="520" />
31
+ </p>
32
+
33
+ <p align="center"><strong>The agentic plotting "IDE" built for everyone </strong></p>
34
+
35
+ <p align="center">
36
+ <img alt="Python 3.12+" src="https://img.shields.io/badge/python-3.12%2B-3776AB?logo=python&logoColor=white" />
37
+ <img alt="License: GPL-3.0" src="https://img.shields.io/badge/license-GPL--3.0-blue" />
38
+ <img alt="Platform" src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-lightgrey" />
39
+ </p>
40
+
41
+ ---
42
+
43
+ Agentic coding already makes plotting easier: give your data to an agent, and it can write a script for you in seconds.
44
+ But **getting a plot** is not the same as **getting a _good_ plot**.
45
+ That first draft is usually not presentation-ready. Quite often, _it just looks bad_.
46
+
47
+ So you spend the next 30 minutes telling the agent exactly what to change. Move the legend. Fix the labels. Soften the colours. Tighten the spacing. After a few rounds you finally feel like you are getting close -- and then comes **another 30 minutes of tiny adjustments**. Worse, sometimes you know _exactly_ what feels wrong, but cannot describe it clearly enough for the agent to act on it. You end up writing 100 words just to point at one awkward corner of the figure.
48
+
49
+ **OpenPlot is built for that part.**
50
+ It is an agentic plotting IDE that lets you stay in control **without babysitting the whole process**. Connect your favourite coding agent -- Codex, Claude Code, or OpenCode -- and let it inspect the data, choose the right visualisation, and handle styling, colour, layout, and positioning for you. In **Auto mode**, agents can review their own drafts and keep refining through multiple passes.
51
+ OpenPlot turns painful prompting into a much simpler decision-making workflow: choose your data file, confirm a few design options, switch on **Auto mode**, and go make your coffee.
52
+
53
+ <table align="center">
54
+ <tr>
55
+ <td align="center" width="50%">
56
+ <img src="assets/file-selection.gif" alt="OpenPlot file selection demo" width="100%" /><br />
57
+ <sub>Pick the data files you want the agent to work with.</sub>
58
+ </td>
59
+ <td align="center" width="50%">
60
+ <img src="assets/decide-plot-style.gif" alt="OpenPlot plot style selection demo" width="100%" /><br />
61
+ <sub>Confirm the deisgn choices and start plotting.</sub>
62
+ </td>
63
+ </tr>
64
+ </table>
65
+
66
+ And when the result is _98% right_ but still not quite there, OpenPlot's **drag-and-select annotation mode** makes the last mile easy. Just point to the exact region you want fixed and describe the change in simple, lazy language. **No prompt engineering.** No carefully crafted essay. Just direct instruction.
67
+
68
+ <table align="center">
69
+ <tr>
70
+ <td align="center" width="50%">
71
+ <img src="assets/make-annotation.gif" alt="OpenPlot annotation demo" width="100%" /><br />
72
+ <sub>Drag-select the exact region you want changed.</sub>
73
+ </td>
74
+ <td align="center" width="50%">
75
+ <img src="assets/fix-annotations.gif" alt="OpenPlot annotation fix demo" width="100%" /><br />
76
+ <sub>Watch live output from the agent addressing your comment.</sub>
77
+ </td>
78
+ </tr>
79
+ </table>
80
+
81
+ If you want to explore multiple directions, OpenPlot makes that easy too. Click any previous step, make any new annotation to branch from it, and try a different adjustment path in parallel. OpenPlot gives you **git-like version control for plots**: switch between branches, compare outcomes, and download both the final image _and_ the directly runnable Python script behind it.
82
+
83
+ OpenPlot also ships with a **built-in Python runtime** and popular data visualisation libraries. Need more? Configure your own environment.
84
+
85
+ We want OpenPlot to be **truly for everyone**.
86
+
87
+ ## Features
88
+
89
+ **Plot Mode** -- Generate plots from local data files through an AI chat interface. Select file paths, preview supported tabular sources, confirm target ranges when needed, approve a plan, and let the agent produce a plotting script autonomously.
90
+
91
+ **Annotation Mode** -- Draw and select regions on rendered plot, attach lazy instruction, and let a coding agent fix it precisely.
92
+
93
+ **Feedback Compiler** -- Annotations are turned into structured LLM prompts with scope rules (local region vs. local element) so the model knows exactly what to change.
94
+
95
+ **MCP Server** -- Built-in MCP bridge for agent integration via `openplot mcp`, with automatic wiring for supported runners.
96
+
97
+ **Multi-Runner Support** -- Connect with your favourite agents [OpenCode](https://opencode.ai), [Codex](https://github.com/openai/codex), or [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview) as the fixing agent, with per-runner model and variant selection.
98
+
99
+ **Version Control** -- Every fix creates a new version with immutable script and plot snapshots. Supports undo and branching to compare between versions.
100
+
101
+ **Background Fix Jobs** -- Kick off repeated fix iterations from the UI and watch live runner output until all pending annotations are addressed.
102
+
103
+ **Desktop App** -- Native desktop app via pywebview on macOS and Windows.
104
+
105
+ **Data Privacy** -- OpenPlot keeps scripts, plots, and session state on your machine. Remote network usage depends on the coding runner and model you connect.
106
+
107
+ **Data Profiling** -- Auto-detects table regions in tabular data, shows previews with integrity notes, and supports multi-sheet Excel workbooks.
108
+
109
+ ## Roadmap
110
+
111
+ - [ ] Support bring-your-own API key
112
+ - [ ] Plugin for jupyter lab
113
+ - [ ] Integrate with NanoBanana
114
+
115
+ ## Installation
116
+
117
+ ### Prerequisites
118
+
119
+ OpenPlot needs a coding agent CLI to generate and fix plots. You must have **at least one** of the following installed:
120
+
121
+ | Agent | Install guide |
122
+ | ----------- | ------------------------------------------------------------------------------------------------ |
123
+ | OpenCode | [docs](https://opencode.ai) |
124
+ | Codex | [docs](https://chatgpt.com/codex) |
125
+ | Claude Code | [docs](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview#getting-started) |
126
+
127
+ > **macOS desktop app users:** The `.dmg` build bundles a one-click installer for coding agents, so you can skip this step and set up an agent from within the app.
128
+
129
+ ### Pre-Built Binaries
130
+
131
+ Current GitHub release artifacts are available from [GitHub Releases](https://github.com/phira-ai/OpenPlot/releases):
132
+
133
+ | Platform | Artifact |
134
+ | ---------------------- | -------------------------- |
135
+ | macOS (M-chip) (arm64) | `OpenPlot-arm64.dmg` |
136
+ | Windows (x64) | `OpenPlot-windows-x64.zip` |
137
+
138
+ Linux users can build from source or use the Nix flake.
139
+
140
+ ### From PyPI
141
+
142
+ ```bash
143
+ pip install openplot
144
+ ```
145
+
146
+ To include desktop app dependencies (pywebview):
147
+
148
+ ```bash
149
+ pip install "openplot[desktop]"
150
+ ```
151
+
152
+ ### From Source
153
+
154
+ **Prerequisites:** Python 3.12+, [uv](https://docs.astral.sh/uv/), Node.js + npm
155
+
156
+ ```bash
157
+ git clone https://github.com/phira-ai/OpenPlot.git
158
+ cd OpenPlot
159
+ uv sync
160
+ npm ci --prefix frontend
161
+ npm run build --prefix frontend
162
+ ```
163
+
164
+ To include desktop app dependencies (pywebview):
165
+
166
+ ```bash
167
+ uv sync --extra desktop
168
+ ```
169
+
170
+ To include development tools (ruff, pytest):
171
+
172
+ ```bash
173
+ uv sync --group dev
174
+ ```
175
+
176
+ ### Nix Flake
177
+
178
+ ```bash
179
+ # Run directly
180
+ nix run github:phira-ai/OpenPlot#openplot -- serve examples/test_plot.py
181
+
182
+ # Run the desktop launcher
183
+ nix run github:phira-ai/OpenPlot#openplot-desktop
184
+
185
+ # Build the package
186
+ nix build github:phira-ai/OpenPlot#openplot
187
+ ```
188
+
189
+ Use as a flake input:
190
+
191
+ ```nix
192
+ {
193
+ inputs.openplot.url = "github:phira-ai/OpenPlot";
194
+ }
195
+ ```
196
+
197
+ and
198
+
199
+ ```nix
200
+ environment.systemPackages = with pkgs; [
201
+ inputs.openplot.packages.${pkgs.stdenv.hostPlatform.system}.openplot
202
+ inputs.openplot.packages.${pkgs.stdenv.hostPlatform.system}.openplot-desktop
203
+ ];
204
+ ```
205
+
206
+ ## Architecture
207
+
208
+ ```
209
+ ┌─────────────────────────────────────────────────────┐
210
+ │ Web UI (React) │
211
+ │ Plot Viewer · Annotation Overlay · Chat Panel │
212
+ └──────────────────────┬──────────────────────────────┘
213
+ │ REST + WebSocket
214
+ ┌──────────────────────▼──────────────────────────────┐
215
+ │ FastAPI Backend (Python) │
216
+ │ Script Executor · Feedback Compiler · Session Mgr │
217
+ │ Version Control · Data Profiler · Fix Job Runner │
218
+ └──────────┬────────────────────────────┬─────────────┘
219
+ │ stdio (MCP) │ subprocess
220
+ ┌──────────▼───────────┐ ┌───────────▼─────────────┐
221
+ │ Coding Agent │ │ Python Interpreter │
222
+ │ (OpenCode / Codex / │ │ (matplotlib, seaborn, │
223
+ │ Claude Code) │ │ numpy, pandas, ...) │
224
+ └──────────────────────┘ └─────────────────────────┘
225
+ ```
226
+
227
+ 1. The **React frontend** renders plots and captures region annotations.
228
+ 2. The **FastAPI backend** compiles annotations into structured prompts, executes scripts, manages versioned state, and serves everything over REST and WebSocket.
229
+ 3. The **MCP server** bridges the backend to coding agents over stdio, enabling a closed feedback loop: annotate, fix, re-render, repeat.
230
+
231
+ <details>
232
+ <summary><strong>CLI Reference</strong></summary>
233
+
234
+ ### `openplot serve`
235
+
236
+ Start the OpenPlot backend/UI server and open the browser by default.
237
+
238
+ ```
239
+ openplot serve [FILE] [OPTIONS]
240
+ ```
241
+
242
+ | Option | Default | Description |
243
+ | -------------- | ----------- | ------------------------------------ |
244
+ | `FILE` | _(none)_ | Python script (`.py`) |
245
+ | `--port` | `17623` | Server port (`0` for auto-pick) |
246
+ | `--host` | `127.0.0.1` | Bind address |
247
+ | `--no-browser` | off | Don't open the browser automatically |
248
+
249
+ When `FILE` is omitted, OpenPlot restores the most recently updated workspace. If no workspace exists, it launches in plot mode.
250
+
251
+ ### `openplot desktop`
252
+
253
+ Launch the native desktop window.
254
+
255
+ ```
256
+ openplot desktop [FILE] [OPTIONS]
257
+ ```
258
+
259
+ Accepts the same `.py` `FILE` input and the same options as `serve` except `--no-browser`.
260
+
261
+ ### `openplot mcp`
262
+
263
+ Start the MCP stdio bridge for agent integration.
264
+
265
+ ```
266
+ openplot mcp [OPTIONS]
267
+ ```
268
+
269
+ | Option | Default | Description |
270
+ | -------------- | ------------------- | -------------------- |
271
+ | `--server-url` | _(auto-discovered)_ | OpenPlot backend URL |
272
+
273
+ Server URL discovery priority: `--server-url` > `OPENPLOT_SERVER_URL` > `~/.openplot/port`.
274
+
275
+ `openplot serve` does not launch the MCP stdio bridge itself; it writes the discovery port file used by `openplot mcp`. In normal OpenPlot runner flows, supported agents launch `openplot mcp` automatically when they need MCP access.
276
+
277
+ </details>
278
+
279
+ <details>
280
+ <summary><strong>Configuration</strong></summary>
281
+
282
+ ### Environment Variables
283
+
284
+ | Variable | Description |
285
+ | ------------------------- | --------------------------------------------------------- |
286
+ | `OPENPLOT_STATE_DIR` | Override the runtime state/artifacts root |
287
+ | `OPENPLOT_SERVER_URL` | MCP only: override the backend URL used by `openplot mcp` |
288
+ | `OPENPLOT_SESSION_ID` | MCP only: target a specific session in MCP calls |
289
+ | `OPENPLOT_BUILTIN_PYTHON` | Advanced: override the built-in Python interpreter path |
290
+
291
+ Selected data files stay at their original paths; OpenPlot no longer copies them into an app-managed data store.
292
+
293
+ ### State Storage Paths
294
+
295
+ | Platform | State |
296
+ | -------- | ----------------------------------------------- |
297
+ | macOS | `~/Library/Application Support/OpenPlot/state/` |
298
+ | Linux | `~/.local/state/openplot/` |
299
+ | Windows | `%LOCALAPPDATA%/OpenPlot/state/` |
300
+
301
+ </details>
302
+
303
+ ## Contributing
304
+
305
+ Contributions are welcome. To get started:
306
+
307
+ ```bash
308
+ # Clone and install with dev dependencies
309
+ git clone https://github.com/phira-ai/OpenPlot.git
310
+ cd OpenPlot
311
+ uv sync --group dev
312
+
313
+ # Install frontend dependencies
314
+ npm ci --prefix frontend
315
+
316
+ # Run backend checks
317
+ uv run pytest
318
+ uv run ruff check src tests
319
+
320
+ # Run frontend checks
321
+ npm run test --prefix frontend
322
+ npm run lint --prefix frontend
323
+
324
+ # Build frontend (includes TypeScript build)
325
+ npm run build --prefix frontend
326
+ ```
327
+
328
+ Please open an issue before submitting large changes.
329
+
330
+ ## License
331
+
332
+ This project is licensed under the [GNU General Public License v3.0](LICENSE).
@@ -0,0 +1,304 @@
1
+ <p align="center">
2
+ <img src="frontend/openplot.png" alt="OpenPlot" width="520" />
3
+ </p>
4
+
5
+ <p align="center"><strong>The agentic plotting "IDE" built for everyone </strong></p>
6
+
7
+ <p align="center">
8
+ <img alt="Python 3.12+" src="https://img.shields.io/badge/python-3.12%2B-3776AB?logo=python&logoColor=white" />
9
+ <img alt="License: GPL-3.0" src="https://img.shields.io/badge/license-GPL--3.0-blue" />
10
+ <img alt="Platform" src="https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-lightgrey" />
11
+ </p>
12
+
13
+ ---
14
+
15
+ Agentic coding already makes plotting easier: give your data to an agent, and it can write a script for you in seconds.
16
+ But **getting a plot** is not the same as **getting a _good_ plot**.
17
+ That first draft is usually not presentation-ready. Quite often, _it just looks bad_.
18
+
19
+ So you spend the next 30 minutes telling the agent exactly what to change. Move the legend. Fix the labels. Soften the colours. Tighten the spacing. After a few rounds you finally feel like you are getting close -- and then comes **another 30 minutes of tiny adjustments**. Worse, sometimes you know _exactly_ what feels wrong, but cannot describe it clearly enough for the agent to act on it. You end up writing 100 words just to point at one awkward corner of the figure.
20
+
21
+ **OpenPlot is built for that part.**
22
+ It is an agentic plotting IDE that lets you stay in control **without babysitting the whole process**. Connect your favourite coding agent -- Codex, Claude Code, or OpenCode -- and let it inspect the data, choose the right visualisation, and handle styling, colour, layout, and positioning for you. In **Auto mode**, agents can review their own drafts and keep refining through multiple passes.
23
+ OpenPlot turns painful prompting into a much simpler decision-making workflow: choose your data file, confirm a few design options, switch on **Auto mode**, and go make your coffee.
24
+
25
+ <table align="center">
26
+ <tr>
27
+ <td align="center" width="50%">
28
+ <img src="assets/file-selection.gif" alt="OpenPlot file selection demo" width="100%" /><br />
29
+ <sub>Pick the data files you want the agent to work with.</sub>
30
+ </td>
31
+ <td align="center" width="50%">
32
+ <img src="assets/decide-plot-style.gif" alt="OpenPlot plot style selection demo" width="100%" /><br />
33
+ <sub>Confirm the deisgn choices and start plotting.</sub>
34
+ </td>
35
+ </tr>
36
+ </table>
37
+
38
+ And when the result is _98% right_ but still not quite there, OpenPlot's **drag-and-select annotation mode** makes the last mile easy. Just point to the exact region you want fixed and describe the change in simple, lazy language. **No prompt engineering.** No carefully crafted essay. Just direct instruction.
39
+
40
+ <table align="center">
41
+ <tr>
42
+ <td align="center" width="50%">
43
+ <img src="assets/make-annotation.gif" alt="OpenPlot annotation demo" width="100%" /><br />
44
+ <sub>Drag-select the exact region you want changed.</sub>
45
+ </td>
46
+ <td align="center" width="50%">
47
+ <img src="assets/fix-annotations.gif" alt="OpenPlot annotation fix demo" width="100%" /><br />
48
+ <sub>Watch live output from the agent addressing your comment.</sub>
49
+ </td>
50
+ </tr>
51
+ </table>
52
+
53
+ If you want to explore multiple directions, OpenPlot makes that easy too. Click any previous step, make any new annotation to branch from it, and try a different adjustment path in parallel. OpenPlot gives you **git-like version control for plots**: switch between branches, compare outcomes, and download both the final image _and_ the directly runnable Python script behind it.
54
+
55
+ OpenPlot also ships with a **built-in Python runtime** and popular data visualisation libraries. Need more? Configure your own environment.
56
+
57
+ We want OpenPlot to be **truly for everyone**.
58
+
59
+ ## Features
60
+
61
+ **Plot Mode** -- Generate plots from local data files through an AI chat interface. Select file paths, preview supported tabular sources, confirm target ranges when needed, approve a plan, and let the agent produce a plotting script autonomously.
62
+
63
+ **Annotation Mode** -- Draw and select regions on rendered plot, attach lazy instruction, and let a coding agent fix it precisely.
64
+
65
+ **Feedback Compiler** -- Annotations are turned into structured LLM prompts with scope rules (local region vs. local element) so the model knows exactly what to change.
66
+
67
+ **MCP Server** -- Built-in MCP bridge for agent integration via `openplot mcp`, with automatic wiring for supported runners.
68
+
69
+ **Multi-Runner Support** -- Connect with your favourite agents [OpenCode](https://opencode.ai), [Codex](https://github.com/openai/codex), or [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview) as the fixing agent, with per-runner model and variant selection.
70
+
71
+ **Version Control** -- Every fix creates a new version with immutable script and plot snapshots. Supports undo and branching to compare between versions.
72
+
73
+ **Background Fix Jobs** -- Kick off repeated fix iterations from the UI and watch live runner output until all pending annotations are addressed.
74
+
75
+ **Desktop App** -- Native desktop app via pywebview on macOS and Windows.
76
+
77
+ **Data Privacy** -- OpenPlot keeps scripts, plots, and session state on your machine. Remote network usage depends on the coding runner and model you connect.
78
+
79
+ **Data Profiling** -- Auto-detects table regions in tabular data, shows previews with integrity notes, and supports multi-sheet Excel workbooks.
80
+
81
+ ## Roadmap
82
+
83
+ - [ ] Support bring-your-own API key
84
+ - [ ] Plugin for jupyter lab
85
+ - [ ] Integrate with NanoBanana
86
+
87
+ ## Installation
88
+
89
+ ### Prerequisites
90
+
91
+ OpenPlot needs a coding agent CLI to generate and fix plots. You must have **at least one** of the following installed:
92
+
93
+ | Agent | Install guide |
94
+ | ----------- | ------------------------------------------------------------------------------------------------ |
95
+ | OpenCode | [docs](https://opencode.ai) |
96
+ | Codex | [docs](https://chatgpt.com/codex) |
97
+ | Claude Code | [docs](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview#getting-started) |
98
+
99
+ > **macOS desktop app users:** The `.dmg` build bundles a one-click installer for coding agents, so you can skip this step and set up an agent from within the app.
100
+
101
+ ### Pre-Built Binaries
102
+
103
+ Current GitHub release artifacts are available from [GitHub Releases](https://github.com/phira-ai/OpenPlot/releases):
104
+
105
+ | Platform | Artifact |
106
+ | ---------------------- | -------------------------- |
107
+ | macOS (M-chip) (arm64) | `OpenPlot-arm64.dmg` |
108
+ | Windows (x64) | `OpenPlot-windows-x64.zip` |
109
+
110
+ Linux users can build from source or use the Nix flake.
111
+
112
+ ### From PyPI
113
+
114
+ ```bash
115
+ pip install openplot
116
+ ```
117
+
118
+ To include desktop app dependencies (pywebview):
119
+
120
+ ```bash
121
+ pip install "openplot[desktop]"
122
+ ```
123
+
124
+ ### From Source
125
+
126
+ **Prerequisites:** Python 3.12+, [uv](https://docs.astral.sh/uv/), Node.js + npm
127
+
128
+ ```bash
129
+ git clone https://github.com/phira-ai/OpenPlot.git
130
+ cd OpenPlot
131
+ uv sync
132
+ npm ci --prefix frontend
133
+ npm run build --prefix frontend
134
+ ```
135
+
136
+ To include desktop app dependencies (pywebview):
137
+
138
+ ```bash
139
+ uv sync --extra desktop
140
+ ```
141
+
142
+ To include development tools (ruff, pytest):
143
+
144
+ ```bash
145
+ uv sync --group dev
146
+ ```
147
+
148
+ ### Nix Flake
149
+
150
+ ```bash
151
+ # Run directly
152
+ nix run github:phira-ai/OpenPlot#openplot -- serve examples/test_plot.py
153
+
154
+ # Run the desktop launcher
155
+ nix run github:phira-ai/OpenPlot#openplot-desktop
156
+
157
+ # Build the package
158
+ nix build github:phira-ai/OpenPlot#openplot
159
+ ```
160
+
161
+ Use as a flake input:
162
+
163
+ ```nix
164
+ {
165
+ inputs.openplot.url = "github:phira-ai/OpenPlot";
166
+ }
167
+ ```
168
+
169
+ and
170
+
171
+ ```nix
172
+ environment.systemPackages = with pkgs; [
173
+ inputs.openplot.packages.${pkgs.stdenv.hostPlatform.system}.openplot
174
+ inputs.openplot.packages.${pkgs.stdenv.hostPlatform.system}.openplot-desktop
175
+ ];
176
+ ```
177
+
178
+ ## Architecture
179
+
180
+ ```
181
+ ┌─────────────────────────────────────────────────────┐
182
+ │ Web UI (React) │
183
+ │ Plot Viewer · Annotation Overlay · Chat Panel │
184
+ └──────────────────────┬──────────────────────────────┘
185
+ │ REST + WebSocket
186
+ ┌──────────────────────▼──────────────────────────────┐
187
+ │ FastAPI Backend (Python) │
188
+ │ Script Executor · Feedback Compiler · Session Mgr │
189
+ │ Version Control · Data Profiler · Fix Job Runner │
190
+ └──────────┬────────────────────────────┬─────────────┘
191
+ │ stdio (MCP) │ subprocess
192
+ ┌──────────▼───────────┐ ┌───────────▼─────────────┐
193
+ │ Coding Agent │ │ Python Interpreter │
194
+ │ (OpenCode / Codex / │ │ (matplotlib, seaborn, │
195
+ │ Claude Code) │ │ numpy, pandas, ...) │
196
+ └──────────────────────┘ └─────────────────────────┘
197
+ ```
198
+
199
+ 1. The **React frontend** renders plots and captures region annotations.
200
+ 2. The **FastAPI backend** compiles annotations into structured prompts, executes scripts, manages versioned state, and serves everything over REST and WebSocket.
201
+ 3. The **MCP server** bridges the backend to coding agents over stdio, enabling a closed feedback loop: annotate, fix, re-render, repeat.
202
+
203
+ <details>
204
+ <summary><strong>CLI Reference</strong></summary>
205
+
206
+ ### `openplot serve`
207
+
208
+ Start the OpenPlot backend/UI server and open the browser by default.
209
+
210
+ ```
211
+ openplot serve [FILE] [OPTIONS]
212
+ ```
213
+
214
+ | Option | Default | Description |
215
+ | -------------- | ----------- | ------------------------------------ |
216
+ | `FILE` | _(none)_ | Python script (`.py`) |
217
+ | `--port` | `17623` | Server port (`0` for auto-pick) |
218
+ | `--host` | `127.0.0.1` | Bind address |
219
+ | `--no-browser` | off | Don't open the browser automatically |
220
+
221
+ When `FILE` is omitted, OpenPlot restores the most recently updated workspace. If no workspace exists, it launches in plot mode.
222
+
223
+ ### `openplot desktop`
224
+
225
+ Launch the native desktop window.
226
+
227
+ ```
228
+ openplot desktop [FILE] [OPTIONS]
229
+ ```
230
+
231
+ Accepts the same `.py` `FILE` input and the same options as `serve` except `--no-browser`.
232
+
233
+ ### `openplot mcp`
234
+
235
+ Start the MCP stdio bridge for agent integration.
236
+
237
+ ```
238
+ openplot mcp [OPTIONS]
239
+ ```
240
+
241
+ | Option | Default | Description |
242
+ | -------------- | ------------------- | -------------------- |
243
+ | `--server-url` | _(auto-discovered)_ | OpenPlot backend URL |
244
+
245
+ Server URL discovery priority: `--server-url` > `OPENPLOT_SERVER_URL` > `~/.openplot/port`.
246
+
247
+ `openplot serve` does not launch the MCP stdio bridge itself; it writes the discovery port file used by `openplot mcp`. In normal OpenPlot runner flows, supported agents launch `openplot mcp` automatically when they need MCP access.
248
+
249
+ </details>
250
+
251
+ <details>
252
+ <summary><strong>Configuration</strong></summary>
253
+
254
+ ### Environment Variables
255
+
256
+ | Variable | Description |
257
+ | ------------------------- | --------------------------------------------------------- |
258
+ | `OPENPLOT_STATE_DIR` | Override the runtime state/artifacts root |
259
+ | `OPENPLOT_SERVER_URL` | MCP only: override the backend URL used by `openplot mcp` |
260
+ | `OPENPLOT_SESSION_ID` | MCP only: target a specific session in MCP calls |
261
+ | `OPENPLOT_BUILTIN_PYTHON` | Advanced: override the built-in Python interpreter path |
262
+
263
+ Selected data files stay at their original paths; OpenPlot no longer copies them into an app-managed data store.
264
+
265
+ ### State Storage Paths
266
+
267
+ | Platform | State |
268
+ | -------- | ----------------------------------------------- |
269
+ | macOS | `~/Library/Application Support/OpenPlot/state/` |
270
+ | Linux | `~/.local/state/openplot/` |
271
+ | Windows | `%LOCALAPPDATA%/OpenPlot/state/` |
272
+
273
+ </details>
274
+
275
+ ## Contributing
276
+
277
+ Contributions are welcome. To get started:
278
+
279
+ ```bash
280
+ # Clone and install with dev dependencies
281
+ git clone https://github.com/phira-ai/OpenPlot.git
282
+ cd OpenPlot
283
+ uv sync --group dev
284
+
285
+ # Install frontend dependencies
286
+ npm ci --prefix frontend
287
+
288
+ # Run backend checks
289
+ uv run pytest
290
+ uv run ruff check src tests
291
+
292
+ # Run frontend checks
293
+ npm run test --prefix frontend
294
+ npm run lint --prefix frontend
295
+
296
+ # Build frontend (includes TypeScript build)
297
+ npm run build --prefix frontend
298
+ ```
299
+
300
+ Please open an issue before submitting large changes.
301
+
302
+ ## License
303
+
304
+ This project is licensed under the [GNU General Public License v3.0](LICENSE).
@@ -0,0 +1,43 @@
1
+ [project]
2
+ name = "openplot"
3
+ version = "1.0.0"
4
+ description = "Makes plotting and fine-tuning plots easy and interactive."
5
+ readme = "README.md"
6
+ authors = [{ name = "Philo Wu", email = "philo.wu@codeboyphilo.ai" }]
7
+ requires-python = ">=3.12"
8
+ dependencies = [
9
+ "fastapi>=0.115.0",
10
+ "uvicorn[standard]>=0.30.0",
11
+ "websockets>=13.0",
12
+ "click>=8.1.0",
13
+ "pydantic>=2.0.0",
14
+ "mcp>=1.26.0",
15
+ "numpy>=2.4.2",
16
+ "pandas>=3.0.1",
17
+ "matplotlib>=3.10.8",
18
+ "seaborn>=0.13.2",
19
+ "openpyxl>=3.1.5",
20
+ ]
21
+
22
+ [project.scripts]
23
+ openplot = "openplot.cli:main"
24
+ openplot-desktop = "openplot.desktop:main"
25
+
26
+ [project.optional-dependencies]
27
+ desktop = [
28
+ "pywebview>=5.2; platform_system != 'Linux'",
29
+ "pywebview[qt]>=5.2; platform_system == 'Linux'",
30
+ "pyobjc-core>=11.1; platform_system == 'Darwin'",
31
+ "pyobjc-framework-Cocoa>=11.1; platform_system == 'Darwin'",
32
+ "pyobjc-framework-Quartz>=11.1; platform_system == 'Darwin'",
33
+ "pyobjc-framework-Security>=11.1; platform_system == 'Darwin'",
34
+ "pyobjc-framework-WebKit>=11.1; platform_system == 'Darwin'",
35
+ ]
36
+
37
+ [build-system]
38
+ requires = ["uv_build>=0.10.6,<0.11.0"]
39
+ build-backend = "uv_build"
40
+
41
+ [dependency-groups]
42
+ dev = ["ruff>=0.8.0", "pytest>=8.0.0"]
43
+ packaging = ["pyinstaller>=6.16.0"]
@@ -0,0 +1,3 @@
1
+ """OpenPlot: Visual plot debugger."""
2
+
3
+ __version__ = "1.0.0"
@@ -0,0 +1 @@
1
+ """API helpers and schemas for OpenPlot."""