Install
$ agentstack add skill-samtalki-agentrepl-jl-run-agentrepl ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ● Shell / process execution Used
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
AgentREPL.jl is an MCP server that exposes a persistent Julia REPL (eval, sessions, pkg, revise, plots) over JSON-RPC on STDIO. There is no GUI and no network port, so you drive it by being its MCP client: spawn the server, do the initialize handshake, call tools. The driver .claude/skills/run-agentrepl/driver.mjs does exactly that — use it for everything below.
All paths are relative to the repo root (/Users/sam/Research/AgentREPL.jl).
Prerequisites
Verified on macOS (darwin), Julia 1.12.6, Node v26. Linux is equivalent — there is nothing platform-specific in the launch path.
- Julia 1.12+ — the
juliabinary on PATH. Installed here via juliaup. - Node 18+ — only for
driver.mjs. Uses Node stdlib only, nonpm install.
Setup
Manifest.toml is gitignored, so resolve and precompile deps once after clone (~30s cold):
julia --project=. -e "using Pkg; Pkg.instantiate(); Pkg.precompile()"
Optional — enable Revise.jl hot-reload. Revise is only a test-extra of this package, not a runtime dep, and the worker inherits your global env on its load path. So hot-reload works only if Revise lives in your default environment:
julia -e 'using Pkg; Pkg.activate(); Pkg.add("Revise")'
Without this, info reports Revise.jl: not available and the server logs a Could not load Revise.jl on worker warning (and records a session note) per worker spawn. Eval is unaffected.
Run (agent path)
Drive the server with driver.mjs. It spawns julia --project=. bin/julia-repl-server, handles the handshake, and skips the non-JSON chatter the server interleaves on its streams.
Full smoke test — launches, exercises all 8 tools, prints PASS/FAIL, exits non-zero on any failure (~10s warm, after precompile):
node .claude/skills/run-agentrepl/driver.mjs
One-shot eval — spawn, eval, print the formatted result, exit:
node .claude/skills/run-agentrepl/driver.mjs eval 'using Statistics; mean([1,2,3,4,5])'
Call any tool with a JSON args object:
node .claude/skills/run-agentrepl/driver.mjs call info '{}'
node .claude/skills/run-agentrepl/driver.mjs call session '{"action":"list"}'
Interactive — one Julia expression per stdin line, eval'd on a persistent worker (state carries across lines), Ctrl-D to quit:
printf 'x = collect(1:5)\nsum(x)\nusing UnicodePlots\nlineplot(1:10, sin.(1:10), title="sine")\n' \
| node .claude/skills/run-agentrepl/driver.mjs repl
| command | what it does | |---|---| | driver.mjs | full smoke test over all 8 tools, PASS/FAIL summary | | driver.mjs eval '' | one eval, prints the formatted result | | driver.mjs call '' | call any tool (eval, reset, info, pkg, activate, log_viewer, session, revise) | | driver.mjs repl | interactive eval, one expression per stdin line, state persists |
Plots are ANSI text, not images. UnicodePlots renders to a colored ANSI block. The driver prints it to stdout; capture it to a file to inspect:
node .claude/skills/run-agentrepl/driver.mjs eval 'using UnicodePlots; lineplot(1:10, (1:10).^2)' > /tmp/agentrepl-plot.txt
Env overrides for the driver: JULIA_PROJECT_DIR (point at a different AgentREPL checkout), JULIA_BIN (julia executable path).
Run (human path)
The server is meant to be registered with an MCP client, not run by hand. With Claude Code, install the plugin (claude /plugin add samtalki/AgentREPL.jl) or claude mcp add; see README.md. To launch it raw and confirm it speaks MCP, pipe a handshake into the bare entry point (it reads JSON-RPC on stdin, writes responses on stdout, and blocks waiting for a client):
printf '%s\n%s\n%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"capabilities":{},"clientInfo":{"name":"c","version":"1"},"protocolVersion":"2025-06-18"}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
| julia --project=. bin/julia-repl-server 2>/dev/null \
| grep -o '"name":"[a-z_]*"' | sort -u
Prints the 8 tool names. JULIA_REPL_PROJECT=/path activates a project on the worker; JULIA_REPL_AUDIT_DIR=/path enables per-session audit logs.
Test
julia --project=. -e "using Pkg; Pkg.test()" # Aqua + unit suites (~45s)
AGENTREPL_E2E=true julia --project=. -e "using Pkg; Pkg.test()" # + real server subprocess + transport test
During tests you'll see [worker::stderr] ... lines — that is the worker's drained stderr (e.g. project-activation chatter, Revise warnings), routed to the test process's stderr on purpose. The suite still ends with Testing AgentREPL tests passed.
Gotchas
- Framing is newline-delimited JSON, not LSP
Content-Length. One JSON object per line. A client written for the LSP framing will hang. The driver and the raw-launch snippet above both assume NDJSON. - The stdout transport is clean JSON; diagnostics go to stderr. Malt workers keep their stdout/stderr on private pipes (drained to the server's stderr), and the framework's own logs go to stderr too — so the stdout transport carries only JSON-RPC. The driver still skips non-
{lines defensively, and the bare-launch snippet pipes stderr to/dev/null. - First eval is slow; the worker spawns lazily. No worker exists until the first
eval/pkgcall (or aninfo/pkgtool call) — that call spawns a Malt worker and attempts to load Revise on it. UnicodePlots loads only on the firstusing UnicodePlots. Cold, budget tens of seconds; the driver's per-request timeout is 120s for this reason. Later evals are milliseconds. resetkills the worker and drops all state. It returns fast but the next eval pays the worker spawn cost again. Variables, loaded packages, andusingimports are gone — that is the point (it enables struct/type redefinition).- Revise "not available" is expected on a clean machine. See Setup. It is graceful degradation, not a failure; eval works regardless.
- STDIO only, no port. You cannot
curlthis server. The single local IPC channel issession attach(a chmod-600 Unix socket for an interactive human REPL), which needstmuxand is out of scope for headless driving.
Troubleshooting
timeout (120000ms) waiting for tools/call: almost always the cold first eval's worker spawn colliding with a precompile. Run the Setup precompile first, then retry.- Driver prints
server exited (code=1 ...): the Julia process died on launch. Runjulia --project=. -e "using AgentREPL"directly to see the real error (usually a missingManifest.toml— run the Setup step). Could not load Revise.jl on workerwarning on stderr: harmless. Silence it by adding Revise to your global env (Setup), or ignore it.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: samtalki
- Source: samtalki/AgentREPL.jl
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.