Repository navigation
Conversation
Every jj widget called isInsideJjRepo, which spawned `jj root`, before running its own uncached `jj` command, with no timeout. With all eight jj widgets configured, a render spawned 8 `jj root` processes in a non-jj directory and 16 jj processes inside a jj repo (9x root, 3x diff --stat, ...), each read query also snapshotting the working copy. - isInsideJjRepo first walks up for a `.jj` directory (jj's own workspace discovery); without one it returns false without spawning. With one it still confirms via `jj root`, so a missing jj binary still renders "no jj". - runJjArgs goes through the same in-process + persistent TTL cache as git (runGitArgs is refactored into a shared runCachedCommand, git behaviour unchanged), stored under ~/.cache/ccstatusline/jj-cache and invalidated by the mtimes of .jj/repo/op_heads/heads (every operation, including a snapshot) and .jj/working_copy/checkout. Secondary workspaces follow the .jj/repo pointer file. Uses the gitCacheTtlSeconds setting. Commands that may snapshot (`jj diff`) are keyed to the repo state after they ran, so their own snapshot does not invalidate the entry they just wrote. - jj commands get the same 5 s timeout as git. - The change-id, description, bookmarks and workspace-name queries pass --ignore-working-copy: their output does not depend on unsnapshotted file edits. `jj diff --stat` keeps snapshotting. Spawns per render (8 jj widgets): non-jj cwd 8 -> 0; jj repo 16 -> 6 on an empty cache, 0 on a warm one; right after a file edit (cache past its TTL) 16 -> 7, then 2 on the next render, then 0. CPU (user+sys incl. children, median of 25 interleaved passes, load1 ~61 on 6 cores): non-jj 1597 -> 1245 ms (-22%), jj repo warm 2304 -> 1262 ms (-45%), cold 2280 -> 1769 ms (-22%). Output is byte-identical to main for the jj configs and for the existing git/default/heavy configs. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This was referenced Sep 30, 2026
whycantfindaname
pushed a commit
to whycantfindaname/ccstatusline
that referenced
this pull request
Oct 1, 2026
Merged from the jason/beta4-local-fixes Trellis build (compat-repair base): bounded stdin reads in shared hooks (sirmalloc#590), research dispatch may write the task research dir (sirmalloc#634), scoped archive commits (sirmalloc#622, sirmalloc#630), list filter traversal (sirmalloc#631), remove-subtask link check (sirmalloc#632), hooks.local.json ignore (sirmalloc#633).
This was referenced Oct 4, 2026
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This was referenced Oct 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
BLUF
jj rootand then its own uncachedjjcommand, with no timeout. With all 8 jj widgets configured, one render spawned 8 processes in a non-jj directory and 16 inside a jj repo..jjdirectory walk decides "not a jj repo" without spawning anything.--ignore-working-copy.main.Details
isInsideJjRepo). jj finds its workspace by walking up to the nearest.jjdirectory, so the widget now does the same walk first. If there is no.jj, it returnsfalsewithout spawning. If there is one, it still confirms withjj root. That keeps today'sno jjoutput when.jjexists butjjis not installed.runGitArgsis split into a sharedrunCachedCommandingit.ts. This is a pure move: the git exec options, memory keys, persistent file layout andgit.test.tsare all unchanged.runJjArgsuses the shared cache and stores its entries in~/.cache/ccstatusline/jj-cache/. Using a separate directory means colocated.git+.jjrepos cannot collide..jj/repo/op_heads/headsand.jj/working_copy/checkout. Every jj operation, including a working-copy snapshot, changes both, as checked with jj 0.45.1. Secondary workspaces follow the.jj/repopointer file.jj diff) take an optionalrefreshMetadatahook, so they are keyed to the repo state after they ran. Without it, the snapshot recorded byjj diffwould invalidate the entry it had just written. Read-only commands stay keyed to the state before they ran, so an operation that lands concurrently still causes a refresh. The git path does not use the hook.gitCacheTtlSecondssetting, default 5 s.diff --shortstat, a file edit shows up injj diff --statwithin one TTL. jj also inherits the setting's existing "0 = mtime only" meaning: with a TTL of 0, an edit shows up only after the next jj operation. This is the same trade-off git widgets already have for unstaged changes with a TTL of 0.--ignore-working-copy. This is added to the change-id, description, bookmarks (heads(::@ & bookmarks())) and workspace-name queries. None of their output depends on file edits that have not been snapshotted: I checked each query with and without the flag after editing files, including with a bookmark on@, and the outputs matched.jj diff --statstill snapshots, because the snapshot is the data it reports. One side effect: in a stale workspace, these four queries may now show the repo view instead of failing tono jj. I did not reproduce a stale workspace to confirm this..jjpath with zero spawns, discovery from a subdirectory, memory and persistent cache hits, cached failures, TTL expiry, invalidation on op-head and checkout changes, the secondary-workspace pointer, separate cache entries forallowEmpty, and post-run versus pre-run keying.main(red before) and pass with the change (green after)..jjworkspace with an isolated HOME, through a sharedjj-test-helpers.ts.Measurements
The setup: 8 jj widgets, jj 0.45.1,
node dist/ccstatusline.js, and an isolated HOME for each arm. CPU is user+sys including reaped children. I ran 25 interleaved round-robin passes. Load1 during the run was min 50.8, median 61.2, max 68.6 on 6 cores, so compare ratios rather than absolute times.node -e 0Spawns per render. The first three rows were counted with strace
-fexecve. The post-edit rows were counted with a loggingjjwrapper and a 60 s TTL, because strace under this load makes a single render take longer than the 5 s TTL.jj root×8)The stdout of the patched build is byte-identical to
mainfor the jj configs, in a jj repo and a non-jj directory, on cold and warm caches. It is also identical for the existinggit3,defaultandheavyconfigs.Checks
bun run lint(tsc + eslint--max-warnings=0): clean.bun run build: OK.bun test:jj.test.ts,git.test.tsand the 9Jj*widget files.fetchUsageData error handling(5 s timeouts), 15 in custom-command capture, and 15 in TUI menus and editors.main(35440e4) under the same load. They failed there too: 52 failures in the usage-fetch and TUI files, and 16 in custom-command capture.main. The patched build's re-keying change was re-checked after the benchmark run and still produced identical output.This PR touches
src/utils/git.ts(refactor only). As of opening, none of our other open PRs (including #624usage-fetch.tsand #625ansi.ts) touchgit.tsor the jj files.Overlap
src/utils/git.tsas well; the two branches conflict there. Whichever merges first, I will rebase the other.🤖 Generated with Claude Code