From 95820357f61e5d00c6626d2a7f00f4b12a335eee Mon Sep 17 00:00:00 2001 From: alexismunoz1 Date: Sat, 6 Jun 2026 14:48:17 -0300 Subject: [PATCH] fix(topic): stop writing 'Error: Reached max turns 1' as topic when MCPs are configured The async claude -p refinement loaded MCP servers, letting a tool call burn the single allowed turn; the CLI then emitted the max-turns error to stdout, which slipped past 2>/dev/null and the permissive sanitizer to become the topic. Run the refinement with --strict-mcp-config and no tools so the turn can't be consumed, parse --output-format json accepting .result only when is_error is false, and guard against any leftover CLI error string. --- CHANGELOG.md | 5 +++++ package.json | 2 +- scripts/user-prompt-hook.sh | 20 ++++++++++++++++++-- skills/set-topic/SKILL.md | 2 +- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d7357c..13661cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [5.3.2] — 2026-06-06 + +### Fixed +- Topic no longer shows the literal `Error: Reached max turns 1` when MCP servers are configured. The async `claude -p` refinement now runs with `--strict-mcp-config` and no tools, so the single allowed turn can't be consumed by a tool call. The call also uses `--output-format json` and only accepts `.result` when `is_error` is false, with a guard that discards any leftover CLI error string so the heuristic topic is kept instead. + ## [5.2.4] — 2026-06-01 ### Docs diff --git a/package.json b/package.json index a182e95..c4a5b7a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@alexismunozdev/claude-session-topics", - "version": "5.3.1", + "version": "5.3.2", "description": "Session topics for Claude Code — auto-set and display a topic in the statusline, change anytime with /set-topic", "bin": { "claude-session-topics": "bin/install.js" diff --git a/scripts/user-prompt-hook.sh b/scripts/user-prompt-hook.sh index 6ffdfc3..669c42f 100755 --- a/scripts/user-prompt-hook.sh +++ b/scripts/user-prompt-hook.sh @@ -279,11 +279,27 @@ refine_topic() { full_prompt=$(printf '%s\n\nConversación:\n%s' "$instruction" "$context") local refined out_file="${TOPIC_FILE}.refine.$$" + # --strict-mcp-config + --allowedTools "" load zero MCP servers and no tools, + # so the model can't burn the single turn on a tool call (which would make the + # CLI emit "Error: Reached max turns 1" to stdout and get written as the topic). + # --output-format json lets us accept the result only when is_error is false. printf '%s' "$full_prompt" | CLAUDE_SESSION_TOPICS_SKIP=1 \ - run_with_timeout 30 claude -p --model haiku --max-turns 1 >"$out_file" 2>/dev/null || true - refined=$(tr -d '\r' < "$out_file" 2>/dev/null | grep -v '^[[:space:]]*$' | head -n 1 || true) + run_with_timeout 30 claude -p --model haiku --max-turns 1 \ + --strict-mcp-config --allowedTools "" --output-format json >"$out_file" 2>/dev/null || true + if command -v jq >/dev/null 2>&1; then + refined=$(jq -r 'select(.is_error == false) | .result // empty' "$out_file" 2>/dev/null \ + | grep -v '^[[:space:]]*$' | head -n 1 || true) + else + refined=$(tr -d '\r' < "$out_file" 2>/dev/null | grep -v '^[[:space:]]*$' | head -n 1 || true) + fi rm -f "$out_file" + # Guard: never let a CLI error string become the topic (belt-and-suspenders for + # the jq-less path or unexpected error formats). + case "$refined" in + Error:*|*"Reached max turns"*|*"Execution error"*) refined="" ;; + esac + # Sanitize: strip quotes, trim, whitelist chars, truncate refined=$(printf '%s' "$refined" \ | sed -E 's/^[[:space:]"'"'"'`]+//;s/[[:space:]"'"'"'`.,:;!?]+$//' \ diff --git a/skills/set-topic/SKILL.md b/skills/set-topic/SKILL.md index daed3cc..c36f4c6 100644 --- a/skills/set-topic/SKILL.md +++ b/skills/set-topic/SKILL.md @@ -3,7 +3,7 @@ name: set-topic description: Set or change the session topic displayed in the statusline argument-hint: allowed-tools: [Bash] -version: "5.3.1" +version: "5.3.2" --- Set the session topic to: $ARGUMENTS