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 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.
@@ -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.
@@ -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"]