Help us improve
Share bugs, ideas, or general feedback.
From agent-squad-hr
Diagnose "I edited the template / view / CSS but Flask debug-mode keeps serving the old version" when running a local dev server (Flask, Django runserver, Rails server, etc.) from one git worktree while editing files in a sibling worktree of the same repo. Use when: (1) you have multiple `git worktree` checkouts of the same repo (typical with `.claude/worktrees/<feature>` directories), (2) a dev server is running in worktree A serving its working tree, (3) you're making edits in worktree B because branch X is checked out at A and you can't `git checkout X` in B too, (4) `curl http://127.0.0.1:PORT/page` returns byte-identical responses despite your edits, (5) you're tempted to blame Jinja bytecode cache, Flask `@_ttl_cache`, or browser caching. Root cause is filesystem-level: each git worktree has its own independent working tree on disk; Flask is reading worktree A's files, not worktree B's. Cache-busting tricks (`touch app.py`, browser hard refresh, restart Flask) won't help. Sister skill to `flask-debug-ttl-cache-stale-after-rebake` (genuine TTL cache trap) and `gh-pr-merge-worktree-checkout-trap` (branch-checked-out-elsewhere errors). Different from `deploy-from-stale-worktree-silent-rollback` (which covers Cloud Run / Docker production deploys, not localhost).
npx claudepluginhub wan-huiyan/agent-squad-hrHow this skill is triggered — by the user, by Claude, or both
Slash command
/agent-squad-hr:flask-debug-cross-worktree-edit-staleThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You're running a Flask dev server (`python app.py` with `debug=True`,
Guides technical evaluation of code review feedback: read fully, restate for understanding, verify against codebase, respond with reasoning or pushback before implementing.
Share bugs, ideas, or general feedback.
You're running a Flask dev server (python app.py with debug=True,
or flask run --debug) from one git worktree. You're editing template
/ static / view files from a sibling worktree of the same repo,
because the branch you want to ship is checked out at the running
worktree and git checkout <branch> fails in your editing worktree.
You hit curl http://127.0.0.1:PORT/the-page after each edit, and the
response bytes don't change. You hypothesize Jinja bytecode cache,
Flask @_ttl_cache, browser caching, CDN, or stale __pycache__. You
try touch app.py to bust Flask's debug-reload, restart the process,
clear browser cache. Nothing fixes it.
Root cause: git worktrees have independent working trees on
disk. Each git worktree directory has its own copy of every tracked
file. Flask is reading from <worktree-A>/templates/page.html. Your
edits live in <worktree-B>/templates/page.html. They're physically
different files; the dev server has no way to see B's edits until A's
disk state changes.
Fire this skill when ALL of these are true:
git worktree list shows ≥2 worktrees of the same repo.lsof -i :PORT shows the
server process.lsof -p <PID> | grep cwd, or check the script
that launched it) is in worktree A.curl against the page returns byte-identical responses despite
confirmed-saved edits in worktree B.If condition 6 is FALSE (you created a new file), the new file simply doesn't exist in worktree A's tree. Same root cause, different shape: either commit + ff-merge into A's branch, or create the file in A.
# 1. Confirm cross-worktree mismatch
diff -q \
<(grep "your-recent-edit-marker" "<worktree-A>/path/to/file") \
<(grep "your-recent-edit-marker" "<worktree-B>/path/to/file")
# Files differ → confirmed.
# Files match → look elsewhere (TTL cache, CDN, etc.).
# 2. Confirm Flask is actually reading from A
lsof -p $(lsof -ti :PORT | head -1) | grep "cwd\|<worktree-A>"
# 3. Check git state of A
git -C "<worktree-A>" rev-parse HEAD
git -C "<worktree-A>" status -sb
# What branch is A on? Are there uncommitted changes that would conflict
# with merging your work in?
Three fixes, in order of safety + ease:
If A has a clean working tree and is checked out on a branch your work should land on (e.g., the wip branch), commit your edits in B and fast-forward-merge into A.
# In worktree B (where you're editing):
git -C "<worktree-B>" add <files>
git -C "<worktree-B>" commit -m "..."
# Then ff-merge into A's branch (run from B is fine; --ff-only refuses
# any non-trivial merge so it's safe):
git -C "<worktree-A>" merge --ff-only <your-branch>
Flask debug-reload watches the disk and picks up the changed files on next request. Done.
This is also the right move when the user wants the work merged into the wip branch anyway — preferable to polluting A with WIP commits.
Stop the dev server in A; start it in B from your branch directly. Costs you the convenience of running from the "blessed" worktree but eliminates the cross-worktree gap entirely.
# Stop A's server
lsof -ti :PORT | xargs kill -9
# Start in B
cd "<worktree-B>/<dashboard-dir>"
python3.11 app.py # or flask run --debug --port PORT
For a one-off probe (e.g., "does my CSS edit even render?"), copy the single file across:
cp "<worktree-B>/static/css/foo.css" "<worktree-A>/static/css/foo.css"
Don't use this as a workflow. It silently overwrites whatever's in A and creates divergence-from-git that's easy to forget. Only use to prove the diagnosis before committing to Fix 1 or Fix 2.
After applying Fix 1 or Fix 2:
curl -s "http://127.0.0.1:PORT/page" | grep "your-recent-edit-marker" | wc -l
# > 0 → fix worked, dev server now serves your edits
# 0 → still stale; check Flask log for reload errors, or escalate
# to the sister TTL-cache skill
| Symptom | Wrong skill | Right diagnosis |
|---|---|---|
touch app.py doesn't help | flask-debug-ttl-cache-stale-after-rebake (Flask TTL cache) | This skill — file-level divergence |
| Browser shows old version after server restart | Browser cache | This skill — server is reading A, browser is correctly receiving A's content |
| Restart Flask, still stale | Bytecode cache | This skill — file system, not Python state |
git status in B shows clean tree but page still old | Git confusion | This skill — A's tree is independent of B's |
The fast disambiguation: does worktree A's working tree have your edit? If no, it's this skill. If yes, look elsewhere.
Real session 2026-05-08 (this is where the skill was extracted):
/Users/.../the-project-repo) had
wip/monitor-noapp-cohort-broaden checked out, Flask running on
:8006 from there..claude/worktrees/monitor-prettify) was where
edits were being made.templates/roadmap.html, curl
returned byte-identical 27,028 bytes every time.grep "miscounted in training" <worktree-A>/...html → 0
hits. grep "miscounted in training" <worktree-B>/...html → 3
hits. Confirmed disk divergence.Result: page served correctly within ~1 second of the merge (Flask debug-reload caught the file change).
diff -q between worktree
paths confirms the hypothesis in <1 second. Don't hypothesize for
3 minutes like the original session did — diff -q first.flask-debug-ttl-cache-stale-after-rebake — genuine TTL-cache trap
in Flask, distinct mechanism (in-process cache, not filesystem
divergence). Use that skill when worktrees agree on disk but Flask
still serves old responses.gh-pr-merge-worktree-checkout-trap — git-side error that prevents
you from git checkout-ing the same branch in two worktrees.
Forces you into the cross-worktree edit pattern this skill diagnoses.deploy-from-stale-worktree-silent-rollback — production sibling
pattern: Cloud Run / Docker build context = local filesystem, so
deploying from worktree A bakes A's stale state into the image.
This skill's localhost-Flask analogue.worktree-index-corrupt-async-post-commit-hook — different worktree
trap: corrupt index after async post-commit hooks. Use that skill
when git status itself errors with unable to read <sha>.git-worktree(1): each worktree has its own
HEAD, index, and working tree but shares the object store.
https://git-scm.com/docs/git-worktreedebug=True reloads on file-watcher events; the watcher
scans the process's CWD tree, not "the repo".
https://flask.palletsprojects.com/en/latest/server/