pythond
pythond
sshd gives you a shell. pythond gives you Python.
Persistent Python daemon with named sessions. Code in, result out.<br>Variables, connections, and threads survive between calls.<br>Agents send code through WebSocket. Humans attach with a real terminal.<br>Same namespace.
pip install pythond
Python 3.10+. Three entry points:
CommandRoleLike<br>pythonddaemonsshd<br>pyshsession clientfunction call / attach<br>pyctldaemon controlsystemctl
Quick start
pyctl start<br>pysh new work<br>pysh run work "x = 42"<br>pysh run work "x + 1"<br># 43<br>pysh attach work
State persists
pysh run work "import sqlite3; db = sqlite3.connect('app.db')"
# ... 100 turns later ...
pysh run work "db.execute('SELECT count(*) FROM users').fetchone()"<br># (42,)
The connection never closed. The namespace is the workspace.
Async execution
# fire: thread, shares namespace<br>pysh fire work "model = train(X, y)"<br>pysh poll work abc123<br># {"cell_id":"abc123", "status":"done", "output":"..."}<br>pysh run work "model.score(X_test)" # model is there
# fork: child process (POSIX only), killable, pickles vars back<br>pysh fork work "results = expensive_search(params)"<br>pysh int work # SIGKILL the fork (POSIX)
Remote
AI agents can't hold SSH sessions open. The local daemon holds<br>the connection the agent can't hold.
# server<br>pip install pythond<br>pyctl start --listen 0.0.0.0:7984 --show-token<br># Non-loopback --listen auto-enables TLS<br># prints token and cert fingerprint
# client: self-signed server cert must be pinned before connecting<br># copy server ~/.pythond/tls/cert.pem to client as ~/server_cert.pem<br>pyctl pin ~/server_cert.pem<br>pythond daemon<br>pyctl connect work 10.0.0.5:7984 --tls<br>pysh run work "import platform; platform.node()"<br># remote-host-01
mTLS plus token
# client: generate client cert<br>pyctl cert<br># copy client ~/.pythond/tls/cert.pem to server as ~/client_cert.pem
# server: generate server cert, then trust client cert<br>pyctl cert<br># copy server ~/.pythond/tls/cert.pem to client as ~/server_cert.pem<br>pyctl trust ~/client_cert.pem<br>pyctl start --listen 0.0.0.0:7984 --show-token<br># Non-loopback --listen auto-enables TLS<br># cert is required and token is still required
# client: pin server cert, then connect (client cert sent automatically)<br>pyctl pin ~/server_cert.pem<br>pythond daemon<br>pyctl connect work 10.0.0.5:7984 --tls<br>pysh run work "x"
Write file, then exec
Complex code with quotes, f-strings, or SQL? Write a file, load it.<br>No escaping.
cat > /tmp/task.py
Two channels, one namespace
Agent channel (pysh run): Human channel (pysh attach):<br>code in, text out POSIX PTY / Windows WinPTY<br>no ANSI, no parsing tab completion, Ctrl-C<br>WebSocket protocol Ctrl-] to detach<br>\ /<br>same Python namespace
Two control surfaces
pysh run work "x = 1" # agent/script: one-shot command<br>pysh attach work # human developer: interactive attach<br>pyctl status # operator: daemon status
pyctl manages the daemon. pysh manages sessions.<br>No command secretly starts the daemon, creates a session, and attaches in one<br>step. pysh attach is a real PTY on POSIX/WSL. On native Windows it<br>uses WinPTY, which preserves execution and shared state but is not fully<br>byte-transparent for readline screen redraws. Use WSL when exact terminal<br>behaviour matters.
Commands
pysh new create session<br>pysh run "code" sync exec, raw output<br>pysh fire "code" async thread, shares namespace (can't kill C code)<br>pysh fork "code" async process (POSIX), killable, pickles vars back<br>pysh poll [cell_id] check async result<br>pysh int interrupt (fire=best effort, fork=kill)<br>pysh kill terminate session<br>pysh ls list sessions<br>pysh status JSON health<br>pysh vars JSON namespace names<br>pysh complete "text" JSON completion candidates<br>pysh attach human REPL (Ctrl-] to detach)
pyctl start [--listen H:P] [--tls] [--show-token] start daemon<br>pyctl stop stop daemon<br>pyctl status daemon endpoint metadata and liveness<br>pyctl connect [--tls] proxy to remote<br>pyctl disconnect drop remote<br>pyctl cert show/generate TLS cert<br>pyctl trust authorize client<br>pyctl pin verify server
pyctl cert prints the certificate path, key path,<br>fingerprint, and role hints: copy this cert to the server for<br>pyctl trust when this machine is a client, or copy it to the<br>client for pyctl pin when this machine is a server.
Protocol
WebSocket text frames. First line = command. After newline = code body.<br>Python code is never JSON-escaped.
ws.send("run work\nprint('hello')") # "hello"<br>ws.send("fire work\ntrain(epochs=50)") # {"cell_id":"..."}<br>ws.send("ls") # " work: alive"
Security
The security model mirrors SSH:
pythondSSH equivalent<br>token in daemon.jsonprivate key in ~/.ssh/<br>pyctl trust cert.pemadding a line to authorized_keys<br>pyctl pin cert.pemadding a line to known_hosts<br>authenticated clientlogged-in user
Once authenticated, a client has full access to all sessions — no per-session permission isolation. Same as SSH: once you log in, you are that user with all their permissions.
Not a sandbox: code runs with the daemon user's OS permissions.
ModeAuth<br>Local POSIXAF_UNIX...