Skip to content

skill(libtmux-profiler): Tachyon profiling workflows for libtmux/tmuxp#663

Draft
tony wants to merge 2 commits into
masterfrom
2026-04-libtmux-profiler-skill
Draft

skill(libtmux-profiler): Tachyon profiling workflows for libtmux/tmuxp#663
tony wants to merge 2 commits into
masterfrom
2026-04-libtmux-profiler-skill

Conversation

@tony

@tony tony commented Apr 29, 2026

Copy link
Copy Markdown
Member

Summary

Adds a Claude Code skill at .claude/skills/libtmux-profiler/ that documents and automates Python 3.15's stdlib profiling.sampling (Tachyon) for libtmux/tmuxp work. Pure tooling addition — no runtime code changes, no public API impact.

What's in here

The skill itself

SKILL.md documents seven workflows for libtmux/tmuxp performance investigation:

  • pstats top-N — terminal-only summary of dominant wall-time consumers
  • Automated pstats diff — structured before/after comparison via the bundled diff-pstats.py helper (replaces Python 3.15.0a8's broken --diff-flamegraph)
  • Single-call microbenchmark — tight-loop per-call timing of one libtmux API
  • Heatmap — line-level attribution within a hot function
  • Live TUI — top(1)-style real-time profiler
  • Attach to a running pytest — diagnose hangs without restart
  • Sampling mode selection guide (wall / cpu / gil / exception)

reference/flamegraph-reading.md is a visual-signature cheat sheet for plain and diff flamegraphs.

Helper scripts

Each script in .claude/skills/libtmux-profiler/scripts/ solves a single discrete problem:

setup-tachyon-venv.sh — idempotent bootstrap that creates a .venv-3.15 venv with libtmux installed editable plus the testing dep group. Skips the dev group because watchfiles has no Rust wheel for 3.15a8 yet.

init-profile-session.sh — builds the per-session output directory at /tmp/py-profiling/<TS>/<project>/<branch>/<name>/ and writes a README with HEAD short-sha so the artifact set stays reconstructable after the branch moves.

bench-libtmux-call.py — tight-loop microbench against a real tmux server. Uses a registry-of-callables design (BENCH_TARGETS dict) so the script can never execute caller-supplied Python expressions. Built-in targets: has_session, list_sessions, list_windows, session_name, show_options, list_panes.

diff-pstats.py — markdown table of cumtime deltas between two .pstats files, sorted by abs(Δ) so the biggest movers surface first. Paste-ready for PRs, issues, or chat.

Toolchain bump

.tool-versions adds Python 3.15.0a8 alongside the existing 3.10-3.14. The project's pinned Python (3.14) is unchanged — 3.15 is only used by the skill's .venv-3.15 venv.

.gitignore overrides the global .claude/ ignore so this skill ships with the repo.

What this is not

  • No runtime code changes. Nothing in src/libtmux/ is touched.
  • No new dependencies. The venv is created on demand by the bootstrap script.
  • No CI changes. The skill is invoked manually by Claude Code agents working on the repo.

Verification

The skill is non-runtime, so verification is mostly "the bootstrap is idempotent and the helpers don't crash."

The setup script is idempotent — safe to re-run, skips work when the venv already exists:

$ bash .claude/skills/libtmux-profiler/scripts/setup-tachyon-venv.sh

Smoke-test the diff helper against any two .pstats files:

$ ./.venv-3.15/bin/python .claude/skills/libtmux-profiler/scripts/diff-pstats.py path/to/baseline.pstats path/to/current.pstats --top 10

Smoke-test the microbench against the default has_session target:

$ BENCH_ITERS=100 ./.venv-3.15/bin/python .claude/skills/libtmux-profiler/scripts/bench-libtmux-call.py

Test plan

  • Bootstrap runs cleanly on a fresh checkout (requires Python 3.15.0a8 via mise)
  • Each helper script runs without errors
  • pytest is unaffected — same 885 + 1 skipped as on master
@codecov

codecov Bot commented Apr 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 51.29%. Comparing base (5a34cc5) to head (041a80f).
⚠️ Report is 96 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #663   +/-   ##
=======================================
  Coverage   51.29%   51.29%           
=======================================
  Files          25       25           
  Lines        3488     3488           
  Branches      686      686           
=======================================
  Hits         1789     1789           
  Misses       1404     1404           
  Partials      295      295           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
@tony tony force-pushed the 2026-04-libtmux-profiler-skill branch from b6b40f1 to aeb0ed0 Compare May 10, 2026 16:01
tony added 2 commits May 30, 2026 06:56
why: Python 3.15 ships the new profiling.sampling stdlib module
("Tachyon"), a statistical sampling profiler that produces flamegraphs,
heatmaps, and Gecko-format call trees with zero target instrumentation.
It works on WSL where kernel perf is unavailable. We're using it to
profile libtmux's bench-engines path and identify lag sources outside
the engine layer (e.g. tmuxp's _wait_for_pane_ready loop).
what:
- .tool-versions: append 3.15.0a8 to the python line so `mise install`
  picks it up alongside the existing 3.10-3.14 matrix. The first entry
  (3.14) remains the default for project tooling; 3.15 is for ad-hoc
  profiling
…/skills/

why: Profiling investigations against libtmux/tmuxp historically required
ad-hoc cProfile invocations and manual flamegraph wrangling. Python 3.15's
new stdlib `profiling.sampling` module (Tachyon) ships everything needed
in-tree — flamegraphs, heatmaps, line-level attribution, pstats — but the
"how to use it on this codebase" knowledge isn't discoverable from the
module help. This skill is the institutional capital that makes Tachyon
trivially repeatable on libtmux/tmuxp work.
what:
- SKILL.md with workflows for: pstats top-N (terminal-only summary),
  automated pstats diff (before/after with the bundled diff-pstats.py
  helper, replaces the broken --diff-flamegraph alpha), single-call
  microbench (per-call timing of one libtmux API), heatmap (line-level
  attribution), live TUI (top(1)-style real-time profiler), attach to a
  running pytest (diagnose hangs without restart), sampling-mode
  selection guide, output-reading cheat sheet
- scripts/setup-tachyon-venv.sh: idempotent bootstrap that creates
  `.venv-3.15` with libtmux installed editable + the testing dep group
  (skips dev because watchfiles has no Rust wheel for 3.15a8 yet)
- scripts/init-profile-session.sh: builds the per-session output
  directory at /tmp/py-profiling/<TS>/<project>/<branch>/<name>/ and
  writes a README.md with HEAD short-sha so the artifact set stays
  reconstructable after the branch moves
- scripts/bench-libtmux-call.py: tight-loop microbench against a real
  tmux server using a registry-of-callables design (BENCH_TARGETS dict)
  so the script can never execute caller-supplied Python expressions.
  Targets: has_session, list_sessions, list_windows, session_name,
  show_options, list_panes
- scripts/diff-pstats.py: structured pstats arithmetic — loads two
  .pstats files, computes per-function cumtime deltas, prints a
  markdown table sorted by abs(delta) for paste-into-PR/issue use.
  Replaces Python 3.15.0a8's broken `--diff-flamegraph` until the
  upstream UnboundLocalError is fixed
- reference/flamegraph-reading.md: visual-signature cheat sheet for
  reading plain flamegraphs (sleep loops, fixture setup, dispatch
  chains) and diff flamegraphs (when 3.15 fixes the alpha bug)
- .gitignore: override the global `.claude/` ignore so this skill
  ships with the repo
@tony tony force-pushed the 2026-04-libtmux-profiler-skill branch from aeb0ed0 to 041a80f Compare May 30, 2026 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant