Opp repl shared terminal
Run opp_repl inside a shared tmux session with its MCP server exposed, so a human (attached to tmux) AND an AI assistant (Claude Code, Windsurf, Cursor, VS Code) drive the SAME live IPython/OMNeT++ namespace at once. Default transport is a Unix domain socket reached via opp_repl_mcp_bridge; a TCP+bearer-token mode is available for remote clients. Bundled scripts start/attach/stop the session and write the client config. Load when the user wants to co-pilot one persistent opp_repl session with an AI.From its SKILL.md
npx -y skills add tabgab/opp_repl-skill --skill opp-repl-shared-terminalAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
10.3 KB, ~2.6k tokens by cl100k_base, as published. Nobody here has run it
opp_repl shared-terminal mode (tmux + MCP)
This skill stands up a single opp_repl process driven concurrently by two clients:
- the human user, who
tmux attaches and types at the live IPython prompt; - an AI assistant (Claude Code, Windsurf, Cursor, VS Code, or any
MCP client), which calls the
execute_pythonMCP tool.
Because execute_python runs in the same IPython namespace as the
interactive user, all state (loaded projects, results, variables,
imports) is genuinely shared — no context drift between what the user
sees and what the AI sees. It is one process.
This composes the base pack (opp-repl-mcp-server, opp-repl-repl-usage)
into a collaboration workflow; load those for the underlying details.
When to use
- "I want Claude Code and me to share one opp_repl terminal."
- The AI should inspect/extend simulation work the user is doing live, or the user should watch and steer what the AI runs.
- One persistent OMNeT++ session that survives closing the AI client or terminal emulator.
For plain single-user opp_repl, use opp-repl-repl-usage. For the MCP
transport details and per-client config, see opp-repl-mcp-server.
Architecture
┌────────────────────────────────────┐
│ tmux session: opp_repl │
│ ┌──────────────────────────────┐ │
user ─►│ │ opp_repl (IPython) │ │ stdio ┌───────────────┐
attach │ │ --mcp-socket <path> │◄─┼── bridge ──┤ opp_repl_ │◄─ AI client
│ │ --load ... │ │ (UDS) │ mcp_bridge │ (Claude Code,
│ └──────────────────────────────┘ │ └───────────────┘ Windsurf, …)
└────────────────────────────────────┘
- One opp_repl process; tmux owns its PTY so the user can attach.
- Default: opp_repl listens on a Unix domain socket; AI clients
spawn
opp_repl_mcp_bridge(stdio↔socket). No token needed — the socket's0600permissions are the access control. - Fallback:
--http [PORT]exposes streamable HTTP on127.0.0.1with a bearer token, for remote clients or older opp_repl.
Prerequisites
- opp_repl installed with the MCP extra:
pip install "opp_repl[mcp]"(opp_replandopp_repl_mcp_bridgeon PATH after sourcing the OMNeT++setenv/ activating the venv). tmuxinstalled.- The AI client runs on the same host (socket and TCP both bind locally). For a remote client, forward over SSH and keep auth on.
Files in this skill
scripts/start_shared_repl.sh— start opp_repl in tmux with the MCP server, wait for it, and write the AI client's config. Socket transport by default;--http [PORT]for TCP+token.scripts/attach_repl.sh—tmux attachto type at the live prompt (--read-onlyto watch only).scripts/stop_repl.sh— graceful shutdown (sendsexit, then kills the session if it lingers); shreds the token / removes the socket.scripts/configure_mcp_client.sh— (re)write a client's MCP config for Claude Code / Windsurf / VS Code without restarting the REPL.templates/claude_code_mcp.json,templates/windsurf_mcp_config.json— reference config shapes.
All scripts are POSIX-bash and work on Linux and macOS.
Procedure
1. Verify prerequisites
command -v tmux opp_repl opp_repl_mcp_bridge
echo "$OMNETPP_ROOT" # source the OMNeT++ setenv first if unset
2. Start the shared session
From this skill directory:
scripts/start_shared_repl.sh \
[--session-name opp_repl] \
[--load '<.opp glob>' ...] \
[--client claude|windsurf|vscode|none] \ # default: claude
[--http [PORT]] \ # default: Unix socket
[--detach]
Defaults: socket transport, client claude, and — when no --load is
given — $OMNETPP_ROOT/omnetpp.opp + $OMNETPP_ROOT/samples/*/*.opp,
or the bundled --load @opp descriptors. Without --detach you are
attached to tmux immediately.
The script:
- Aborts if a tmux session of that name exists (stop it first, or use
a different
--session-name). - Socket mode: picks
~/.opp_repl_shared/mcp-<session>.sockand runsopp_repl --mcp-socket <path> --load …. HTTP mode: mints a token, passes its SHA-256 via--mcp-token-hash(or--mcp-bypass-token-hash-checkon older opp_repl). - Polls the endpoint until it answers (socket via
curl --unix-socket). - Writes the chosen client's MCP config (see step 4).
- Attaches you to tmux (unless
--detach).
3. Attach from any terminal
scripts/attach_repl.sh # read-write
scripts/attach_repl.sh --read-only
Detach with Ctrl-b d. Multiple terminals may attach at once; every
keystroke is visible to the AI because they share one kernel.
4. Point the AI client at the session
start_shared_repl.sh already wrote the config for --client
(default Claude Code → a project .mcp.json). To (re)configure later,
or target a different client:
scripts/configure_mcp_client.sh --client claude # or windsurf | vscode
Then reload the client:
- Claude Code: restart / reload the window (or
claude mcp add --transport stdio opp_repl -- opp_repl_mcp_bridge). - Windsurf: restart or "Refresh MCP servers".
- VS Code/Cursor: reload the window.
The opp_repl server should expose the execute_python tool and the
opp-repl://… resources.
5. Stop the session
scripts/stop_repl.sh
Sends exit to IPython (flushes pending writes), waits up to 5 s, then
kills the session if needed, and cleans up the token/socket.
What is actually shared
- Python namespace: yes.
execute_pythonruns in the REPL'suser_nsvia IPythonrun_cell; variables/imports cross both ways. - stdout/stderr: yes — AI-triggered output appears in the tmux pane and its scrollback.
- Input prompt: NOT shared. Only the user types at
In [N]:; the AI submits cells over MCP. opp_repl serialises cell execution, so a long-running cell on one side queues the other. - Working directory / env vars: shared (one process).
- Simulation subprocesses: spawned by opp_repl; a
run_simulations()on one side blocks a conflicting run from the other until it returns.
Transports
- Unix socket (default, recommended): no token;
0600perms; AI clients useopp_repl_mcp_bridge. Best for a local human+AI pair. - TCP + token (
--http): streamable HTTP on127.0.0.1, bearer token in theAuthorizationheader. Use for remote clients (over an SSH tunnel) or opp_repl builds without the socket transport.
Full details and per-client config shapes are in opp-repl-mcp-server.
Pitfalls
- Token rotation (HTTP mode): every
--httpstart mints a new token and rewrites the client config — reload the client or it 401s. - Stale session / socket: a crashed REPL can leave the tmux session
or socket file behind.
stop_repl.shcleans both; re-run start after. - Bind address: the socket and TCP port are local. For a remote
client, forward over SSH (
ssh -Lfor TCP, or run the bridge on the host) and keep auth on — never expose TCP unauthenticated. - opp_repl not on PATH: the start script sources
$OMNETPP_ROOT/setenvwhen set; ifOMNETPP_ROOTis wrong, the env is silently incomplete. Alwaysecho $OMNETPP_ROOTandcommand -v opp_replbefore filing a bug. - MCP cancellation ≠ Ctrl-C: the client's "stop" maps to opp_repl's
cooperative interrupt; it does not instantly kill a running
opp_runsubprocess. Use the user-side prompt toCtrl-Can in-flight sim. - Non-strict client config: if the target config has comments or
trailing commas, the JSON merge refuses to overwrite — fix it by hand
and re-run
configure_mcp_client.sh. - Config scope: Claude Code
.mcp.jsonis written in the current directory (project scope); run start/configure from the workspace you drive the AI from, or passCLAUDE_MCP_CONFIG=~/.claude.json.
Verification
After start_shared_repl.sh returns and you're attached:
In [1]: shared_marker = "hello from user"
Ask the AI (via chat) to execute_python("shared_marker") — it should
return 'hello from user'. Have it set another variable; re-attach and
confirm it's visible at the prompt.
Without an AI client — hit the endpoint directly:
# Socket transport:
SOCK=$(cat ~/.opp_repl_shared/socket)
curl -sN --unix-socket "$SOCK" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"execute_python","arguments":{"code":"print(\"mcp ok\")"}}}' \
http://localhost/mcp
# TCP transport (--http):
TOKEN=$(cat ~/.opp_repl_shared/token)
curl -sN -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"execute_python","arguments":{"code":"print(\"mcp ok\")"}}}' \
http://127.0.0.1:9966/mcp
Expect a streaming response containing mcp ok; the same line appears
in the tmux pane the user is watching.
See also
opp-repl-mcp-server— transports, auth, and per-client config.opp-repl-repl-usage— the interactive REPL the user drives.opp-repl-sandbox— isolate the shared server under bubblewrap.opp-repl-ai-workflows— what the AI does once connected.opp-repl-overview— map of which skills to load when.
What ships with it: 6 files
16.2 KB alongside SKILL.md, 4 of them executable
scripts/
- attach_repl.shruns884 B
- configure_mcp_client.shruns4.7 KB
- start_shared_repl.shruns7.8 KB
- stop_repl.shruns1.7 KB