openplot 1.0.0__py3-none-any.whl

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.
@@ -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,34 @@
1
+ openplot/__init__.py,sha256=nUJ1I3CPbQ-f0MJ991fkSk-V0CWkhDF7LUg6OGdLDEQ,61
2
+ openplot/api/__init__.py,sha256=chpbPDwFF-66YsGOSuPr9U99hfDN_hZn5QGpgLttSAI,44
3
+ openplot/api/schemas.py,sha256=L78fLgcJQaLWn27PWXeCsZ1TpWcjR36k0vp8sfLg_tc,3088
4
+ openplot/cli.py,sha256=Iy-4RaFIuObadZpi2k150maXJwHC2P0FVhD1nMtJmxo,4092
5
+ openplot/desktop.py,sha256=loBRlK60K5B6A2mL1yH_TpI-N1iyCLFn2CFimyHllco,12387
6
+ openplot/domain/__init__.py,sha256=g_pEHlyIPL9BMzVoHeDeKkU052c3Ygpbwvkct5qiuBA,42
7
+ openplot/domain/annotations.py,sha256=tVjACUhJGWAbfa6qa1RKviwnnkggDHWiCO_DXFDGWx0,1442
8
+ openplot/domain/regions.py,sha256=a1DJRdlpxYLh4NplZJ2rzSCGnyEq8FEASogvFekwW2g,1496
9
+ openplot/executor.py,sha256=jbvx8ofbILyt0PBuEBUVH-xY8WLVwtQ-M9VbWvHfohA,22735
10
+ openplot/feedback.py,sha256=goaT4iNAGW_-QpZPv96R6foXUeXtql2dT3d95JbHZ1k,5098
11
+ openplot/mcp_server.py,sha256=_qIBl7A826BZfHaNgpLGEyr0Bv76gqcUIw7e_Hxt_L8,13431
12
+ openplot/models.py,sha256=eK-HmSBchrd4VuyB7-m9436yacmihazamXBcbh1xv6k,12715
13
+ openplot/release_versioning.py,sha256=a4fFyftMIxdwOf8bmRKdozXOXTgBMJD455OIEYio8i8,10443
14
+ openplot/server.py,sha256=Fz0tfSqbeMm3bc-vwAXS8r58ecShQbbjP66_McISpbw,378840
15
+ openplot/services/__init__.py,sha256=66n5YXVZWuGkYZy6z7W47-MFDOEqYaz457tu9XDiazk,51
16
+ openplot/services/naming.py,sha256=fbHrWqYldd8MbXRu7pXkydYWhZ_8w7ZCT_pQtr9-uK0,1948
17
+ openplot/static/assets/MarkdownRenderer-DqMDEmDw.js,sha256=U0VLANaqcsGCfEDGychawl-n1Xx0zJX9ikUkhgTyDIs,1824
18
+ openplot/static/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2,sha256=M9erRg3_Th_FhnONXVDj4EvLSOm-97lBVMx-B67ta2Y,14692
19
+ openplot/static/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2,sha256=NkD5NRsqRjFRXf_qOAksJOcNud8u8el8EMvetBY-YYY,15308
20
+ openplot/static/assets/geist-latin-wght-normal-Dm3htQBi.woff2,sha256=DLvmKGoA81bpiYB4PMlQqbaTdR4Ert-5fZUm_23CsxY,28400
21
+ openplot/static/assets/iconify-xdk4cov8.js,sha256=KJvUYwkDupzYPEx4wvzUCqmD82hfaDWgoUwyNEN6fEw,41429
22
+ openplot/static/assets/index-9qrwxLoh.css,sha256=bkPKEfEUa8LYf_vWrFGcRJH1_JTJiZMcWnrIYHuFGts,111020
23
+ openplot/static/assets/index-DhwX5yIi.js,sha256=ZW4YpPQulzKXWFQNV1PkT-htIuq4SYI8Vsck70pw1UA,218344
24
+ openplot/static/assets/lucide-DCaNFHhh.js,sha256=iJ1J1yhgJ7gbo9zDSqtnXOtoUR8Hr001D54GeueqvAY,8388
25
+ openplot/static/assets/markdown-BgYhP8km.js,sha256=fymO8mwu_tLDEqo5sJv_rcyRQbkOQlalzUG6xKRCtjI,156615
26
+ openplot/static/assets/openplot-DYqSIMi_.png,sha256=aqNUyTLR6ZMQXxT_Hpf18Hgl_gAi8rsnuD8wBaF6Wk4,16847
27
+ openplot/static/assets/react-vendor-C4hNv3Lv.js,sha256=pmYsFfFCH55lEsGbkgnlSlcRgNzmlmpiAyUJTm05PxU,192906
28
+ openplot/static/assets/ui-DjPaK12C.js,sha256=Rfi5kHmKLCOTokb2JQq4IPptKewcfDQsv3NiKadBSc4,135829
29
+ openplot/static/index.html,sha256=QPx92GiOAk2vA8AJzveFfusMEAwGqwTyrvcudtw_zgg,704
30
+ openplot/static/vite.svg,sha256=SnSK_UQ5GLsWWRyDTEAdrjPoeGGrXbrQgRw6O0qSFPs,1497
31
+ openplot-1.0.0.dist-info/WHEEL,sha256=GuAqCqoyQuys5_R4zkHUJFlKXw4RpRLNzo31-ui90WQ,81
32
+ openplot-1.0.0.dist-info/entry_points.txt,sha256=mSIPtPJXyADeYzDT3A4MbdFdZn_CmpjD6udLfQOyrQQ,89
33
+ openplot-1.0.0.dist-info/METADATA,sha256=imh-4483ZqKu3hGu87-rSALCDOEUSaZnfcFLXKy7JuY,14495
34
+ openplot-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.10.12
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,4 @@
1
+ [console_scripts]
2
+ openplot = openplot.cli:main
3
+ openplot-desktop = openplot.desktop:main
4
+