diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 6fdb129..8348e54 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -6,14 +6,14 @@ }, "metadata": { "description": "Julia development tools for Claude Code - persistent REPL, multi-session, Revise hot-reloading, modern workflows", - "version": "0.7.0" + "version": "0.7.1" }, "plugins": [ { "name": "julia", "source": "./claude-plugin", "description": "Persistent Julia REPL for Claude Code - multi-session with Revise.jl hot-reloading, eliminates TTFX startup penalty", - "version": "0.7.0", + "version": "0.7.1", "author": { "name": "Samuel Talkington", "email": "talkington@pm.me" diff --git a/CHANGELOG.md b/CHANGELOG.md index 54925bd..8bb1f8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.7.1] - 2026-06-07 + +### Fixed +- Plugin hooks no longer halt the agent after each eval/edit. All three were `type: prompt`, + which spawns a separate decision-model call per matching tool use and ended the turn with + "stopped continuation", even for scalar eval results. The two prompt hooks that only + restated skill guidance (display code before `eval`; expand results for color plots) are + removed; the `julia-evaluation`/`julia-plot` skills already carry that guidance. The + post-edit revise hook is rewritten as a non-blocking `type: command` hook + (`hooks/revise-nudge.sh`) that injects an `additionalContext` reminder to call `revise` + after a `.jl` edit, so the auto-revise nudge survives without a per-edit model call or a + turn halt. +- Corrected README references to a removed `julia-language` skill; the auto-triggering + skills are `julia-evaluation` and `julia-plot`. + ## [0.7.0] - 2026-06-07 ### Changed @@ -79,7 +94,8 @@ First public release of AgentREPL.jl. ### Note Tmux bidirectional REPL mode is deprecated. Use distributed mode with log_viewer instead. (Removed in 0.6.0) -[Unreleased]: https://github.com/samtalki/AgentREPL.jl/compare/v0.7.0...HEAD +[Unreleased]: https://github.com/samtalki/AgentREPL.jl/compare/v0.7.1...HEAD +[0.7.1]: https://github.com/samtalki/AgentREPL.jl/compare/v0.7.0...v0.7.1 [0.7.0]: https://github.com/samtalki/AgentREPL.jl/compare/v0.6.2...v0.7.0 [0.6.0]: https://github.com/samtalki/AgentREPL.jl/compare/v0.5.0...v0.6.0 [0.5.0]: https://github.com/samtalki/AgentREPL.jl/releases/tag/v0.5.0 diff --git a/CLAUDE.md b/CLAUDE.md index 638d480..f839e55 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -72,7 +72,7 @@ Julia code in REPL output is syntax highlighted using [JuliaSyntaxHighlighting.j ### Plotting -UnicodePlots.jl is a dependency loaded on workers (not in the main module). `capture_eval_on_worker` passes the color preference into the worker so `repr` renders color-aware types (UnicodePlots output) with ANSI. The `julia-plot` skill and a PostToolUse eval hook tell the user to expand the tool result (Ctrl+O) for color rather than pasting ANSI art into chat. +UnicodePlots.jl is a dependency loaded on workers (not in the main module). `capture_eval_on_worker` passes the color preference into the worker so `repr` renders color-aware types (UnicodePlots output) with ANSI. The `julia-plot` skill tells the user to expand the tool result (Ctrl+O) for color rather than pasting ANSI art into chat. ### Audit Logging @@ -185,7 +185,7 @@ The `claude-plugin/` directory contains the plugin itself; `.claude-plugin/marke - Auto-configures the MCP server (no manual `claude mcp add` needed) - Provides user-invoked skills: `/julia-reset`, `/julia-info`, `/julia-pkg`, `/julia-activate`, `/julia-log`, `/julia-session`, `/julia-revise`, `/julia-develop` - Includes auto-triggering skills: `julia-evaluation` (REPL best practices, in `skills/julia/`) and `julia-plot` (plotting guidance) -- Has hooks (`claude-plugin/hooks/hooks.json`): PreToolUse on `eval` (require code displayed before running), PostToolUse on Write/Edit (auto-`revise` after `.jl` edits), PostToolUse on `eval` (tell the user to expand the result for color plots instead of pasting ANSI) +- Has one hook (`claude-plugin/hooks/hooks.json` runs `hooks/revise-nudge.sh`): a non-blocking PostToolUse hook on Write/Edit that injects an `additionalContext` reminder to call `revise` after a `.jl` edit. The guidance to display code before `eval` and to expand plot results for color lives in the `julia-evaluation`/`julia-plot` skills, not hooks. Install with: ```bash diff --git a/Project.toml b/Project.toml index e7a3460..fa785e0 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "AgentREPL" uuid = "c6b0b931-bd15-49f6-a31f-cf7d80eb5e81" -version = "0.7.0" +version = "0.7.1" authors = ["Samuel Talkington "] [deps] diff --git a/README.md b/README.md index 1c8f88d..fcaa198 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ AgentREPL is the simplest way to give Claude Code a persistent Julia session. Th 1. **Zero-friction setup.** STDIO transport means Claude Code spawns and manages the Julia process automatically. No server to start, no port to configure, no process to monitor. Install the plugin and start coding. -2. **Workflow-native Revise.jl.** Every worker auto-loads Revise.jl. The plugin's PostToolUse hook automatically calls `revise` after you edit `.jl` files. You never manually reload code. +2. **Workflow-native Revise.jl.** Every worker auto-loads Revise.jl, and a non-blocking PostToolUse hook reminds the model to call `revise` after you edit `.jl` files, so you rarely reload code by hand. 3. **True process isolation.** Each session is a separate Malt.jl worker process. You can redefine structs, kill crashed sessions, and run parallel workloads without cross-contamination. `reset` does what it says -- complete state erasure including type definitions. @@ -44,8 +44,8 @@ claude /plugin add samtalki/AgentREPL.jl This provides: - Auto-configured MCP server (no manual setup) - 8 skills: `/julia-reset`, `/julia-info`, `/julia-pkg`, `/julia-activate`, `/julia-log`, `/julia-session`, `/julia-revise`, `/julia-develop` -- Auto-triggering skills for Julia evaluation best practices and language expertise -- Hooks: code display validation before `eval`, automatic `revise` after `.jl` file edits +- Auto-triggering skills for Julia evaluation best practices and plotting +- A non-blocking hook that reminds the model to `revise` after `.jl` file edits ### Option B: Manual MCP Configuration @@ -394,7 +394,7 @@ The activated environment persists across `reset` calls. | Auto-start from Claude Code | Yes | No | No | | Dependencies | 6 (3 stdlib) | 30+ | Few | | Session isolation | Process-level (Malt.jl) | Via Gate | Shared REPL | -| Revise.jl integration | Auto-load + auto-revise hook | Manual | No | +| Revise.jl integration | Auto-load + revise nudge (hook + skill) | Manual | No | | True hard reset (type redef) | Yes | N/A | No | | Debugging (breakpoints, stepping) | No | Yes (VS Code) | No | | Semantic code search | No | Yes (Qdrant) | No | @@ -442,12 +442,11 @@ No need to manually run `claude mcp add`. The plugin configures the Julia MCP se | `/julia:julia-revise [action] [path]` | Hot-reload code changes | | `/julia:julia-develop [path]` | Set up development workflow | -**Auto-triggering:** `julia-evaluation` (best practices for REPL usage) and `julia-language` (deep Julia expertise: types, dispatch, metaprogramming, performance). +**Auto-triggering:** `julia-evaluation` (best practices for REPL usage) and `julia-plot` (UnicodePlots plotting guidance). ### Hooks -- **PreToolUse (eval)**: Validates that Julia code is displayed in a readable format before calling eval -- **PostToolUse (Write/Edit)**: Automatically calls `revise` after editing `.jl` files to hot-reload changes +- **PostToolUse (Write/Edit)**: A non-blocking `type: command` hook that reminds the model to call `revise` after editing `.jl` files, so the session hot-reloads without losing state. The display-code-before-eval and plot-expansion guidance lives in the `julia-evaluation` and `julia-plot` skills. ### Installation ```bash diff --git a/claude-plugin/.claude-plugin/plugin.json b/claude-plugin/.claude-plugin/plugin.json index 94aca46..7a25a87 100644 --- a/claude-plugin/.claude-plugin/plugin.json +++ b/claude-plugin/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "julia", - "version": "0.7.0", + "version": "0.7.1", "description": "Persistent Julia REPL for Claude Code — multi-session with Revise.jl hot-reloading, eliminates TTFX startup penalty", "repository": "https://github.com/samtalki/AgentREPL.jl", "homepage": "https://github.com/samtalki/AgentREPL.jl", diff --git a/claude-plugin/README.md b/claude-plugin/README.md index 5ff82ab..f916ac2 100644 --- a/claude-plugin/README.md +++ b/claude-plugin/README.md @@ -56,9 +56,9 @@ All tools except `log_viewer` and `session` accept an optional `session` paramet ### Hooks -- **PreToolUse (eval)** - Ensures Julia code is displayed in a readable format before calling eval -- **PostToolUse (Write/Edit)** - Automatically calls `revise` after editing `.jl` files to hot-reload changes -- **PostToolUse (eval)** - Pastes rich visual output (plots, tables, matrices) as raw text to preserve ANSI colors +- **PostToolUse (Write/Edit)** - A non-blocking `type: command` hook (`hooks/revise-nudge.sh`) that reminds the model to call `revise` after editing `.jl` files, so the session hot-reloads without losing state. + +The guidance to display code before eval and to expand plot results lives in the `julia-evaluation` and `julia-plot` skills, not hooks. ## Architecture @@ -76,7 +76,7 @@ The plugin is designed to **minimize REPL restarts**: 1. **Revise.jl** auto-loads on every worker — edit `.jl` files and hot-reload without losing state 2. **Multiple sessions** — isolate risky work without affecting your main session -3. **PostToolUse hook** — automatically hot-reloads after editing Julia files +3. **PostToolUse hook** — reminds the model to `revise` after editing `.jl` files (non-blocking; never halts the turn) 4. **Reset is a last resort** — only needed for struct layout changes (Julia < 1.12) or corrupted state ## Usage @@ -106,7 +106,7 @@ On first use, Claude will ask about your environment preference: # Edit source files... -/julia:julia-revise # Hot-reload changes (or automatic via hook) +/julia:julia-revise # Hot-reload changes (the PostToolUse hook reminds you automatically) /julia:julia-pkg test # Run tests ``` diff --git a/claude-plugin/hooks/hooks.json b/claude-plugin/hooks/hooks.json index 004140b..d39ff04 100644 --- a/claude-plugin/hooks/hooks.json +++ b/claude-plugin/hooks/hooks.json @@ -1,32 +1,12 @@ { "hooks": { - "PreToolUse": [ - { - "matcher": "mcp__plugin_julia_julia-repl__eval", - "hooks": [ - { - "type": "prompt", - "prompt": "Before calling eval, display the Julia code you are about to evaluate in a ```julia code block in your response text. The MCP permission prompt shows code as an escaped string which is unreadable — the user needs to see formatted code first." - } - ] - } - ], "PostToolUse": [ { "matcher": "Write|Edit", "hooks": [ { - "type": "prompt", - "prompt": "If the file just written or edited ends in .jl (a Julia source file) and a Julia REPL session is active (i.e., you have previously called eval, session, or any julia-repl MCP tool in this conversation), call the revise MCP tool with action='revise' to hot-reload the changes into the active Julia session. This preserves session state and avoids needing a reset. Do NOT call revise for non-.jl files or if no Julia session has been started yet." - } - ] - }, - { - "matcher": "mcp__plugin_julia_julia-repl__eval", - "hooks": [ - { - "type": "prompt", - "prompt": "If the eval result contains visual output (Unicode plots with Braille characters, heatmaps, density plots), tell the user to expand the tool result to see it with full color: 'Expand the eval result above (Ctrl+O) to see the plot with colors.' Do NOT paste plot/ANSI art into your message — it loses colors and streams painfully slowly. For structured text output (tables, matrices, DataFrames), paste it in a fenced code block. Do not paste simple scalars or errors." + "type": "command", + "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/revise-nudge.sh\"" } ] } diff --git a/claude-plugin/hooks/revise-nudge.sh b/claude-plugin/hooks/revise-nudge.sh new file mode 100755 index 0000000..a182aef --- /dev/null +++ b/claude-plugin/hooks/revise-nudge.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# PostToolUse(Write|Edit): if a .jl file was edited, remind the model to hot-reload via the +# revise MCP tool. Non-blocking — emits additionalContext only; never blocks or halts. +set -euo pipefail +payload="$(cat)" +if printf '%s' "$payload" | grep -qE '"file_path"[[:space:]]*:[[:space:]]*"[^"]*\.jl"'; then + printf '%s' '{"hookSpecificOutput":{"hookEventName":"PostToolUse","additionalContext":"A .jl file was edited. If a Julia REPL session is active, call the revise MCP tool with action=revise to hot-reload the change without losing session state."}}' +fi diff --git a/claude-plugin/skills/julia-plot/SKILL.md b/claude-plugin/skills/julia-plot/SKILL.md index 4937b7c..a25f9e6 100644 --- a/claude-plugin/skills/julia-plot/SKILL.md +++ b/claude-plugin/skills/julia-plot/SKILL.md @@ -1,7 +1,7 @@ --- name: julia-plot description: Activates when user asks to plot, chart, or visualize data in the Julia REPL. -version: 0.7.0 +version: 0.7.1 --- # Julia Plotting — UnicodePlots diff --git a/claude-plugin/skills/julia/SKILL.md b/claude-plugin/skills/julia/SKILL.md index d10e443..403201c 100644 --- a/claude-plugin/skills/julia/SKILL.md +++ b/claude-plugin/skills/julia/SKILL.md @@ -1,7 +1,7 @@ --- name: julia-evaluation description: Activates when user asks to run, evaluate, or test Julia code in a persistent REPL session, or mentions Julia REPL, Julia session, or hot-reloading Julia changes. -version: 0.7.0 +version: 0.7.1 --- # Julia REPL — Behavioral Rules @@ -26,7 +26,7 @@ Prefer `revise` — it preserves session state. Only `reset` when required. | Struct layout (Julia < 1.12) | `reset` required | | Corrupted state / stuck code | `reset` required | -After editing `.jl` files, call `revise(action="revise")` to hot-reload (the PostToolUse hook may do this automatically). +After editing `.jl` files, call `revise(action="revise")` to hot-reload (a PostToolUse hook reminds you after `.jl` edits). ## Error Recovery diff --git a/test/test_plugin_validation.sh b/test/test_plugin_validation.sh index 21d3e21..a6f58d1 100755 --- a/test/test_plugin_validation.sh +++ b/test/test_plugin_validation.sh @@ -72,13 +72,19 @@ fi check ".mcp.json references julia-repl-server" \ "grep -q 'julia-repl-server' '$PLUGIN_DIR/.mcp.json'" -# --- hooks.json has expected hooks --- -check "hooks.json has PreToolUse hook" \ - "grep -q 'PreToolUse' '$PLUGIN_DIR/hooks/hooks.json'" +# --- hooks.json wires the non-blocking revise nudge --- +check "hooks.json is valid JSON" \ + "! command -v python3 >/dev/null 2>&1 || python3 -c \"import json; json.load(open('$PLUGIN_DIR/hooks/hooks.json'))\" 2>/dev/null" check "hooks.json has PostToolUse hook" \ "grep -q 'PostToolUse' '$PLUGIN_DIR/hooks/hooks.json'" +check "hooks.json references revise-nudge.sh" \ + "grep -q 'revise-nudge.sh' '$PLUGIN_DIR/hooks/hooks.json'" + +check "revise-nudge.sh exists" \ + "[ -f '$PLUGIN_DIR/hooks/revise-nudge.sh' ]" + # --- Server entry point exists --- check "bin/julia-repl-server exists" \ "[ -f '$REPO_DIR/bin/julia-repl-server' ]"