[BUG] skill-creator run_loop.py: --results-dir stays empty when parent session compacts (no per-iteration flush + lost task handle)

Resolved 💬 2 comments Opened Apr 23, 2026 by thomHayner Closed May 28, 2026

Preflight

  • Searched existing issues, no duplicate for this specific mechanism
  • Single bug report
  • Claude Code v2.1.98 (latest at time of filing)

What's Wrong?

When skill-creator's run_loop.py is launched as a background Bash task (run_in_background: true) and the parent Claude Code session auto-compacts while the loop is still running, the user is left with an empty --results-dir and no way to monitor or recover the work — even though the background process itself keeps running.

What Should Happen?

Either:

  • Partial results.json / HTML report should land in --results-dir on every iteration so progress is recoverable after any mid-flight termination, or
  • The parent session should retain (or re-attach to) the background-task handle after compaction so BashOutput still works.

Ideally both. Today neither happens, and the two combine into silent data loss from the user's perspective.

Error Messages/Logs

No errors. That's part of the problem — ~/.claude/debug/latest contains zero 429 / rate_limit / overloaded_error / quota / SIGKILL / SIGTERM hits across the window. The process wasn't killed and didn't error; it just became unobservable.

Steps to Reproduce

  1. Install the skill-creator plugin from claude-plugins-official.
  2. In a Claude Code session, kick off the optimizer as a background Bash task with a --results-dir argument and a workload that will take longer than the remaining context budget, e.g.:

``bash
python -m scripts.run_loop \
--eval-set <path> \
--skill-path <path> \
--results-dir /tmp/claude-runs \
--max-iterations 10 \
--model claude-opus-4-7
`
launched via the Bash tool with
run_in_background: true`.

  1. Continue working in the parent session until auto-compaction fires.
  2. After compaction, observe:
  • /tmp/claude-runs/<timestamp>/ exists but is empty
  • BashOutput on the old task handle returns nothing useful
  • ps and disk activity (fixture files mutating under the skill being evaluated) show the underlying workers are still running
  • No live report in --results-dir — it's actually in $TMPDIR/skill_description_report_<name>_<timestamp>.html, which the user has no way to know about without reading run_loop.py

Confirmed mechanism (two separate things, both needed)

1. run_loop.py does not flush to --results-dir until the loop finishes.

In skill-creator/scripts/run_loop.py:

  • Per-iteration progress is written to a live HTML report path in tempfile.gettempdir() (line ~274), not under --results-dir.
  • results.json is only written after the loop returns (line ~313).
  • report.html in --results-dir is also only written after the loop returns (line ~321).
  • If the loop doesn't complete, --results-dir stays empty indefinitely. Mine did — the timestamped subdir was created, then never written to again.

2. Claude Code loses the background-task handle across parent-session compaction.

After auto-compaction, the parent session cannot BashOutput the previously-backgrounded task. The process itself continues — in my case, parallel subagent workers kept mutating fixture files on disk for minutes after compaction, and the dynamic skill-list hashes in system reminders kept rotating, then cleaned up normally. No kill, no signal.

Claude Model

Opus (claude-opus-4-7)

Claude Code Version

2.1.98

Platform

Anthropic API

Operating System

macOS 26.4.1

Additional Information

The original version of this issue claimed the process was "killed" by compaction and later speculated about a rate-limit null-return. Both were wrong — see correction comment below. An independent re-scan of the debug log and disk state did not support either claim; the real bug is the narrower two-part mechanism above. Leaving the issue open against that narrower claim.

Suggested labels for maintainer triage: area:skills, area:bash, has repro, data-loss, claude-code-assisted.

Suggested fixes (either/both):

  • In run_loop.py: flush a partial results.json (and/or copy the live HTML) into --results-dir on every iteration, not only after the loop returns. Cheap, survives any kind of mid-flight termination or lost handle.
  • In Claude Code: on parent-session compaction, preserve (or re-attach to) background-task handles so BashOutput still works post-compaction. At minimum, surface a warning that backgrounded work is now unobservable so the user knows to check disk directly.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗