pyreplab 0.1.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.
- pyreplab-0.1.0/LICENSE +21 -0
- pyreplab-0.1.0/PKG-INFO +241 -0
- pyreplab-0.1.0/README.md +222 -0
- pyreplab-0.1.0/pyproject.toml +29 -0
- pyreplab-0.1.0/pyreplab +404 -0
- pyreplab-0.1.0/pyreplab.egg-info/PKG-INFO +241 -0
- pyreplab-0.1.0/pyreplab.egg-info/SOURCES.txt +9 -0
- pyreplab-0.1.0/pyreplab.egg-info/dependency_links.txt +1 -0
- pyreplab-0.1.0/pyreplab.egg-info/top_level.txt +1 -0
- pyreplab-0.1.0/pyreplab.py +344 -0
- pyreplab-0.1.0/setup.cfg +4 -0
pyreplab-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Zhimin Zou
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pyreplab-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyreplab
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Persistent Python REPL for LLM CLI tools
|
|
5
|
+
Author: Zhimin Zou
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/protostatis/pyreplab
|
|
8
|
+
Project-URL: Repository, https://github.com/protostatis/pyreplab
|
|
9
|
+
Keywords: repl,llm,cli,persistent,data-analysis
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Topic :: Software Development :: Interpreters
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Dynamic: license-file
|
|
19
|
+
|
|
20
|
+
# pyreplab
|
|
21
|
+
|
|
22
|
+
Persistent Python REPL for LLM CLI tools.
|
|
23
|
+
|
|
24
|
+
LLM coding CLIs (Claude Code, Copilot CLI, etc.) can't maintain a persistent Python session — each bash command runs in a fresh process. For large datasets, reloading on every query is impractical. pyreplab fixes this.
|
|
25
|
+
|
|
26
|
+
## How it works
|
|
27
|
+
|
|
28
|
+
A background Python process sits in memory with a persistent namespace. You write `.py` files with `#%%` cell blocks, then execute cells by reference. No ports, no sockets, no dependencies.
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
Write a `.py` file with `#%%` cell blocks — in your editor, or let an LLM write it:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
# analysis.py
|
|
36
|
+
|
|
37
|
+
#%% Load
|
|
38
|
+
import pandas as pd
|
|
39
|
+
df = pd.read_csv("data.csv")
|
|
40
|
+
print(df.shape)
|
|
41
|
+
|
|
42
|
+
#%% Explore
|
|
43
|
+
print(df.describe())
|
|
44
|
+
|
|
45
|
+
#%% Top rows
|
|
46
|
+
print(df.head(20))
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Then run cells:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pyreplab start --workdir /path/to/project # start (auto-detects .venv/)
|
|
53
|
+
pyreplab run analysis.py:0 # Load data
|
|
54
|
+
pyreplab run analysis.py:1 # Explore (df still loaded)
|
|
55
|
+
pyreplab run analysis.py:2 # Top rows (no reload)
|
|
56
|
+
pyreplab stop
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## CLI reference
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
pyreplab <command> [args]
|
|
63
|
+
|
|
64
|
+
start [opts] Start the REPL (opts passed to pyreplab.py)
|
|
65
|
+
run file.py Run all #%% cells in file
|
|
66
|
+
run file.py:N Run cell N from file (0-indexed)
|
|
67
|
+
run 'code' Run inline code
|
|
68
|
+
run Read code from stdin
|
|
69
|
+
stop Stop the current session
|
|
70
|
+
stop-all Stop all active sessions
|
|
71
|
+
ps List all active sessions with PID, uptime, memory
|
|
72
|
+
status Check if REPL is running
|
|
73
|
+
clean Remove session files
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Server options
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
python pyreplab.py [options]
|
|
80
|
+
|
|
81
|
+
--session-dir DIR Session directory (default: /tmp/pyreplab)
|
|
82
|
+
--workdir DIR Working directory for the REPL
|
|
83
|
+
--venv PATH Path to virtualenv (auto-detects .venv/ in workdir)
|
|
84
|
+
--conda [ENV] Activate conda env (default: base)
|
|
85
|
+
--no-conda Disable conda auto-detection
|
|
86
|
+
--timeout SECS Per-command timeout (default: 30)
|
|
87
|
+
--max-output CHARS Hard cap on output size (default: 100000)
|
|
88
|
+
--max-rows N Pandas display rows (default: 50)
|
|
89
|
+
--max-cols N Pandas display columns (default: 20)
|
|
90
|
+
--poll-interval SECS Poll interval (default: 0.05)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Environment detection
|
|
94
|
+
|
|
95
|
+
pyreplab automatically detects and activates Python environments so your project packages are available. Detection follows a priority order — the first match wins:
|
|
96
|
+
|
|
97
|
+
| Priority | Source | How it's found |
|
|
98
|
+
|----------|--------|----------------|
|
|
99
|
+
| 1 | `--venv PATH` | Explicit flag |
|
|
100
|
+
| 2 | `.venv/` in workdir | Auto-detected |
|
|
101
|
+
| 3 | `--conda [ENV]` | Explicit flag |
|
|
102
|
+
| 4 | Conda base | Auto-detected fallback |
|
|
103
|
+
|
|
104
|
+
If a project has a `.venv/`, that always takes precedence over conda. If no `.venv/` exists, pyreplab falls back to conda's base environment (giving you numpy, pandas, scipy, etc. out of the box). Use `--no-conda` to disable the fallback.
|
|
105
|
+
|
|
106
|
+
### Virtual environments (venv, uv, virtualenv)
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Auto-detect .venv/ in workdir (most common)
|
|
110
|
+
pyreplab start --workdir /path/to/project
|
|
111
|
+
|
|
112
|
+
# Explicit path to any virtualenv
|
|
113
|
+
pyreplab start --venv /path/to/.venv
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Works with `uv venv`, `python -m venv`, or any standard virtualenv.
|
|
117
|
+
|
|
118
|
+
### Conda environments
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Auto-detect: if no .venv/, conda base is used automatically
|
|
122
|
+
pyreplab start --workdir /path/to/project
|
|
123
|
+
|
|
124
|
+
# Explicit: force conda base
|
|
125
|
+
pyreplab start --conda
|
|
126
|
+
|
|
127
|
+
# Named conda env
|
|
128
|
+
pyreplab start --conda myenv
|
|
129
|
+
|
|
130
|
+
# Disable conda fallback (bare Python only)
|
|
131
|
+
pyreplab start --no-conda
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Conda base is found by checking, in order:
|
|
135
|
+
1. `$CONDA_PREFIX` (set when a conda env is active)
|
|
136
|
+
2. `$CONDA_EXE` (e.g. `~/miniconda3/bin/conda` → derives `~/miniconda3`)
|
|
137
|
+
3. Common install paths: `~/miniconda3`, `~/anaconda3`, `~/miniforge3`, `~/mambaforge`, `/opt/conda`
|
|
138
|
+
|
|
139
|
+
Named envs resolve to `<conda_base>/envs/<name>`.
|
|
140
|
+
|
|
141
|
+
## Session isolation
|
|
142
|
+
|
|
143
|
+
Each `--workdir` gets its own isolated session — separate process, namespace, and files. No clashing between projects.
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Two projects, two sessions
|
|
147
|
+
pyreplab start --workdir ~/projects/project-a
|
|
148
|
+
pyreplab start --workdir ~/projects/project-b
|
|
149
|
+
|
|
150
|
+
# See what's running
|
|
151
|
+
pyreplab ps
|
|
152
|
+
# SESSION PID UPTIME MEM DIR
|
|
153
|
+
# project-a_a1b2c3d4 12345 5m30s 57MB /tmp/pyreplab/project-a_a1b2c3d4
|
|
154
|
+
# project-b_e5f6g7h8 12346 2m15s 43MB /tmp/pyreplab/project-b_e5f6g7h8
|
|
155
|
+
|
|
156
|
+
# Commands auto-resolve to the right session based on cwd
|
|
157
|
+
cd ~/projects/project-a && pyreplab run analysis.py:0
|
|
158
|
+
cd ~/projects/project-b && pyreplab run analysis.py:0
|
|
159
|
+
|
|
160
|
+
# Stop everything
|
|
161
|
+
pyreplab stop-all
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Display limits
|
|
165
|
+
|
|
166
|
+
Output is automatically truncated for LLM-friendly sizes:
|
|
167
|
+
|
|
168
|
+
| Library | Setting | Default |
|
|
169
|
+
|---------|---------|---------|
|
|
170
|
+
| pandas | max_rows | 50 |
|
|
171
|
+
| pandas | max_columns | 20 |
|
|
172
|
+
| pandas | max_colwidth | 80 chars |
|
|
173
|
+
| numpy | threshold | 100 elements |
|
|
174
|
+
|
|
175
|
+
Override with `--max-rows` and `--max-cols`. The `--max-output` flag is a hard character cap that truncates at line boundaries, keeping both head and tail.
|
|
176
|
+
|
|
177
|
+
## Protocol
|
|
178
|
+
|
|
179
|
+
**cmd.py** (client writes):
|
|
180
|
+
```python
|
|
181
|
+
#%% id: unique-id
|
|
182
|
+
import pandas as pd
|
|
183
|
+
df = pd.read_csv("big.csv")
|
|
184
|
+
print(df.shape)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
The first line is a `#%%` cell header with an optional command ID. The rest is plain Python — no escaping, no JSON encoding.
|
|
188
|
+
|
|
189
|
+
**output.json** (pyreplab writes):
|
|
190
|
+
```json
|
|
191
|
+
{"stdout": "(1000, 5)\n", "stderr": "", "error": null, "id": "unique-id"}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Files are written atomically (write `.tmp`, then `os.rename`). The `id` field prevents reading stale output.
|
|
195
|
+
|
|
196
|
+
## Install
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
git clone https://github.com/anthropics/pyreplab.git
|
|
200
|
+
cd pyreplab
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Make `pyreplab` available on your PATH (pick one):
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# Option 1: symlink (recommended)
|
|
207
|
+
ln -s "$(pwd)/pyreplab" /usr/local/bin/pyreplab
|
|
208
|
+
|
|
209
|
+
# Option 2: add directory to PATH
|
|
210
|
+
echo 'export PATH="'$(pwd)':$PATH"' >> ~/.zshrc
|
|
211
|
+
source ~/.zshrc
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Verify:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
pyreplab start --workdir .
|
|
218
|
+
pyreplab run 'print("hello")'
|
|
219
|
+
pyreplab stop
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Using with Claude Code
|
|
223
|
+
|
|
224
|
+
Append the agent instructions to Claude Code's system prompt:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
claude --append-system-prompt-file /path/to/pyreplab/AGENT_PROMPT.md
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Or add them to your project's `CLAUDE.md` so they're loaded automatically in every session.
|
|
231
|
+
|
|
232
|
+
## Tests
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
bash test_pyreplab.sh # 14 tests: basic execution, persistence, errors, display limits, cells, stdin
|
|
236
|
+
bash test_agent.sh # 10-step agent walkthrough: loads data, analyzes, reaches a conclusion
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Requirements
|
|
240
|
+
|
|
241
|
+
Python 3.9+. Zero dependencies — stdlib only.
|
pyreplab-0.1.0/README.md
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# pyreplab
|
|
2
|
+
|
|
3
|
+
Persistent Python REPL for LLM CLI tools.
|
|
4
|
+
|
|
5
|
+
LLM coding CLIs (Claude Code, Copilot CLI, etc.) can't maintain a persistent Python session — each bash command runs in a fresh process. For large datasets, reloading on every query is impractical. pyreplab fixes this.
|
|
6
|
+
|
|
7
|
+
## How it works
|
|
8
|
+
|
|
9
|
+
A background Python process sits in memory with a persistent namespace. You write `.py` files with `#%%` cell blocks, then execute cells by reference. No ports, no sockets, no dependencies.
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
Write a `.py` file with `#%%` cell blocks — in your editor, or let an LLM write it:
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
# analysis.py
|
|
17
|
+
|
|
18
|
+
#%% Load
|
|
19
|
+
import pandas as pd
|
|
20
|
+
df = pd.read_csv("data.csv")
|
|
21
|
+
print(df.shape)
|
|
22
|
+
|
|
23
|
+
#%% Explore
|
|
24
|
+
print(df.describe())
|
|
25
|
+
|
|
26
|
+
#%% Top rows
|
|
27
|
+
print(df.head(20))
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Then run cells:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pyreplab start --workdir /path/to/project # start (auto-detects .venv/)
|
|
34
|
+
pyreplab run analysis.py:0 # Load data
|
|
35
|
+
pyreplab run analysis.py:1 # Explore (df still loaded)
|
|
36
|
+
pyreplab run analysis.py:2 # Top rows (no reload)
|
|
37
|
+
pyreplab stop
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## CLI reference
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
pyreplab <command> [args]
|
|
44
|
+
|
|
45
|
+
start [opts] Start the REPL (opts passed to pyreplab.py)
|
|
46
|
+
run file.py Run all #%% cells in file
|
|
47
|
+
run file.py:N Run cell N from file (0-indexed)
|
|
48
|
+
run 'code' Run inline code
|
|
49
|
+
run Read code from stdin
|
|
50
|
+
stop Stop the current session
|
|
51
|
+
stop-all Stop all active sessions
|
|
52
|
+
ps List all active sessions with PID, uptime, memory
|
|
53
|
+
status Check if REPL is running
|
|
54
|
+
clean Remove session files
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Server options
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
python pyreplab.py [options]
|
|
61
|
+
|
|
62
|
+
--session-dir DIR Session directory (default: /tmp/pyreplab)
|
|
63
|
+
--workdir DIR Working directory for the REPL
|
|
64
|
+
--venv PATH Path to virtualenv (auto-detects .venv/ in workdir)
|
|
65
|
+
--conda [ENV] Activate conda env (default: base)
|
|
66
|
+
--no-conda Disable conda auto-detection
|
|
67
|
+
--timeout SECS Per-command timeout (default: 30)
|
|
68
|
+
--max-output CHARS Hard cap on output size (default: 100000)
|
|
69
|
+
--max-rows N Pandas display rows (default: 50)
|
|
70
|
+
--max-cols N Pandas display columns (default: 20)
|
|
71
|
+
--poll-interval SECS Poll interval (default: 0.05)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Environment detection
|
|
75
|
+
|
|
76
|
+
pyreplab automatically detects and activates Python environments so your project packages are available. Detection follows a priority order — the first match wins:
|
|
77
|
+
|
|
78
|
+
| Priority | Source | How it's found |
|
|
79
|
+
|----------|--------|----------------|
|
|
80
|
+
| 1 | `--venv PATH` | Explicit flag |
|
|
81
|
+
| 2 | `.venv/` in workdir | Auto-detected |
|
|
82
|
+
| 3 | `--conda [ENV]` | Explicit flag |
|
|
83
|
+
| 4 | Conda base | Auto-detected fallback |
|
|
84
|
+
|
|
85
|
+
If a project has a `.venv/`, that always takes precedence over conda. If no `.venv/` exists, pyreplab falls back to conda's base environment (giving you numpy, pandas, scipy, etc. out of the box). Use `--no-conda` to disable the fallback.
|
|
86
|
+
|
|
87
|
+
### Virtual environments (venv, uv, virtualenv)
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Auto-detect .venv/ in workdir (most common)
|
|
91
|
+
pyreplab start --workdir /path/to/project
|
|
92
|
+
|
|
93
|
+
# Explicit path to any virtualenv
|
|
94
|
+
pyreplab start --venv /path/to/.venv
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Works with `uv venv`, `python -m venv`, or any standard virtualenv.
|
|
98
|
+
|
|
99
|
+
### Conda environments
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Auto-detect: if no .venv/, conda base is used automatically
|
|
103
|
+
pyreplab start --workdir /path/to/project
|
|
104
|
+
|
|
105
|
+
# Explicit: force conda base
|
|
106
|
+
pyreplab start --conda
|
|
107
|
+
|
|
108
|
+
# Named conda env
|
|
109
|
+
pyreplab start --conda myenv
|
|
110
|
+
|
|
111
|
+
# Disable conda fallback (bare Python only)
|
|
112
|
+
pyreplab start --no-conda
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Conda base is found by checking, in order:
|
|
116
|
+
1. `$CONDA_PREFIX` (set when a conda env is active)
|
|
117
|
+
2. `$CONDA_EXE` (e.g. `~/miniconda3/bin/conda` → derives `~/miniconda3`)
|
|
118
|
+
3. Common install paths: `~/miniconda3`, `~/anaconda3`, `~/miniforge3`, `~/mambaforge`, `/opt/conda`
|
|
119
|
+
|
|
120
|
+
Named envs resolve to `<conda_base>/envs/<name>`.
|
|
121
|
+
|
|
122
|
+
## Session isolation
|
|
123
|
+
|
|
124
|
+
Each `--workdir` gets its own isolated session — separate process, namespace, and files. No clashing between projects.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Two projects, two sessions
|
|
128
|
+
pyreplab start --workdir ~/projects/project-a
|
|
129
|
+
pyreplab start --workdir ~/projects/project-b
|
|
130
|
+
|
|
131
|
+
# See what's running
|
|
132
|
+
pyreplab ps
|
|
133
|
+
# SESSION PID UPTIME MEM DIR
|
|
134
|
+
# project-a_a1b2c3d4 12345 5m30s 57MB /tmp/pyreplab/project-a_a1b2c3d4
|
|
135
|
+
# project-b_e5f6g7h8 12346 2m15s 43MB /tmp/pyreplab/project-b_e5f6g7h8
|
|
136
|
+
|
|
137
|
+
# Commands auto-resolve to the right session based on cwd
|
|
138
|
+
cd ~/projects/project-a && pyreplab run analysis.py:0
|
|
139
|
+
cd ~/projects/project-b && pyreplab run analysis.py:0
|
|
140
|
+
|
|
141
|
+
# Stop everything
|
|
142
|
+
pyreplab stop-all
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Display limits
|
|
146
|
+
|
|
147
|
+
Output is automatically truncated for LLM-friendly sizes:
|
|
148
|
+
|
|
149
|
+
| Library | Setting | Default |
|
|
150
|
+
|---------|---------|---------|
|
|
151
|
+
| pandas | max_rows | 50 |
|
|
152
|
+
| pandas | max_columns | 20 |
|
|
153
|
+
| pandas | max_colwidth | 80 chars |
|
|
154
|
+
| numpy | threshold | 100 elements |
|
|
155
|
+
|
|
156
|
+
Override with `--max-rows` and `--max-cols`. The `--max-output` flag is a hard character cap that truncates at line boundaries, keeping both head and tail.
|
|
157
|
+
|
|
158
|
+
## Protocol
|
|
159
|
+
|
|
160
|
+
**cmd.py** (client writes):
|
|
161
|
+
```python
|
|
162
|
+
#%% id: unique-id
|
|
163
|
+
import pandas as pd
|
|
164
|
+
df = pd.read_csv("big.csv")
|
|
165
|
+
print(df.shape)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The first line is a `#%%` cell header with an optional command ID. The rest is plain Python — no escaping, no JSON encoding.
|
|
169
|
+
|
|
170
|
+
**output.json** (pyreplab writes):
|
|
171
|
+
```json
|
|
172
|
+
{"stdout": "(1000, 5)\n", "stderr": "", "error": null, "id": "unique-id"}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Files are written atomically (write `.tmp`, then `os.rename`). The `id` field prevents reading stale output.
|
|
176
|
+
|
|
177
|
+
## Install
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
git clone https://github.com/anthropics/pyreplab.git
|
|
181
|
+
cd pyreplab
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Make `pyreplab` available on your PATH (pick one):
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Option 1: symlink (recommended)
|
|
188
|
+
ln -s "$(pwd)/pyreplab" /usr/local/bin/pyreplab
|
|
189
|
+
|
|
190
|
+
# Option 2: add directory to PATH
|
|
191
|
+
echo 'export PATH="'$(pwd)':$PATH"' >> ~/.zshrc
|
|
192
|
+
source ~/.zshrc
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Verify:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
pyreplab start --workdir .
|
|
199
|
+
pyreplab run 'print("hello")'
|
|
200
|
+
pyreplab stop
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Using with Claude Code
|
|
204
|
+
|
|
205
|
+
Append the agent instructions to Claude Code's system prompt:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
claude --append-system-prompt-file /path/to/pyreplab/AGENT_PROMPT.md
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Or add them to your project's `CLAUDE.md` so they're loaded automatically in every session.
|
|
212
|
+
|
|
213
|
+
## Tests
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
bash test_pyreplab.sh # 14 tests: basic execution, persistence, errors, display limits, cells, stdin
|
|
217
|
+
bash test_agent.sh # 10-step agent walkthrough: loads data, analyzes, reaches a conclusion
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Requirements
|
|
221
|
+
|
|
222
|
+
Python 3.9+. Zero dependencies — stdlib only.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "pyreplab"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Persistent Python REPL for LLM CLI tools"
|
|
5
|
+
requires-python = ">=3.9"
|
|
6
|
+
dependencies = []
|
|
7
|
+
license = "MIT"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
authors = [{name = "Zhimin Zou"}]
|
|
10
|
+
keywords = ["repl", "llm", "cli", "persistent", "data-analysis"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 4 - Beta",
|
|
13
|
+
"Environment :: Console",
|
|
14
|
+
"Intended Audience :: Developers",
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Topic :: Software Development :: Interpreters",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[project.urls]
|
|
20
|
+
Homepage = "https://github.com/protostatis/pyreplab"
|
|
21
|
+
Repository = "https://github.com/protostatis/pyreplab"
|
|
22
|
+
|
|
23
|
+
[build-system]
|
|
24
|
+
requires = ["setuptools>=75"]
|
|
25
|
+
build-backend = "setuptools.build_meta"
|
|
26
|
+
|
|
27
|
+
[tool.setuptools]
|
|
28
|
+
py-modules = ["pyreplab"]
|
|
29
|
+
script-files = ["pyreplab"]
|