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.
- openplot-1.0.0/PKG-INFO +332 -0
- openplot-1.0.0/README.md +304 -0
- openplot-1.0.0/pyproject.toml +43 -0
- openplot-1.0.0/src/openplot/__init__.py +3 -0
- openplot-1.0.0/src/openplot/api/__init__.py +1 -0
- openplot-1.0.0/src/openplot/api/schemas.py +132 -0
- openplot-1.0.0/src/openplot/cli.py +139 -0
- openplot-1.0.0/src/openplot/desktop.py +437 -0
- openplot-1.0.0/src/openplot/domain/__init__.py +1 -0
- openplot-1.0.0/src/openplot/domain/annotations.py +45 -0
- openplot-1.0.0/src/openplot/domain/regions.py +52 -0
- openplot-1.0.0/src/openplot/executor.py +726 -0
- openplot-1.0.0/src/openplot/feedback.py +141 -0
- openplot-1.0.0/src/openplot/mcp_server.py +353 -0
- openplot-1.0.0/src/openplot/models.py +408 -0
- openplot-1.0.0/src/openplot/release_versioning.py +305 -0
- openplot-1.0.0/src/openplot/server.py +11120 -0
- openplot-1.0.0/src/openplot/services/__init__.py +1 -0
- openplot-1.0.0/src/openplot/services/naming.py +75 -0
- openplot-1.0.0/src/openplot/static/assets/MarkdownRenderer-DqMDEmDw.js +2 -0
- openplot-1.0.0/src/openplot/static/assets/geist-cyrillic-wght-normal-CHSlOQsW.woff2 +0 -0
- openplot-1.0.0/src/openplot/static/assets/geist-latin-ext-wght-normal-DMtmJ5ZE.woff2 +0 -0
- openplot-1.0.0/src/openplot/static/assets/geist-latin-wght-normal-Dm3htQBi.woff2 +0 -0
- openplot-1.0.0/src/openplot/static/assets/iconify-xdk4cov8.js +1 -0
- openplot-1.0.0/src/openplot/static/assets/index-9qrwxLoh.css +1 -0
- openplot-1.0.0/src/openplot/static/assets/index-DhwX5yIi.js +19 -0
- openplot-1.0.0/src/openplot/static/assets/lucide-DCaNFHhh.js +1 -0
- openplot-1.0.0/src/openplot/static/assets/markdown-BgYhP8km.js +29 -0
- openplot-1.0.0/src/openplot/static/assets/openplot-DYqSIMi_.png +0 -0
- openplot-1.0.0/src/openplot/static/assets/react-vendor-C4hNv3Lv.js +9 -0
- openplot-1.0.0/src/openplot/static/assets/ui-DjPaK12C.js +12 -0
- openplot-1.0.0/src/openplot/static/index.html +17 -0
- openplot-1.0.0/src/openplot/static/vite.svg +1 -0
openplot-1.0.0/PKG-INFO
ADDED
|
@@ -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).
|
openplot-1.0.0/README.md
ADDED
|
@@ -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 @@
|
|
|
1
|
+
"""API helpers and schemas for OpenPlot."""
|