Skip to main content

Persistent Python REPL for LLM CLI tools

Project description

pyreplab

Persistent Python REPL for LLM CLI tools.

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.

How it works

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.

Quick start

Write a .py file with #%% cell blocks — in your editor, or let an LLM write it:

# analysis.py

#%% Load
import pandas as pd
df = pd.read_csv("data.csv")
print(df.shape)

#%% Explore
print(df.describe())

#%% Top rows
print(df.head(20))

Then run cells:

pyreplab start --workdir /path/to/project   # start (auto-detects .venv/)
pyreplab run analysis.py:0                  # Load data
pyreplab run analysis.py:1                  # Explore (df still loaded)
pyreplab run analysis.py:2                  # Top rows (no reload)
pyreplab stop

CLI reference

pyreplab <command> [args]

  start [opts]        Start the REPL (opts passed to pyreplab.py)
  run file.py         Run all #%% cells in file
  run file.py:N       Run cell N from file (0-indexed)
  run 'code'          Run inline code
  run                 Read code from stdin
  stop                Stop the current session
  stop-all            Stop all active sessions
  ps                  List all active sessions with PID, uptime, memory
  status              Check if REPL is running
  clean               Remove session files

Server options

python pyreplab.py [options]

  --session-dir DIR    Session directory (default: /tmp/pyreplab)
  --workdir DIR        Working directory for the REPL
  --venv PATH          Path to virtualenv (auto-detects .venv/ in workdir)
  --conda [ENV]        Activate conda env (default: base)
  --no-conda           Disable conda auto-detection
  --timeout SECS       Per-command timeout (default: 30)
  --max-output CHARS   Hard cap on output size (default: 100000)
  --max-rows N         Pandas display rows (default: 50)
  --max-cols N         Pandas display columns (default: 20)
  --poll-interval SECS Poll interval (default: 0.05)

Environment detection

pyreplab automatically detects and activates Python environments so your project packages are available. Detection follows a priority order — the first match wins:

Priority Source How it's found
1 --venv PATH Explicit flag
2 .venv/ in workdir Auto-detected
3 --conda [ENV] Explicit flag
4 Conda base Auto-detected fallback

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.

Virtual environments (venv, uv, virtualenv)

# Auto-detect .venv/ in workdir (most common)
pyreplab start --workdir /path/to/project

# Explicit path to any virtualenv
pyreplab start --venv /path/to/.venv

Works with uv venv, python -m venv, or any standard virtualenv.

Conda environments

# Auto-detect: if no .venv/, conda base is used automatically
pyreplab start --workdir /path/to/project

# Explicit: force conda base
pyreplab start --conda

# Named conda env
pyreplab start --conda myenv

# Disable conda fallback (bare Python only)
pyreplab start --no-conda

Conda base is found by checking, in order:

  1. $CONDA_PREFIX (set when a conda env is active)
  2. $CONDA_EXE (e.g. ~/miniconda3/bin/conda → derives ~/miniconda3)
  3. Common install paths: ~/miniconda3, ~/anaconda3, ~/miniforge3, ~/mambaforge, /opt/conda

Named envs resolve to <conda_base>/envs/<name>.

Session isolation

Each --workdir gets its own isolated session — separate process, namespace, and files. No clashing between projects.

# Two projects, two sessions
pyreplab start --workdir ~/projects/project-a
pyreplab start --workdir ~/projects/project-b

# See what's running
pyreplab ps
# SESSION                      PID     UPTIME   MEM    DIR
# project-a_a1b2c3d4           12345   5m30s    57MB   /tmp/pyreplab/project-a_a1b2c3d4
# project-b_e5f6g7h8           12346   2m15s    43MB   /tmp/pyreplab/project-b_e5f6g7h8

# Commands auto-resolve to the right session based on cwd
cd ~/projects/project-a && pyreplab run analysis.py:0
cd ~/projects/project-b && pyreplab run analysis.py:0

# Stop everything
pyreplab stop-all

Display limits

Output is automatically truncated for LLM-friendly sizes:

Library Setting Default
pandas max_rows 50
pandas max_columns 20
pandas max_colwidth 80 chars
numpy threshold 100 elements

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.

Protocol

cmd.py (client writes):

#%% id: unique-id
import pandas as pd
df = pd.read_csv("big.csv")
print(df.shape)

The first line is a #%% cell header with an optional command ID. The rest is plain Python — no escaping, no JSON encoding.

output.json (pyreplab writes):

{"stdout": "(1000, 5)\n", "stderr": "", "error": null, "id": "unique-id"}

Files are written atomically (write .tmp, then os.rename). The id field prevents reading stale output.

Install

git clone https://github.com/anthropics/pyreplab.git
cd pyreplab

Make pyreplab available on your PATH (pick one):

# Option 1: symlink (recommended)
ln -s "$(pwd)/pyreplab" /usr/local/bin/pyreplab

# Option 2: add directory to PATH
echo 'export PATH="'$(pwd)':$PATH"' >> ~/.zshrc
source ~/.zshrc

Verify:

pyreplab start --workdir .
pyreplab run 'print("hello")'
pyreplab stop

Using with Claude Code

Append the agent instructions to Claude Code's system prompt:

claude --append-system-prompt-file /path/to/pyreplab/AGENT_PROMPT.md

Or add them to your project's CLAUDE.md so they're loaded automatically in every session.

Tests

bash test_pyreplab.sh    # 14 tests: basic execution, persistence, errors, display limits, cells, stdin
bash test_agent.sh     # 10-step agent walkthrough: loads data, analyzes, reaches a conclusion

Requirements

Python 3.9+. Zero dependencies — stdlib only.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyreplab-0.1.0.tar.gz (12.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyreplab-0.1.0-py3-none-any.whl (12.7 kB view details)

Uploaded Python 3

File details

Details for the file pyreplab-0.1.0.tar.gz.

File metadata

  • Download URL: pyreplab-0.1.0.tar.gz
  • Upload date:
  • Size: 12.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for pyreplab-0.1.0.tar.gz
Algorithm Hash digest
SHA256 9f7d680d650c833a88e3c55998779c9f8e3a0c3cfc57f2abd392d2d082625f84
MD5 a86f47966edd9c8402a7406fc7818974
BLAKE2b-256 38ad21a500d775aff8ea23c2c824fa92cbe799611100c52eaad9cfea5d831f26

See more details on using hashes here.

File details

Details for the file pyreplab-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pyreplab-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for pyreplab-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4faf6b9c4c7a93bdd04f8bb6578133b795e0d963b54ce5671b06edaa2b3cb691
MD5 66c7a3a162fe65b09804fcfd61c49659
BLAKE2b-256 03cda8986ba7e3c0c0ed6e8f633b6703bf8ff3276989b7af5e16a5d47b26444f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page