assist
-
v0.329 - Refining the comment gate and linking Jira
Most of today refined yesterday’s comment gate. The first rough edge was that the gate blocked all comment edits, including removing them — so I relaxed it to allow trimming, meaning I can still delete or shrink existing comments freely while adding new ones stays gated. The bigger change was hardening the escape hatch: the pin that authorises an allowed comment is now delivered out-of-band (
issuePin) rather than passed inline, so it can’t be forged in the same edit it’s meant to permit. With the gate carrying the policy properly, I dropped the old block-comments verify step, which had become redundant.The other feature ties backlog items to Jira. A new
assist backlog associate-jiracommand — and a/associate-jiraslash command in front of it — links a ticket to a backlog item: it validates the key shape, fetches the issue to confirm it actually exists, and stores the key, with--clearto remove the association. It’s the connective tissue I’d been missing between my own backlog and the tickets that drive some of the work.On the daemon side, I added a protocol-version handshake so the WSL and Windows daemons agree on a protocol version up front and a mismatch is caught cleanly at connect time rather than surfacing as confusing downstream failures. Three fixes rounded out the day: a
--oncesession re-watches its done signal after a restore so it still auto-dismisses, the daemon no longer replays its whole log buffer to a reconnecting browser (which had been dumping a wall of stale lines on every reconnect), and the web UI now shows unmerged files in the git status. -
v0.326 - Gating comments and unifying daemon logs
The theme I’m most pleased with today is enforcing the self-documenting code policy at the hook level rather than hoping I remember it. A new comment edit gate is a PreToolUse hook (
decideCommentGuard) that blocksEdit/Writefrom adding code comments, with an escape hatch: when a comment genuinely earns its place I can confirm it throughcodeCommentand have it allowed. I also hardened the block-comments verify gate so the check can’t be quietly sidestepped. Alongside it, the maintainability gate got a proper override: a special marker comment exempts a file that legitimately can’t hit the index, and theedit-hookprotects the marker itself — Edit/Write can’t add, change, or remove one — so the exemption is a deliberate act rather than something a refactor can flip. The complexity output now surfaces which files are running under an override.The other substantial piece was observability. Daemon logging is now unified into a single
assist.logstream instead of scattered outputs, daemon session operations are logged as they happen, and I dropped a redundant lifecycle logger that was just adding noise. To go with it, a newassist daemon draincommand clears all sessions from the local daemon for a clean slate, and a Windows-proxy create refusal now gets logged so I can see why a session didn’t start.The rest was hardening, much of it on the Windows path now that it carries real traffic. I capped the Windows connect probe at 2s and tightened the create timeout to 5s so a stuck host fails fast, surfaced a failed Windows create to the UI instead of leaving it silent, gated the Windows proxy off when assist is itself running on the Windows host, and stopped an unbounded
w-growth in Windows session ids. A few general fixes too: a hard cap on session fan-out so a runaway can’t spawn endlessly, the web server now binds before the daemon is ready so the page is reachable during startup, the session-card prompt is clamped to five lines, and the 7-day usage row gets a tinted background to set it apart. -
v0.318 - Phase names on cards and steadier status
A small, focused day. Session cards now show the current phase name, so at a glance I can tell whether a run is planning, implementing, or in review without opening it. Paired with that, a card flips to “running” as soon as the session starts thinking rather than waiting for visible output, so the status reflects what’s actually happening instead of lagging behind.
The remaining fixes tightened up two things from earlier in the week. I hardened the usage-peak reset detection so a reset is recognised reliably rather than occasionally being missed or double-counted, and I got the import sort to converge on oxfmt — the formatter and the linter had been disagreeing about import order, so a file could be “fixed” by one and immediately flagged by the other.
-
v0.317 - Scheduled backups and config-driven checks
Yesterday’s backup command grew up into a scheduling system.
assist backup schedule --every <duration>installs a marked crontab block that runsassist backupon a cadence —5mbecomes*/5 * * * *,6hbecomes0 */6 * * *— and re-running with a new duration replaces the block cleanly rather than piling up duplicates. Durations cron can’t represent evenly, like sub-minute or90m, are rejected up front instead of silently misbehaving. There’s aschedule statusto print the active cadence and aschedule removeto tear it down. The backup itself became self-discovering, so backup and restore locate the database on their own rather than needing the path spelled out, and the backups view now shows just the filename with the full path tucked into a tooltip.The verify pipeline got more configurable. A new
assist verify forbidden-stringscheck reads rules from config — each names a JSON file, a set of dot-paths to inspect, and adisallowedwildcard — and fails if any matching value turns up, which lets me catch things like a stray dev URL in a committed config without hard-coding the check. I also fixed the generation of the auto-fix verify scripts so they come out runnable.The rest was cleanup. I finished the move off Biome by removing the last lingering references now that oxc is doing the work, and fixed URL detection in the web terminal so a link that wraps across lines is still recognised as one clickable URL.
-
v0.312 - Capturing browser traffic to extract LinkedIn posts
The headline today is
netcap, a new way to pull my own LinkedIn posts out of the browser.assist netcapstarts a local receiver, paired with a raw Manifest V3 browser extension undernetcap-extension/that patchesfetchandXMLHttpRequestto capture every request/response and forward it to the receiver. Doing the forwarding from the extension’s background context sidesteps the page’s CSP, which is what killed an earlier console-paste approach — and reading the response across everyresponseTyperather than justresponseTextis what finally captured LinkedIn’s voyager GraphQL calls, which return JSON and expose noresponseText. Thenassist netcap extractparses the capture into structured posts — text, markdown with mentions linked, author, hashtags, related posts, and apostedAtdecoded from the activity id — reading both the SDUI responses rendered on first paint and the voyager responses loaded on scroll, deduped by activity urn. Follow-ups added article-card link extraction and a permalink back to each original post. There’s a fair bit of WSL-specific plumbing too, since the browser runs on the Windows host and can’t reach a WSLlocalhost: the receiver copies the extension to a Windows path and targets the WSL VM’s IP.The other feature was a backup command and a backups view in the dashboard, so the assist database can be snapshotted and browsed rather than relying on ad-hoc exports. I also continued polishing the usage history from earlier in the week: segments now order by
created_atwith the newest on top, and a usage reset keeps the pre-reset peak instead of dropping it.A cluster of smaller improvements rounded out the day.
assist verifytraded its--timerflag for a clearer--measure, formats in place as part of the run, and gives clearer messages when it denies something. The session terminal now renders with WebGL for smoother output, a commit off the expected branch raises a warning before it goes through, and I fixed sessions occasionally reading from the wrong transcript by binding each session to its own. -
v0.306 - Honest timers and a steadier proxy
A shorter, tidy-up day. The session timer now counts only running time rather than wall-clock elapsed, so a session that’s been sitting idle or waiting doesn’t inflate its own duration — the number finally reflects how long Claude actually worked. I also pulled the edit action out of the backlog web view; with the launch and refine flows doing the heavy lifting, inline editing in the browser was more clutter than help.
The rest was reliability. The WSL↔Windows proxy now sends a keepalive so the connection doesn’t quietly drop between the two hosts during a long-running session, the backlog web view polls for status so it stays current instead of going stale, and a restored update session now comes back with a clean done state instead of looking like it was still mid-run.
-
v0.305 - Hook-driven status and updating itself
The most impactful change was making session status hook-driven. Instead of inferring whether a session is working, waiting, or done from the terminal output, the daemon now takes its cues from Claude Code’s own hooks — a far more reliable signal touching 41 files across the daemon and UI. On top of that foundation, a session flips to “waiting” when you hit ESC, the running chip only animates while it’s actually running, and restored session cards keep their metadata instead of coming back blank. A local daemon also labels itself by platform now, which matters once Windows and WSL daemons sit side by side.
The other theme was letting assist update itself from the dashboard. There’s a new “Update assist” item in the web menu, and after an update the daemon restarts itself so you’re immediately running the new version. A couple of fixes made that path safe:
assist commit’s pull now autostashes so a dirty tree doesn’t block it, the startup pull is skipped entirely on a dirty worktree, and daemon phases stay resumable across the restart so an in-flight run isn’t lost.On the workflow side, a backlog run can now pause at the review phase rather than always pushing straight through, the review UI labels its toggle “Dismiss” so the action is clear, and a new
assist prs replycommand lets me respond to PR review threads from the CLI. I also added a/strip-commentscommand that enforces a self-documenting code style — declaring the comment policy inCLAUDE.mdand stripping comments that just restate the code. Rounding out the day: the terminal now honours Cmd+C/Cmd+V on macOS, and I continued the oxc migration by moving the project scaffolding over from Biome. -
v0.300 - Swapping Biome for oxc, and remembering usage
The headline change is a toolchain swap: I replaced Biome with oxc for linting and formatting. It touched 169 files — new
.oxlintrc.jsonand.oxfmtrc.jsonconfigs in place ofbiome.json, the verify pipeline rewired to call the new tools, and the editor set up to use them. The one piece Biome had that oxc didn’t was my filename-convention rule, so I ported it as a custom plugin (oxlint-rules/filenameConvention.ts) rather than lose it. It’s a big mechanical diff, but the result is a faster lint/format step that fits the rest of the Rust-based tooling I’ve been leaning on.The features were about making the dashboard remember things across restarts. Peak usage history now persists, so the rate-limit indicator can show how usage has trended rather than just the current snapshot, and the selected session persists and is shared — reload the page or reconnect and you land back on the session you were looking at, and that selection is shared across connected views. A small touch on top: the badge for the currently-open session now animates, so it’s obvious at a glance which card is live.
The rest was reliability, much of it on the Windows side now that sessions span both hosts. I bounded the Windows reconnect loop when there’s a version mismatch and bounded daemon spawn retries, so a wedged Windows host can’t spin forever; failed session restores now surface in the UI instead of failing silently; and forwarding a Windows session strips its host namespace so the path resolves cleanly on the WSL side. One backlog fix too: items without a plan now rewind correctly when sent back through review.
-
v0.297 - One database, and a lot of web polish
The structural change today was consolidating storage. What used to be the “backlog database” is now the “assist database” — a rename that touched 71 files but reflects a real shift: it’s no longer just backlog items. The first thing I moved into it was handovers, which had been living as loose files; storing them in the shared DB means session handovers sit alongside the backlog as proper records I can query and relate. Both changes were mostly mechanical, but they set up the database as the single home for assist’s state rather than a backlog-only store.
Most of the rest was web UI. I can now star backlog items and sessions — a
star/unstarpair on the CLI backed bysetStarred, plusStarActionandSessionStarButtonin the UI, with starred sessions sorting to the top (sortSessionsByStar). Launching a new session now pops a toast so there’s clear feedback that something started, and I fixed a nagging slowdown when switching tabs in the web view. I also removed the old web add-item flow, which the launch buttons had made redundant.On the review and PR side, I added a guard against wall-of-text PR bodies —
validatePrContentrejects bodies that are one giant unbroken paragraph, and the/prcommand now spells out the structure it expects — so PRs come out readable instead of as a wall I’d have to reformat by hand. The complexity report now tells you how to improve a low maintainability score, explicitly nudging toward extracting functions into smaller modules rather than gaming the metric by stripping whitespace or comments. Two smaller fixes rounded it out:assist reviewruns codex from the repo’s working directory so it sees the right files, the Seq query now applies its time window correctly, and a backlog run commits before signalling done on its final phase so nothing is left uncommitted. -
v0.291 - Driving Windows sessions from the WSL dashboard
Yesterday’s TCP proxy was the pipe; today was about actually driving Windows sessions through it from the WSL dashboard. I can now launch, write to, and control a Windows-host session from the same web UI as the local ones, with paths translated across the boundary (
windowsCwdToWslPath) so a session’s working directory makes sense on both sides. Two fixes kept that honest: the Windows daemon now auto-heals when it detects a version drift from the WSL side — spotting the mismatch (isWindowsCreate) and restarting itself so the two halves don’t silently run different code — and backlog origin resolution now handles the Windows case (getCurrentOrigin) so items get tagged to the right repo.The web nav got a few upgrades. Account rate limits are now surfaced right in the nav bar via a
RateLimitsIndicator, with the daemon relaying the limits through (relayRateLimits) and arateLimitLevelmapping them to a colour so I can see at a glance how much headroom is left before starting more work. I also added a hamburger menu that pulls the restart actions into the browser —HamburgerMenu,RestartConfirmDialogand apostRestartcall — so I can restart the daemon or web server without reaching for the Ctrl+R terminal menu. With those in place I dropped the now-redundant “next” button from the web view.Finally,
assist refactor rename filegot noticeably faster. I split the work into acomputeRenameRewritesplanning step and anapplyRenameexecution step, which trimmed the redundant passes that were making the rename feel sluggish on larger projects. -
v0.286 - Reaching Windows sessions and reshaping the PR commands
The bigger half of today went into reaching sessions that live on the Windows side of a WSL split. The daemon can now proxy Windows sessions over TCP — the WSL daemon talks to its Windows-host counterpart on a known port (
windowsDaemonPort) instead of assuming everything runs locally — and a companion change lets it discover those Windows-origin sessions so they show up in the dashboard alongside the Linux ones. It’s the groundwork for treating a two-host setup as a single pool of sessions rather than two disconnected worlds.The other big piece was reshaping the PR commands.
assist prs createbecameassist prs raise, and a newassist prs editlets me rewrite an existing PR’s title and body — both built on shared helpers (buildPrBody,parsePrBody,editPrBody) so raising and editing produce the same well-formed output. To make the wrapper stick, I added a built-incli-hookdeny forgh pr edit(mirroring the existinggh pr createdeny), so edits go through the validatedassistpath instead of rawgh. Alongside it, a new/prs-slackslash command posts a PR’s title and URL to a configured Slack channel — it reads the channel fromprs.slack, refuses to post if that’s unset, and confirms the exact message before sending via the MCP Slack tools.A few smaller things rounded out the day. I hardened the
cli-hookto fail closed when a deny is buried in a compound command rather than letting it slip through, fixed starting a session with an empty prompt, and refactored the news feeds out of their own standalone web app and into the sessions web UI and database — foldingfetchFeeds,parseFeed,groupByDateand friends undersessions/web/ui/newsso there’s one web server and one data store instead of two. -
v0.274 - Taming browser pop-ups under WSL
A short cleanup day, mostly about not having a browser tab fly open when I don’t want one. I added a
--no-openflag toassist sessions,assist sessions web, andassist backlog webso the dashboard can start without launching a browser — handy when a tab is already open or when I’m starting the server from a script. The web server’s own restart now passes--no-openwhen it re-execs itself, so hitting Ctrl+R no longer spawns a fresh tab on top of the one that’s already reconnecting. I also fixed how the browser gets opened under WSL, which wasn’t reliably handing off to the Windows host.The other fix closed out yesterday’s copy/paste work: a paste in the web terminal could register twice, so I tightened
handleClipboardKeyto only fire once. Finally, a small piece of plumbing — the/jiraslash command now fetches work items through the MCP Atlassian server (mcp__claude_ai_Atlassian__getJiraIssue) instead of shelling out toacli, with theassist jiraCLI commands kept around for direct human use. -
v0.281 - The web terminal grows up
Most of today went into making the web sessions terminal feel like a real terminal rather than a read-only window. The headline is a restart menu for the web server itself: hit
Ctrl+Rand a little in-terminal menu appears, built out of small composable pieces —parseMenuKey,nextIndex,renderRestartMenu,createMenuState,createKeyHandler— that lets me restart or re-exec the running server without dropping back to the shell. I started it on a different shortcut and then moved it toCtrl+Ronce it felt natural. Copy and paste landed too, with ahandleClipboardKeyhandler wiring the usual shortcuts through to the terminal, plus a follow-up fix to stop a paste registering twice. Smaller terminal polish rounded it out: reconnecting cleanly after a server restart instead of going dead, and closing an annoying gap between the terminal and the pane beside it.The other big piece was a read-only history transcript view. Closed sessions now render their Claude transcript directly in the dashboard — I parse the session
.jsonl(parseTranscript,findSessionJsonlPath,entryMessages,toolTarget) and render it through a newTranscriptPane/TranscriptRow, with derived history fields and chips (deriveHistoryFields,HistoryCardChips) summarising each run. It meant splitting the session area into a liveTerminalAreaand aTranscriptArea, and reworking the WebSocket plumbing (useSessionSocket,useWebSocket,WsDispatch) to feed both. So now I can scroll back through what a finished session actually did without resuming it.On the backlog side, run cards got an auto-advance toggle so a session can pause between phases instead of barrelling straight through —
consumePauseandsetAutoAdvancecarry the state through the daemon and intorunPhases. Backlog cards also grew a mark-done button for clearing items straight from the dashboard, and the repo selector now orders projects by recency so the one I touched last is at the top.The rest was housekeeping with teeth. I added a built-in
cli-hookdeny forgit commit, pointing it atassist commit "<message>"instead — moving the rule out ofsettings.jsonand into the hook’s ownfindBuiltinDenylist so it travels with the tool and gives a useful message rather than a bare denial. And I pinned overrides for a couple of vulnerable transitive dependencies to clear them out of the tree. -
v0.273 - Resilient sessions and dashboard polish
The daemon’s restart story got two solid fixes today. Restoring a session now resumes it through its backlog wrapper rather than a bare resume, so an interrupted run picks up where it left off instead of starting cold — I tore out the old
discoverClaudeSessionIdguesswork in favour of awatchClaudeSessionIdwatcher that reads the real session id as the process emits it. The companion fix makes a daemon restart resume the correct session, threading the Claude session id throughexecutePhaseandspawnClaudeso a restart can’t reattach to the wrong terminal.Most of the day went into the web dashboard. The toolbar now shows git status counts — ahead/behind and changed-file tallies parsed out of
git status(parseGitStatus,GitStatusCounts,useGitStatusCounts) — so you can see a repo’s state without leaving the page. Card selection got a proper going-over: it defaults to the top card on load, reselects the top card when one closes, and shows a loading state while a new card spins up, all reconciled throughreconcileActiveIdand auseActiveIdReconcilerhook. I also cached backlog items across view switches (backlogItemsCache,itemsEqual,revalidateBacklog) so flipping between views no longer refetches and flickers, narrowed the session sidebar to 25%, evened out the top-nav spacing, reordered the toolbar actions, and fixed the cursor on the active card.The web prompt input got friendlier too — it submits on Enter, and the prompt dropdowns now handle multiline content properly via a shared
FreePromptForm. The terminal renders clickable links. On the backlog side, a refine job can now be kicked off straight from a session card, auto-run reuses an existing draft or bug card instead of spawning a fresh one (reuseSessionForRun,respawnedIds), and refine cards auto-run correctly when marked done.Finally,
assist reviewgot more trustworthy: findings are now validated against the actual diff before they’re posted, so the reviewer can’t comment on lines that aren’t part of the change. I built out a diff line index (buildDiffLineIndex,annotateDiffWithLineNumbers) and apartitionFindingsByDiffsplit that keeps in-diff findings and warns about the rest. Reviews now persist under the home dir, and maintainability runs accept an--ignoreglob to skip paths. -
v0.264 - Session cards that show their work
The dashboard’s session cards were opaque — a terminal and not much else. Today I gave them chips and live activity. A card now shows what kind of session it is (
sessionType), a readable title derived from the command (sessionTitle), and a repo label, and it surfaces live activity emitted from the running process via a newwatchActivity/emitActivitypipe, so you can see a session doing something without scrolling its terminal. The backlog chip links straight to the item’s page, and the review-phase chip highlights when a backlog run reaches review, so the card tells you where in the pipeline the work is at a glance. I also added a per-card auto-run toggle, so you can decide whether a given session chains automatically or waits for you.The repo selector got a proper pass too. It’s keyboard-searchable now — type to filter, arrow keys to move, enter to pick — built out of
RepoFilterInput,RepoMenuList, and auseRepoKeyboardNavhook that replaced the old custom-path input. It also syncs to the active card: focus a session and the selector follows to that session’s repo (useSyncRepoToActiveCard+deriveActiveCwd), so the toolbar context tracks what you’re looking at. And next to the existing “open in VS Code” action, there’s now “open in GitHub”, which resolves the selected repo’s preferred remote and opens it in the browser.On the correctness side, I added a new verify check:
assist verify comment-policy. It flags comments added on changed lines — staged and unstaged — unless they carry a justification marker, which enforces the “only comment unintuitive complexity” rule I keep reminding myself of, and it’s wired into the verify run set filtered to TypeScript files. The daemon also got a run of reliability fixes from yesterday’s restart work: backlog sessions now restore through their wrapper rather than a bare resume, session activity persists across a restore, the session lock is released on dismiss and review-comments launches inacceptEditsmode. I also moved the backlog lock and activity files under~/.assistso they live in one place.The rest was performance and polish. The backlog list and web index were loading full items just to render summaries, so I split out lightweight summary loaders (
loadBacklogSummaries,loadItemSummaries) and lightened both the whole-list and index paths. The maintainability-index formula now prints on every maintainability run rather than just the one report, the free-prompt button got renamed to plain “prompt”, and I extractedisRunLinkinto its own file to tidy uptypes.ts. -
v0.258 - Launching backlog work straight from the web UI
Yesterday’s daemon work made sessions durable; today was about driving them from the web UI instead of dropping back to the terminal. The headline is a Play button on backlog items: from an item card or its detail panel I can now kick off
assist backlog runfor that item and have the session appear in the dashboard, wired up through a newuseSessionLaunchContext. The button only shows where it makes sense —canPlaygates it to todo items, including todo bugs, which I’d missed in the first pass. Alongside it, a Refine button on the item detail launches/refinefor that item directly, so the two things I most often want to do with a backlog item are one click away.I also widened how sessions get launched. The
draftandbugcommands now take an optional description —assist draft "add a foo"forwards as/draft add a foo— and the web UI’s mode buttons grew a free-prompt dropdown so you can type that prompt text in the browser before spawning. There’s a new “open in VS Code” action in the toolbar that opens the selected repo in an editor without leaving the dashboard. And on the CLI side, a purely numericassist run <n>that matches no configured command now falls through toassist backlog run <n>, forwarding the--writeflags — soassist run 42just runs backlog item 42.With more ways to start sessions, I cleaned up how they end and how the list behaves.
--oncesessions now auto-dismiss when their done signal arrives, via a smallshouldAutoDismissrule wired into the status-change path, so single-task sessions clear themselves out. The close button is always shown on a session card now rather than appearing conditionally, and the card’s elapsed timer freezes once the session is done instead of ticking forever. I also dropped the old sidebar run-command list — a chunk of UI (RunButtons,ModeSelector,NewSessionFormand friends) that the new launch flows made redundant.The backlog list itself got faster and more correct. Completed-item filtering moved server-side into
loadVisibleItemsso the browser isn’t pulling down done items just to hide them, and the web list now sorts newest-first. A clutch of fixes rounded it out: cancelling a stale backlog fetch when you switch projects so the previous repo’s items don’t flash in, refreshing session history on tab switch, and resuming a run correctly when its review phase had been rewound. Smaller still, the complexity report now prints the maintainability-index formula alongside the score so the number isn’t a black box. -
v0.245 - Sessions that survive a server restart
The big change today was pulling web sessions out of the web server and into a long-lived daemon. Until now, restarting
assist sessionskilled every running terminal with it — fine when the server never changed, painful the moment I was iterating on it. So I split the two: web sessions are now owned by a daemon process, and the server is a thin client that relays WebSocket traffic to it over a local IPC socket (a unix domain socket at~/.assist/daemon/daemon.sock, or a named pipe on Windows). Restart the server and the sessions keep running with their scrollback intact. The daemon logs to its own file, auto-exits once no sessions remain and no client has connected for 60 seconds, and gets respawned on demand by the server when it’s needed again.This was a large move —
SessionManager,createSession,wirePtyEvents,writeToSessionand the rest of the session core all migrated fromweb/intodaemon/, with new pieces for connecting (connectToDaemon,handleConnection,greetClient), persistence (loadPersistedSessions,restoreSession), and lifecycle (runDaemon,restartDaemon,shutdownSessions). It comes with a small command surface:assist daemon run,status,stop, andrestart. The mental model I landed on: web server changes only needassist sessionsrestarted and sessions survive, while daemon or session-core changes needassist daemon restartto load the new code — which kills the PTYs but auto-respawns claude sessions viaclaude --resume, with run sessions reappearing as not-restored tiles you can retry.Rearchitecture like that always shakes out races.
assist daemon restartand concurrentassist sessionsinvocations could both try to spawn a daemon and orphan one of them, so I added a proper bring-up path — a PID-file watchdog (startPidFileWatchdog), socket-theft detection (reportStolenSocket), and anonListeninghandshake — so only one daemon ever owns the socket and the loser steps aside cleanly. I also fixed a PTY spawn failure that was crashing the whole server: the spawn helper now gets its executable bit ensured up front, and a spawn error surfaces as an error snackbar in the UI over the WebSocket instead of taking the process down with it.The other feature was
--once. The launcher commands —assist next,draft,bug,refine— normally chain: finish one item and they prompt for the next. With--oncethey exit after the first completed run instead, which is what I want when I’m spawning a session for a single task and don’t want it sitting around waiting. That’s backed by a newassist signal donemarker that--oncesessions watch for and plain sessions ignore.A few smaller things rounded out the day.
assist reviewnow ensures.assist/reviewsis gitignored before it writes there, so review artifacts don’t leak into commits. The web UI got a pointer cursor on buttons and links (a small thing that bugged me every time), and backlog items that are in progress now get a highlight and anInProgressChipso the active work stands out in the list. And I tightened the/draftand/refineprompts to enforce vertical slicing in the plans they produce. -
v0.243 - Review by PR number, and an org leaderboard
Most of today was on
assist review, which orchestrates two LLM reviewers (Claude and Codex), synthesises their findings, and posts them as pending line comments. The breaking change:assist review <number>used to mean SHA mode — diff a single commit and write the review files to disk without touching GitHub. I almost never used it, and the surface cost was real: a whole second pipeline (reviewSha,gatherShaContext,buildShaRequest) shadowing the main one. So I ripped SHA mode out and repurposed the positional argument:assist review <number>now runsgh pr checkout <number>first and then reviews that branch exactly as it would the current one. If the checkout fails — dirty tree, unknown number — gh’s error surfaces and the review aborts. One pipeline now, and reviewing someone else’s PR is a single command.Two more review changes. I hit a wall reviewing a large PR: GitHub rejects
gh pr diffwith a 406too_largeonce a PR crosses 300 files.fetchPrDiffnow catches that specific error and falls back to fetching the base and head SHAs and running a localgit diff base...head, so big PRs review instead of erroring out. And I addedassist review --backlog, which after synthesis spawns Claude to file every finding as a single bug backlog item — one phase per finding, each named after the finding with its location, impact, and recommendation captured as tasks. It’s the natural bridge from “here are the problems” to “here’s the queue of work,” without me copying findings across by hand.Away from review,
assist github commits <org>is a new org-wide commit leaderboard: it walks every repo in an organisation over a window (default 30 days,--sinceto override), filters to repos with activity, and reports commit counts per repo and aggregated per committer, with--top <n>and--json. The shared GraphQL helper moved fromprs/up toshared/since both surfaces use it now. Finally, a chunky web UI refactor: the repo selector is now shared between the backlog and sessions toolbars via auseRepoSelectionContext, instead of each view carrying its own filter row — one place to pick which repo you’re looking at, consistent across tabs. -
v0.239 - A PR review gate and some shortcuts
The headline today is a review gate around PR creation. I kept ending up with PRs whose titles or bodies leaked a stray “Claude” reference, and I wanted a hard stop rather than a habit. So
assist prs create --title <title> --body <body>is now the sanctioned path: it runsvalidatePrContent, which refuses any title or body mentioning Claude, then delegates togh pr createwith the assembled args. To make sure the wrapper actually gets used, the cli hook gained afindBuiltinDenylayer —gh pr createis now denied regardless of settings or per-project config, with a message redirecting toassist prs create. The/prcommand instructions were updated to match, and they now require the full proposed title and body to be surfaced throughAskUserQuestion— with the text in the approve option’spreviewfield — before anything runs, in every permission mode including bypass. The point is that I see exactly what’s about to be published, every time.A few shortcuts to cut keystrokes. There’s a top-level
list(aliasedls) that forwards straight tobacklog listwith all its filter flags, so I can typeassist lsfrom anywhere.assist review-comments [number]checks out the given PR (when supplied) and spawns Claude on/review-commentswith edits enabled — it pulls the launcher logic out ofindex.ts, which was getting crowded. Andbacklog nextnow accepts an optional start id, so I can point it at a specific item to begin the run loop from instead of always letting it pick.Two more, both about reconciling state.
assist backlog move-repo <old> [new]retags every item from one origin to another — the fix for items left stranded under a stale origin after a repository rename. It infers the destination from the current repo’s remote when omitted, accepts a bare repo name for the old origin when it unambiguously matches one stored origin, and confirms the count before updating. Finally, a refactor-extract bug: when a file had a leadingbiome-ignoresuppression comment but no imports yet,ts-morphinserted the new import at index 0 — above the suppression — detaching it from the top of the file.addImportPreservingSuppressionsnow counts the leading suppression comments and inserts the import below them. -
v0.234 - A day of backlog polish
A grab-bag day, all of it sanding down rough edges on the backlog flow I’ve been living in. The command ergonomics got the most attention.
backlog runandbacklog nextnow default to auto permission mode — running an item almost always means I want Claude to edit, so-w/--writebecame the default and a--no-writeopt-out was added rather than forcing the flag every time. I added arefinealias on thebacklogcommand, and while I was inregisterBacklogI pulled the long list ofregisterX(cmd)calls into aregistrarsarray that gets iterated, so adding a command is one line instead of two. The other ergonomic win waspullIfConfigured— whencommit.pullis set, backlog commands now rungit pull --ff-onlyfirst and abort on failure, so I stop running an item against a stale tree.The data layer got a targeted-writes pass. After the Drizzle move, per-item commands were still loading the entire backlog into memory, mutating one item, and saving everything back. I replaced
loadAndFindItemwithfindOneItem, which does a single targeted read by id and hands back the resolved orm so the caller can follow up with a targeted write. The whole-backlogsaveBacklogis still there for import/restore tooling that genuinely needs to reconcile everything, but the common path no longer round-trips the world to touch one row.The web UI got some polish too: a loading spinner on the backlog list while a search is in flight (the body moved into its own
ListBodycomponent), backlog chips now derive their colours from the active theme’s contrast instead of hard-coded values, and a fix so the backlog tab navigates back to the list rather than getting stuck on whatever sub-view it last showed. Last, a fix to a phase-rewind edge case: if Claude appended a phase while sitting in the review slot — all authored phases done — the usual index shift keptcurrentPhasepointing at review, so the new phase got skipped on restart.insertPhaseAtnow detects the review slot and rewindscurrentPhaseto the inserted phase so it actually runs before review. -
v0.229 - Backlog moves to Drizzle
Three changes today, all on the backlog data layer that moved to Postgres a couple of days ago. The first was
assist backlog export/import. Now that everything lives in one shared Postgres database rather than per-repo SQLite files, I wanted a way to snapshot the whole thing and move it between machines. Both commands lean on Postgres’COPYfor speed:exportstreams each table out viaCOPY ... TO STDOUTand frames it into a single self-contained file, andimportreads it back viaCOPY ... FROM STDIN. The dump format is a JSON header —{ format, version, tables }— followed by per-table sections prefixed with@table <name> <byteLength>. The byte-length framing keeps each table’s COPY payload verbatim regardless of its contents, so the round-trip is faithful.importvalidates the header against the expected schema and confirms before replacing existing data.The bigger change was migrating the whole data layer from hand-written
pgqueries to Drizzle. The oldBacklogDbinterface wrapped raw SQL strings with?placeholders; every loader and saver now builds queries through Drizzle’s query builder against a typedbacklogSchema. The win that motivated it was batching —loadAllItemsused to loop over every item firing separate queries for comments, links, and plan, which is fine for a handful of items but scales badly. With Drizzle’s relational queries those collapse into far fewer round-trips. The migration touched a lot of files (BacklogDb→BacklogOrm,getBacklogDb→getBacklogOrm, and most of the backlog command surface) but the shape stayed the same. A nice side effect: tests now run against PGlite — real Postgres compiled to WASM — instead of mocking out SQLite, so the SQL is validated against the production dialect without needing an external database. The Drizzle client is structurally identical across the node-postgres and PGlite drivers, so the test client is just cast to the production type.The last one was cosmetic. The backlog list shows which repo each item came from, and after the Postgres move that label was the full normalized origin (
github.com/org/repo). I trimmed it down —originDisplayLabelsresolves the shortest unambiguous name across the whole list, so a remote shows just its bare repo name (repo) unless two listed remotes share that name, in which case both fall back to the disambiguatingorg/repoform. Local repos always show their final path segment. The decision is made across the full set being displayed, so a name only gets shortened when it’s genuinely unique in that view. -
v0.226.1 - Granular backlog edits and mid-run phases
Three changes today, all small, all driven by friction I hit in the past week. First: granular backlog list edits.
assist backlog updatecould only replace the entire acceptance criteria or task list — which meant fixing a typo in AC #2 of a 6-item list required passing all six in. Added--add-ac,--edit-ac <n>,--remove-ac <n>and matching--add-task/--edit-task/--remove-task/--add-check/--edit-check/--remove-checkfor phase tasks and manual checks. Indexing is 1-based to match how the items are displayed. The all-replacingupdategot renamed toupdate-fieldso the command surface stays explicit about whether you’re replacing or mutating.Second: a bug I hit twice while running the new backlog flow.
assist backlog runwas capturing the plan once viaprepareRunand looping over that frozen snapshot, so if Claude appended a phase during the last phase (which is a normal thing to do — discovering work that needs splitting out), the new phase got skipped in favour of jumping straight to the review phase. Fixed by re-resolving the plan from the DB after eachexecutePhaseviareloadPlan, so newly-added trailing phases extend the loop instead of being dropped. PulledrunPhasesandrunReviewout into their own files in the process —run.tsis now a thin orchestrator.Third: a cli-hook tweak. I’d been piping
assist complexitythroughgrep/sedto narrow its output, which triggers permission prompts because the compound command isn’t on any allow list. Butassist complexityalready hasmaintainability/cyclomatic/halsteadsub-commands that produce focused output without any post-processing. The hook now detects piped/chainedassist complexityinvocations and denies them with a specific reason pointing at the sub-commands, instead of falling through to a generic prompt. The general shape is reusable —SUBCOMMAND_READSis a list, more entries can be added when another command grows the same pattern. -
v0.224 - Backlog moves to Postgres
Cut the backlog over from per-repo SQLite +
backlog.jsonlfiles to a global Postgres database. The motivation was the web UI bug from a few days back (openDbcaching a single_dbglobally) plus the wider friction of every project carrying its own.assist/backlog.db: switching repos in the web UI cross-read each other’s data, and there was no good way to look at “everything I’m working on” across projects. Postgres is overkill for the storage volume, but the connection is shared across every assist invocation in any repo, andgetCurrentOrigintags rows with the originating remote so per-repo queries still work.The bulk of the change is a refactor — every loader/saver that used to read JSONL or hit
better-sqlite3now goes through aBacklogDbinterface backed by apgpool. Some_testfiles lost ~30% of their lines because the tests no longer need to set up a fresh on-disk SQLite per run; they go throughcreateTestDband reuse the schema.migrateLocalBacklogruns once per project on first invocation: backs up the existing.assist/backlog.dbandbacklog.jsonl, parses the JSONL, remaps item IDs so they don’t collide with already-migrated rows from other repos, and imports. After verifying the migration the jsonl file is gone from the tree.One catch found right after rollout — backlog commands were hanging after printing their output. The
pgpool’s idle connections and timers keep the Node event loop alive, so the process never exits cleanly. Fixed by switching the CLI toparseAsync().finally(closeBacklogDb)so the pool drains on exit. Stuff that’s harder to fix once it bites: anything that holds the event loop open. -
v0.223 - Gate backlog runs on pending handover
After yesterday’s handover work, the obvious failure mode was: leave a
.assist/HANDOVER.mdfrom the last session sitting on disk, kick offassist backlog nextin a new session, and have it cheerfully start work without ever reading the handover. Sobacklog runandbacklog nextnow check for.assist/HANDOVER.mdup front viablockedByHandoverand refuse to proceed if one exists, telling the user to either start a fresh session (which surfaces the file via the SessionStart hook) orassist handover archiveto set it aside intentionally.Also threw out the prior
/recallplumbing —findRecentSessionJsonl,isSdkCliOnly,encodeCwdForProjects, and most ofload.ts. The SessionStart hook now surfaces the handover directly, so the session-walking machinery underneath/recallis dead code.handover loadis now a thin wrapper around reading the file. -
v0.221 - handover and recall commands
Added
/handoverand/recallClaude Code skills and the supportingassist handovermachinery for cross-session continuity./handoverwrites a structured.assist/HANDOVER.mdwith the sections I always forget to include myself — Current Task, Just Done, Next Steps, Key Files, Open Decisions, Watch Out For, Don’t Do — and archives any prior handover to.assist/handovers/archive/<iso-ts>.mdfirst so re-running it can’t silently clobber notes. The file is gitignored./recallis the read side: it locates the most recent prior session JSONL under~/.claude/projects/<encoded-cwd>/, skips the current session and any sdk-cli-only transcripts (because those aren’t real interactive sessions worth recalling), then emits a terse# Recallblock summarising what was being worked on so a fresh session can pick up.A bunch of the implementation work is in figuring out which session JSONL to actually load: encoding the cwd to the projects-dir naming scheme (
/→-), walking files newest-first by mtime, and the sdk-cli filter that classifies a transcript by inspectingentrypointon everytype:"user"entry. PullediterateUserEntriesandparseUserLineout of the existing summarise code so handover and the session summary path share the same JSONL parsing. -
v0.220.2 - assist review surfaces reviewer failure details
When a reviewer in
assist reviewfailed — codex exiting non-zero, claude bailing early — the user got back a bare “codex CLI exited with code 1” with no context, which is useless for debugging. AddedformatReviewerFailurethat builds a structured diagnostic: exit code, elapsed time, trimmed stderr, and a “fast fail” hint when the process died in under a second (because that almost always means not-installed, not-authenticated, or misconfigured, and the suggested next steps —--versionthenlogin— short-circuit the usual flailing). If stderr is empty it falls back to the tail of stdout so the user has something to read.Bunch of small refactor work alongside it to thread stdout/elapsed time through the failure path:
attachStdoutTailkeeps a bounded tail of each reviewer’s stdout,finaliseReviewerRunandhandleChildClosecarry the new fields, andprintReviewerFailuresruns the formatter for any non-zero exit. Tests cover both the fast-fail hint and the stdout-fallback branch. -
v0.220.1 - assist review handles missing codex CLI
assist reviewwas crashing with an unhandledENOENTwhen thecodexCLI wasn’t on PATH — not a friendly experience for a tool that’s only useful if both reviewers can be spawned. AddedensureCodexAvailablethat checks forcodex, and on miss prompts the user tonpm install -g @openai/codex. If they decline (or the install fails), the run continues with the Claude reviewer alone instead of falling over. The codex result slot is populated with a “skipped” stub so the synthesis stage doesn’t need a special case for “one reviewer was absent”.While I was in there I broke the reviewer plumbing into smaller pieces —
planCodexReviewer,resolveClaude/resolveCodex,runAndSynthesise,waitForChildExit,handleSpawnError— so the run-streaming code stops being one giant function.runReviewers.tsshrank by about 40 lines and the spawn-error path is now in one place instead of three. -
v0.220 - SHA mode and codex guidelines for assist review
Two refinements on top of
assist reviewfrom earlier in the week. First,assist reviewnow accepts an optional SHA argument and reviewssha^..shainstead of the current PR. When a SHA is passed there’s no PR lookup and no GitHub posting — output is just the local review folder. Useful for sanity-checking a single landed commit or a WIP before opening a PR. The PR and SHA paths share arunReviewPipelinebut split context gathering (gatherShaContextvs the PR-based one) and request building so neither path has to special-case the other.Second, I folded a much stronger set of reviewer guidelines into the prompt that goes to both Claude and Codex. The old prompt asked for findings with severity/impact/recommendation but didn’t say much about when something is worth flagging — so reviewers were raising pre-existing issues, vague tangles, and style nits dressed up as bugs. The new rubric is explicit: must be discrete and actionable, introduced by this change, not pre-existing, named to a concrete code path, and clearly not intentional. There’s also direct guidance on tone (matter-of-fact, no flattery, no padding) and an instruction to return zero findings when nothing clears the bar rather than padding to look thorough.
Smaller doc tweak:
claude/CLAUDE.mdnow points Claude at the Atlassian MCP server for Jira context instead of describingassist jirashell calls. -
v0.217 - Backlog shortcuts, skott, and repo selector
A grab-bag of small improvements to the daily-driver flow, mostly around the backlog.
/next [id]is now a shortcut to run a specific backlog item by id instead of having the orchestrator pick — handy when I already know which item I want to work on next.assist backlog stoplands as the inverse ofstart: reverts an in-progress item back totodoso I can park work without it sitting in a half-state./draftwas also fetched a lot of codebase context up front before even asking what the user wanted, so it now defers those reads until after the description is captured.On the tooling side I replaced
madgewithskottfor the circular-dependency check inassist verify.madgewas dragging in ~1.4MB of transitive deps for what should be a fast static check, andskottdoes the same job with a much smaller surface and faster startup, so the verify wall time drops on every run. Also fixedrefactor rename symbolin monorepos — it was loading the wrongtsconfig.jsonwhen a project had multiple, so the rename only covered part of the source tree.findTsConfiggot pulled out to share the walking logic between extract and rename.In progress on a branch: moving the repo selector from inside the sessions view up into the top toolbar so it’s shared across sessions and backlog. The wip commit pulls the selection state into a
RepoSelectionProvidercontext, dropsRepoFilterRow, and rewires the backlog web view to read the active repo from the same source. Not landed yet. -
v0.215 - assist review orchestrates Claude and Codex
Spent the day building
assist review, a command that runs Claude Code and Codex CLI as two independent reviewers over the current PR’s diff and synthesises their findings into a single set of line-level pending comments. The shape is: kick off both children concurrently, stream their events throughparseClaudeEvent/parseCodexEventparsers, collect findings into a structured shape (parseFindings), then hand the merged set to a synthesis pass that dedupes and severity-rates beforepostFindingsposts them viaghand optionally submits the review. Findings that couldn’t be located in the diff are warned about rather than dropped silently.Once the bones were in place the iteration loop got fast. The reviewers were initially diffing against the local base branch and missing PR-level context, so they now feed off
gh pr diffand prior PR comments viafetchExistingComments+formatPriorComments— so a second review run doesn’t re-raise points the original reviewer already wrote. The streaming UI was a wall of log lines, so it’s now a set of stacked ora spinners that show each reviewer’s progress in place. And--refineand--applyflags landed on top:--refinedrops into an interactive synthesis loop where I can tweak the merged findings before posting, and--applyspawns a Claude session pointed at the resulting findings so the fixes can be made and pushed in the same flow. The severity rubric in the synthesis prompt also got reworked after seeing it call too many things “high”. -
v0.211 - /verify-new slash command
Added a
/verify-newClaude Code slash command that walks through registering a newverify:*run entry. The interesting step is the hunt-for-quietness one: becauseassist verifyruns everyverify:*entry in parallel and only surfaces output for failures, a noisy success drowns out the actual signal. The skill explicitly tells Claude to read the wrapped tool’s--help, look for--silent,--quiet,--reporter=dot-style options, and apply them before adding the entry, then verify with a real run. That’s the part I always forget to do manually. -
v0.210 - Forward comments command and subdir fixes
A few unrelated improvements today, all driven by friction I was hitting in real reviews. The headline is a new
/forward-commentsClaude Code slash command: paste in a coarse review someone gave outside GitHub (Slack message, in-person notes), pass the reviewer’s handle, and it splits the prose into atomic concerns and posts each one as a separate line-level review comment on the current branch’s PR, prefixed withvia @handle. Framing prose and transitions get dropped — only actionable points become comments.Two fixes alongside it.
assist backlogwas bailing when run from a subdirectory becauseloadConfigonly checked cwd; it now walks up looking for.claude/assist.ymlorassist.ymland resolves the project root from wherever it finds the config. And theprscommand’sghcalls were occasionally hittingupstreaminstead oforiginon forks, which surfaced wrong PR data — added agetPreferredRemoteRepohelper that prefersoriginwhenever it exists, falling back to whatever single remote is configured. -
v0.209 - assist sql for MSSQL
Added an
assist sqlcommand for running queries against MSSQL — the missing piece for being able to spelunk through a database without dropping into SSMS or another GUI. Connections are configured up-front (sql set-connection) and stored alongside the existing seq connections, with named selection across calls.sql queryrunsSELECTstatements and prints the result as a table;sql mutaterunsINSERT/UPDATE/DELETE/MERGEstatements and refuses anything that doesn’t look like a mutation via anisMutationcheck, so a careless paste of a wideSELECTcan’t accidentally tear through a table. Both share the connection resolution, auth, and pool plumbing undersrc/commands/sql/.Also slipped in a small fix:
assist run add verify:*was creating aclaude/commands/<name>.mdslash command for every verify run, which doesn’t make sense — verify scripts get invoked byassist verify, not as individual user commands. The slash-command file is now skipped when the run name starts withverify:. -
v0.207 - assist mermaid export
Added
assist mermaid exportto render the fenced mermaid blocks inside a markdown file out to SVGs. With a file argument it pulls every```mermaidblock and writes them next to each other as<stem>-<index>.svg; with no argument it scans*.mdin the current directory.--out <dir>overrides the destination and--index <n>renders just the nth block, which is handy when iterating on a single diagram. The actual rendering goes through Kroki — POST the source, get back SVG — and the endpoint is configurable viamermaid.krokiUrlfor anyone running a self-hosted instance. -
v0.206.2 - Resolve Roam port file by channel
The Claude icon stopped showing up in Roam when
show-claude-code-iconwas enabled. Root cause was that Roam now writes channel-specific port files (roam-local-api-beta.port, etc.), and assist was still reading the legacyroam-local-api.port— which on my machine was a stale file from a previous stable install pointing at a dead port. UpdatedpostRoamActivityto globroam-local-api*.portunder%APPDATA%/Roamand pick the most recently modified file. AcurlPOST against the freshly resolved beta port comes back with{ok:true}and the icon is back. -
v0.206.1 - cli-hook approves redirects to OS temp
The cli-hook approval check refused any command containing
>or>>, which made things likeaz containerapp logs show ... > $TMPDIR/ca-logs3.jsonunapprovable — even though redirecting log output into a temp file is a perfectly safe pattern. Loosened the parser to strip a redirect when its target sits under the OS temp directory and otherwise return a specificredirect target '...' is outside the OS temp directoryerror instead of the generic “unable to parse”. The temp-path matcher handles both POSIX and Windows path styles (case-insensitive, forward or back slashes, drive-letter required) so the check is consistent across machines.While in there I changed
splitCompoundto return a result object ({ ok, parts | error }) instead ofstring[] | undefined, which lets the hook surface the actual reason a command was rejected rather than just saying it couldn’t parse. PulledgroupByOperator,consumeRedirect, andisRedirectTargetAllowedout into their own files so the parser stays under control as more cases get added. -
v0.206 - verify init defaults to assist.yml
assist verify initused to look at the existing setup and write verify scripts to wherever it already had hooks —package.jsonscripts ifpackage.jsonhad them,assist.ymlrun entries otherwise. That heuristic was wrong:assist.ymlis the canonical place for these commands now, so the default should always beassist.yml. Reversed it soverify initwrites toassist.ymlunconditionally, with a--package-jsonopt-out for projects that genuinely want the npm script form. -
v0.205.1 - Windows fix for assist devlog next
assist devlog nextwas crashing on Windows with'%h' is not recognized as an internal or external command. The cause was threegit log --pretty=format:'%ad|%h|%s'calls running viaexecSync—cmd.exedoesn’t strip single quotes the way bash does, so%hgot expanded as an empty env var and the rest of the format string was parsed as a command. Switched all three call sites (devlog list,devlog next,getLastVersionInfo) fromexecSyncwith a shell string toexecFileSyncwith an argv array, which sidesteps the shell entirely and works the same way on every platform. -
v0.205 - Spike — auto-generating skills from session data
Spent the day digging into how skills could be extracted automatically from Claude Code session transcripts instead of being hand-written. Sessions live as JSONL files under
~/.claude/projects/<sanitized-path>/<uuid>.jsonl— user and assistant entries with tool calls inline — and even with the tool-call noise stripped, each one only weighs in at a couple of thousand tokens of text. A whole project’s worth of sessions fits comfortably in context, which changes what’s feasible.I cloned
AutoSkilland walked through its three-stage pipeline (plan → expand → compile) and the prompt engineering behind it. The extraction philosophy is the interesting part: only lift skills from concrete, reusable user requirements, treat assistant replies as untrusted evidence, and lean toward missing a one-off over saving a generic task. Worth porting. The runtime itself is not — it requires an external LLM API key, and its filesystem-backed storage plus embedding dedupe is overkill at the scale of <100 skill files. The recommendation written up in.assist/spike-75.mdis to port the prompts and use Claude Code itself as the extraction LLM via anassist skill extractCLI command plus a/skill-extractskill that runs the approval flow. Zero external dependencies, and the cost is already inside the session. -
v0.205 - Unified web UI, assist modes, global deny
The two separate web UIs — sessions dashboard and backlog view — are now one MUI app with shared navigation. Having them as siblings always felt wrong given they read from the same project state, and merging them opens the door to cross-linking (e.g. jumping from a backlog item to the session that worked on it). The sessions tab also got mode buttons for picking between assist behaviours directly from the UI, and the prompt input now stays visible whether a session is running or idle instead of appearing and vanishing.
On the CLI, I added
roamactivity commands targeting a Codex flow, and global deny config support so deny rules can live in a user-level config and apply across every project instead of being repeated in eachassist.yml. -
v0.200 - Web UI polish, session summarise, prompt analyzer
The web dashboard got most of the attention today. I added
runcommand execution and a retry button for failed run sessions, so I can trigger and re-trigger commands from the browser instead of dropping back to the terminal. Phase rewind landed in the backlog web view too, mirroring the CLI command. I also madeassistwith no arguments default to opening the sessions dashboard, and added hover states to card buttons so it’s clearer what’s clickable.On the CLI side, I built a prompt frequency analyzer for spotting which prompts I type most often — useful for figuring out what to turn into skills or aliases — and a
session summarisecommand for capturing what a session accomplished. Suffix matching forassist runnow resolves partial names and shows candidates on ambiguity.A cluster of fixes:
cli-hookcheck was failing to parse PowerShell$nullredirects, the caveman skill prefix needed removing after a rename,seqquery timestamp filtering was silently dropping filters and lacked relative-time support, and cross-platform browser-open was misbehaving when the dashboard tried to pop the session URL. -
v0.194 - Repo selector on new session form
The new-session form in the web dashboard picked up a repo selector, so I can kick off a session against any tracked project without typing the path or remembering which directory I last started Claude in. I also softened a help-discovery hint in the backlog output that was over-confident about suggesting commands when the agent couldn’t find what it needed.
-
v0.193 - Web sessions dashboard with history and resume
I built a web dashboard for Claude Code sessions — a browser-based harness for seeing what’s running, what’s queued, and what finished. The first cut landed with a sessions list, and the same day I added history browsing and resume so I can pick up a prior session from where it left off instead of starting fresh every time.
Small fix earlier: the caveman skill invocation needed to use its fully qualified name to resolve correctly when spawned from a plugin-namespaced context.
-
v0.191 - Caveman prompts and cd approval
Two features and a cluster of small fixes. The
cli-hookallow-list now approvescdinto any directory that Read is already allowed to touch — previouslycdwas gated separately and kept prompting even though the target was clearly in-scope. I also added a “caveman” config that prefixes every spawned Claude prompt with a short directive to keep replies terse. It’s silly, it works, and it saves me from typing “no yapping” into every session.Fixes:
ensureGitignorewas duplicating entries on CRLF files because the line-split didn’t normalise newlines,reindexPhasesnow defers FK checks soremove-phasedoesn’t trip over the constraint mid-reindex,backlog add --descwas storing literal\nstrings instead of newlines, and thecli-hookcheck was rejecting shell builtinstrueandfalseas unknown commands. -
v0.189 - Linked run configs and gitignore cleanup
Two features today. I can now pull in
runconfigs from externalassist.ymlfiles — linking makes shared commands reusable across projects without copy-pasting every time I spin up a new repo. I also simplified.gitignoreentries to a single.assist*pattern instead of listing each generated file individually, which is easier to reason about and one less thing to update when assist adds a new signal or lock file.A quick follow-up fix: linked run commands using
bash -cwith chained commands were hanging on Windows because the bash path and run prefix weren’t being resolved correctly. Both are now resolved before the command is spawned. -
v0.187 - Position option for add-phase
A tiny day.
backlog add-phasegained a--positionoption so I can insert a phase at a specific index instead of always appending. Useful when I realise mid-flow that a plan needs an extra step somewhere in the middle, rather than having to rewind and rebuild. -
v0.186 - Backlog refinements and run command expansion
Big day — eleven minor releases. The backlog picked up the most surface area: a
refinecommand for iterating on item details through conversation, arewind-phasefor walking items back when a phase is wrong, adelete-commentfor pruning noise, and an auto-commit config toggle for people who don’t want everybacklog addgenerating a commit. I also made phase numbering 1-based end-to-end so the CLI and the display finally agree, after a brief run wherephase 0in commands showed asphase 1on screen.The
runcommand grew aremovesubcommand and a--cwdoption onrun add, andrun helpnow lists the commands I’ve actually configured rather than just the built-in flags. I added anactivitycommand with a weekly chart to get a feel for where I’ve been spending time, and followed up the same day with a date range in the chart and a label fix after I noticed it said “per week” when it was really per day. Rounding out the day: a/add-commandslash command for adding new run commands conversationally, backtick formatting in PR bodies so code symbols render properly, a fix for thecli-hookdeny-rule check when commands don’t parse cleanly, and a couple of signal-file fixes (scoping per session and widening the gitignore pattern) after/nextstarted terminating the wrong Claude session. -
v0.175 - Auto-pick single items and fd redirect matching
A small but satisfying day.
/nextnow auto-picks when there’s only one backlog item left, skipping the prompt that used to ask me to confirm the obvious. If there are multiple items the interactive selection is unchanged — this only short-circuits the single-item case on the first iteration of a session.On the fix side, the
cli-hookallow-list matcher was failing on macOS when commands included file-descriptor redirects like2>/dev/null. The matcher now stripsfdredirects before comparing against the allow list, so commands that are legitimately allowed don’t get blocked just because of a trailing redirect. -
v0.174 - SQLite backlog storage and search
The big move today was switching backlog storage from YAML files to SQLite, with JSONL kept alongside as a synced mirror for diffing and git history. The migration path also updates
.gitignoreautomatically when the DB is created, so the binary never accidentally ends up committed. A handful of follow-up fixes fell out of this — surfacing parse errors instead of silently dropping items, detecting the SQLite DB in backlog gates, handling null comment phases in the JSONL, and stripping unknown keys inplanTaskSchemaso legacy rows don’t crashbacklog ls.On the feature side,
backlog addnow takes CLI options instead of reading from a file — a breaking change but much nicer for scripting and for the/draftflow. I added awontdostatus for items I’ve decided not to pursue, full-text search across item fields, and browser routing to the backlog web UI so deep links and back/forward finally work. A few UX fixes landed too: prompting before auto-starting a single item, skipping the phase prompt for terminal items, and allowing literal backticks in quoted args forsplitCompound. -
v0.169 - Permission system overhaul and backlog item linking
I overhauled the permission system today. The old monolithic
cli-readspermission group got split into separatereadsandwritescategories, and I added deny rules viacli-hook denycommands so specific patterns can be blocked. Allow and deny rules now merge across tools (Claude Code and any other configured tool), and I fixed a couple of edge cases — normalizing the./prefix in allow matchers and supporting entries without the:*suffix.Backlog items can now be linked to each other, which is useful for tracking related work and dependencies. I also added
--dirto backlog commands for operating on backlogs in other directories, and backlog comments now get inlined directly into phase prompts so Claude Code has full context when executing a phase. Thedraftandbugmodes gained edit mode support, and I added a global config option forsyncauto-confirm so it stops prompting on every sync.On the
seqcommand, I added a--fromoption for filtering by time range and switched historical queries to use/api/datainstead of the events endpoint. I also replaced the--jsonstdin approach with a--fileflag for passing structured input, which is cleaner and avoids control character issues. -
v0.158 - Backlog workflow polish and CLI aliases
I spent today polishing the backlog workflow to make it smoother for continuous use. The headline feature is
backlog nextnow loops automatically when items remain, so I can kick off a session and let it chew through multiple backlog items without manual re-invocation. I also addeddraftandbuglaunch modes with/nextchaining, so after filing a bug or drafting an item the session chains straight into the next piece of work.Backlog items now support comments and summaries — comments can be added during execution and summaries are saved when an item is marked done, giving better traceability on what was decided and why. Items also auto-commit after
backlog add, removing the manual step.I added a
backlog showcommand for viewing item details, and a few convenience aliases:lsforbacklog listandaas a top-level CLI alias forassist. A couple of fixes improved reliability — graceful exit on Ctrl-C during prompts instead of crashing, and fixing summary persistence so it saves on done rather than phase-done. -
v0.150 - Backlog orchestration and test coverage push
I built out the backlog orchestration system today — the big addition is phased execution, where backlog items now progress through tracked phases with automatic advancement. Each phase can include manual checks, and sessions auto-kill on phase completion so Claude Code doesn’t wander off-task. A review phase is auto-generated for each item, and items are automatically marked done when their plan completes. I also added a
/draftcommand for creating new backlog items with LLM-assisted questioning.On the refactoring side, I added
assist refactor extractfor pulling functions and their private dependencies into new files. Getting the import rewriting right took a few iterations — fixing stale import cleanup, rewriting paths in the destination file, and skipping barrel exports for non-public functions.I pushed test coverage from roughly nothing to 17.31%, converting existing tests to BDD style (
describe/itblocks) and adding new coverage forsplitCompound,collectDependencies,resolveImports, and the backlog run completion logic. I also addedtest-coverandtest-reviewslash commands so Claude Code can incrementally improve coverage during sessions.The backlog web view got plan progress display, and the CLI picked up several UX improvements: a
showcommand, numbered acceptance criteria, type display in thenextlist, comments and summaries on items, a-w/--writeflag forbacklog run/next, and aliases likenextforbacklog next -wandremoveforbacklog delete. I also added a/bugcommand for filing bugs with structured reproduction steps and acoveragecommand for reporting test coverage metrics. -
v0.134 - Window screenshot capture command
Added an
assist screenshotcommand that captures a screenshot of a running application window. You pass it a process name likeassist screenshot notepadand it grabs the visible window bounds using the DWM extended frame bounds API (which excludes the invisible shadow padding Windows adds), then BitBlts the region from the screen DC into a PNG.The heavy lifting is in a PowerShell script that gets written to a temp file and executed with
-NoProfile -ExecutionPolicy Bypass. It handles DPI awareness, restoring minimised windows, and all the GDI cleanup. The output directory defaults to./screenshotsbut is configurable viascreenshot.outputDirin the assist config.I also added a
/screenshotslash command so Claude Code can capture windows during debugging sessions — useful for visual verification of UI changes without leaving the conversation. -
v0.132 - Inspect scope unification and issue filters
Continued refining
dotnet inspecttoday. I replaced the separate--refand--baseflags with a single--scopeoption that acceptsall,base:<ref>, orcommit:<ref>— defaulting to working copy diff when omitted. This cleaned up thegetChangedCsFileslogic considerably, turning what was a pair of loosely-related flags into a proper discriminated union with aparseScopefunction.On the filtering side, I added
--suppressto hide specific issue type IDs from the command line (merged with any suppression rules already in config), and--onlyto show exclusively the specified IDs. The--onlyfilter is handy when you’re hunting for a specific category likeCommentedCodeacross a solution without wading through everything else. Both support variadic arguments so you can pass multiple IDs in one go. -
v0.133 - CLI reads refactor, Raven slash command, and Roam integration
I moved all the shell read commands (
cat,head,ls,grep, etc.) out ofclaude/settings.jsonand into theassist.cli-readsfile where they belong. This meant updatingfindCliReadto support single-word command matching — previously it only matched two-word prefixes likegit log, so bare commands likecatorheadwere falling through. Much cleaner having all the read-command allow-listing in one place.Added a
/ravenslash command so Claude Code can interact with RavenDB connections and collections conversationally — listing collections, querying documents, and managing connections without leaving the editor.The
seq querydefault count went from 50 to 1000, which is a much more useful default for log exploration. It now also warns when results hit the limit so you know to increase--countif needed.Finally, I added
assist roam show-claude-code-iconwhich forwards Claude Code hook activity to the Roam local API. It reads the Roam API port from the app data directory and POSTs activity events, failing silently if Roam isn’t running. -
v0.127 - Dotnet inspect overhaul and Seq queries
Big restructure of the .NET inspection tooling today. I replaced the old
netframeworkcommand group with a unifieddotnetnamespace, consolidating code inspection, build tree, and dependency commands under one roof. Thedotnet inspectcommand now runs JetBrains InspectCode by default with--sweaas opt-in, filters out unreliable.Globalrules that were producing false positives, and supports a--baseflag to scope inspections to files changed since a given git ref. I also added a--roslynflag that runs Roslyn-based analysis as an alternative engine, with results filtered to only changed.csfiles.The rate-limit status line segment got smarter — it now colour-codes based on consumption pace rather than just the raw percentage, so the visual signal better reflects whether you’re likely to hit the cap.
The other major addition was
assist seqfor querying Seq log servers. It reuses the same connection-auth pattern I’d built for RavenDB (which I extracted into a sharedcreateConnectionAuthhelper), so you can store named connections and query logs with filters directly from the CLI. I added a/seqClaude command alongside it so Claude Code can search logs during debugging sessions.Finally, I wired up
/inspectas a Claude slash command so code inspections can be triggered conversationally without leaving the editor. -
v0.120.1 - Config resolution from subdirectories
Fixed config loading so
assistfindsassist.ymlwhen invoked from a subdirectory of the repo. PreviouslyloadConfigonly looked in the current working directory, which meant commands failed silently when you were deeper in the tree. Now it walks up to the repo root using a sharedfindRepoRoothelper that was already in the .NET commands — extracted it tosrc/shared/so both paths can reuse it.Also refined the
/review-commentsClaude command to group PR comments by thread rather than processing each comment individually. Follow-up comments (like a reviewer endorsing a bot suggestion) are now presented as context alongside the primary actionable comment, andfixed/wontfixis only called once per thread. -
v0.118 - Rate limits in the status line
Added rate limit visibility to the Claude Code status line. The status line now shows current API rate limit usage, and a follow-up improvement added time-to-reset countdowns so you can see at a glance when limits will refresh. Handy for knowing whether to keep working or take a break when approaching the cap.
-
v0.116 - Backlog web status dropdown
Added a status dropdown to the backlog web UI so items can be moved between statuses directly from the detail view. The
StatusPickercomponent shows available statuses and sends updates back to the server, which parses and writes the new status into the item body. This means I can now triage and update backlog items without leaving the browser. -
v0.115 - RavenDB query commands and Jira view
Added a full suite of RavenDB commands.
ravendb authhandles authentication via 1Password secret references,ravendb set-connectionsaves named connection configs (URL, database, secret ref), andravendb queryruns RQL queries against a connection with automatic pagination. There’s alsoravendb collectionsto list collections andravendb searchfor full-text search across items. Connections are resolved interactively if not specified, and credentials are fetched from 1Password at runtime.Extended the Jira integration with a
jira viewcommand that prints the issue title and description, complementing the existingjira accommand. Refactored the shared fetch logic intofetchIssue.tsso both commands reuse the same API call. Also updated the Claude instructions so it knows when to usejira viewvsjira ac.Narrowed the CLI hook discovery in
permit-cli-readsto only scan files listed in a newassist.cli-readsmanifest rather than discovering all readable commands dynamically. This gives more control over which commands get added to the allow list. -
v0.112 - Madge circular dependency checks and Jira Claude command
Added
madgeas a verify check for circular dependency detection. Selecting it duringverify initinstalls the package and wires up averify:madgescript. While integrating it I found and fixed a handful of actual circular dependencies — extracted shared types in the backlog web UI components and pulled common logic into ashared.tsmodule in the restructure planner.Also added a
/jiraClaude command so Claude Code can fetch Jira issue context directly, and improvedverify initto detect scripts already defined inassist.ymlso it doesn’t offer to set up checks that are already configured. The init detection was refactored to pull setup handler registration into its own module and centralise the “install package and add script” pattern viasetupVerifyRunEntry. -
v0.109 - Refactor rename commands and madge integration
Added two new
refactor renamesubcommands powered byts-morph.refactor rename filemoves a TypeScript file and updates all imports across the project, whilerefactor rename symbolrenames a variable, function, class, or type and updates every reference. Both default to dry-run mode showing what would change, with an--applyflag to execute.Also added
madgeas an option inverify initfor circular dependency detection — selecting it installs the package and wires up averify:madgescript automatically.Fixed a test that was failing on non-Windows platforms by skipping the MSYS path conversion test when not running on Windows.
-
v0.108 - RSS news reader with web UI
Built an RSS news reader into the CLI.
news addlets you add feed URLs to your global config, andnews webspins up a local web server that fetches all configured feeds, parses both RSS and Atom formats, and renders items in a React UI grouped by date. Each feed gets a consistent color-coded badge, items show favicons and relative timestamps, and excerpts are extracted from descriptions with HTML stripped. Also extracted shared web server utilities intosrc/shared/web.tsto deduplicate the pattern already used by the backlog web view.Separately, fixed the
prs fixedcommand to push the commit before resolving the review thread — previously it would resolve the thread with a commit link that didn’t exist on the remote yet. Also suppressed noisy JSON output fromgh apicalls when resolving PR comment threads. -
v0.107 - Jira authentication and acceptance criteria
Added Jira integration with two new commands.
jira authhandles authentication via API token, prompting for site, email, and token then persisting the site and email to~/.assist/jira.jsonfor future use.jira acfetches and prints acceptance criteria for a given issue key, converting Atlassian Document Format to readable markdown text with support for headings, ordered and bullet lists, and inline code.Also fixed
gh apicalls in the PR comment resolution flow to suppress JSON output that was being dumped to the terminal by piping stdout topipeinstead ofinherit. -
v0.106 - Devlog repos command and skip list relocation
Added a
devlog reposcommand that scans all tracked repositories and displays a summary table of their devlog status — showing the last version, date, and how many unversioned days remain. Handy for quickly seeing which repos have pending devlog entries.Moved the devlog skip days configuration out of each individual repo’s
assist.ymland into the blog repo’s config instead. Skip days are now keyed by repo name in a single central location, which keeps per-repo configs cleaner and makes the skip list easier to manage. Updateddevlog skip,devlog list, anddevlog nextto read from the new location. -
v0.102 - .NET Framework dependency tree and run parameters
Added a
netframework depscommand that builds and prints a dependency tree for .NET Framework projects. It finds containing solutions, resolves.csprojreferences, and displays the tree structure. Useful for understanding project dependencies in legacy codebases.Enhanced the
runcommand with positional parameter support —run addcan now define named parameters that get substituted at runtime, making custom commands more flexible. Also added elapsed time printing after each run completes, so you can see how long commands take.Fixed npm install detection to work through
fnmandnvmversion manager wrappers. -
v0.98 - Compound command support in CLI hook
Extended the CLI hook to handle compound commands — piped commands,
&&chains, and semicolons are now split and each part checked individually against the approved reads list. This means Claude Code can auto-approve things likegit status && git diffwithout needing each compound form explicitly listed. Consolidated the cli-hook subcommands into a cleaner structure.Also switched the cli-reads lookup to pure JavaScript to avoid shell overhead on each hook invocation, and made
assist updaterunnpm installafter pulling to ensure dependencies stay in sync. -
v0.96 - CLI read permissions and auto-discovery
Built a CLI permissions system that auto-discovers read-only commands from installed CLIs and generates a flat file (
assist.cli-reads) of safe-to-approve patterns. Thecli-discovercommand parses help output from CLIs to classify subcommands as read-only or mutating, andcli-hookintegrates with Claude Code’s hook system to auto-approve matching commands. This replaces the manually-maintained allow list insettings.jsonfor read operations.Also auto-approves read-only
gh apicalls by inspecting the HTTP method and endpoint, added a/syncslash command for syncing settings from the terminal, and fixed commit argument ordering to put the message first. -
v0.93 - Commit workflow improvements and shell escaping
Improved the
commitcommand to accept a message directly without requiring file arguments, and updatednewto automatically add VS Code configuration when scaffolding a Vite project. Fixed shell argument escaping across the tool and added a--verboseflag for debugging.Several fixes around packaging and release — made voice runtime dependencies optional so they don’t block installation, synced
package-lock.jsonwith the newastalias, and ensured the lock file gets committed during releases. Also fixedisGitRepoto check the exact git root rather than matching parent directories, and used a shorter notification sound for WSL. -
v0.91 - GPU speech-to-text and radon complexity checks
Switched the voice daemon’s speech-to-text to use GPU inference for faster transcription, and fixed silence detection to properly reset after smart turn checks. Also added word-level diffing for more accurate voice typing output.
Added radon-based complexity checks for Python projects — both cyclomatic complexity and maintainability index at the file level. This complements the existing TypeScript complexity checks and runs as part of
verify.Introduced
astas a short alias for theassistcommand. Added context percentage colouring to the status line, madecommitaccept explicit file lists and status output, paginated the GitHub API inlist-commentsto handle large PRs, and hid completed items frombacklog listby default. -
v0.85 - Voice interaction daemon
Built a voice interaction daemon that listens for a wake word and transcribes speech to type into Claude Code. The daemon runs as a background process with configurable wake and submit words — say the wake word to start listening, then the submit word to send. Iterated on it throughout the day, fixing word-level diff for more accurate typing, deduplicating daemon code, and routing debug output to a separate console window.
Added
prs commentfor posting new review comments on PRs, and expandedverifywith anallmode and diff-based filters so you can run all checks or only checks relevant to changed files. Also addedrunenvironment support and ano-venvverification check for Python projects. -
v0.78 - Backlog web polish and verify list
Spent the day polishing the backlog web UI. Migrated the forms to Base UI components and switched the styling to Tailwind for a cleaner look. Added a completed items toggle, a delete command, and story/bug type categorisation. The web UI now opens the browser automatically and is the default when running
assist backlogwith no arguments.On the CLI side, added
verify listandrun listcommands so you can see what verification steps and run configs are available without actually running them. Also addedhardcoded-colorsto the ignore config for projects that need to opt out of colour literal checks. -
v0.67 - React web UI for backlog management
Built a web frontend for the backlog command using React. Running
assist backlog webspins up a local server that serves a single-page app for managing backlog items — viewing, creating, and editing items with descriptions and acceptance criteria. The UI is bundled withtsupand served inline via an HTML template, keeping it self-contained without needing a separate dev server.Also fixed config saving to preserve unknown keys, so custom or future config values aren’t silently dropped when writing back to
assist.yml. -
v0.66 - Verify from run configs and command generation
Updated
verifyto resolve its entries from both run configs and package scripts, so custom verification steps defined viaassist run addare picked up automatically alongside the standard checks. Also maderun addgenerate a command file when adding a new run config, giving each custom command a proper home rather than just an inline script. -
v0.64 - Journal and standup commands
Added
/journaland/standupClaude commands. The journal command appends an entry summarising recent work, decisions, and notable observations. The standup command reads recent journal entries and generates a standup update. Both are Claude commands rather than CLI commands since they rely on Claude’s context and summarisation abilities.Also fixed the commit config to include proper defaults so it works correctly even when not explicitly configured.
-
v0.63 - Roam Research OAuth integration
Added a
roam authcommand that handles the full OAuth authorization flow for Roam Research. It prompts for client credentials, opens the browser for authorization, spins up a local callback server to receive the auth code, and exchanges it for an access token. The token gets stored in the config for use by future Roam commands.Also added a few more git commands (
git status,git grep,git log) to the permissions allow list so Claude Code can use them without prompting. -
v0.58 - Review comment skipping and self-update
Added a skip option to the
/review-commentsClaude command so individual comments can be passed over without needing to reply or resolve them. This is useful for comments that need more thought or aren’t actionable yet.Also added an
assist updatecommand for self-updating the tool via npm, and fixed the permissions allow list for complexity commands. -
v0.56 - Backlog management and project scaffolding
Added a
backlogcommand for managing a simple task backlog — items can be listed (with a verbose flag for descriptions), added with an editor for longer descriptions, and picked off with/next-backlog-itemwhich selects and starts implementing the next item. This gives a lightweight way to track what needs doing without leaving the terminal.Built an
assist newcommand that scaffolds a new project — sets up a Vite React TypeScript template, initialises git, and gets everything ready to go. Also addedtsupsupport tovscode initfor projects using that bundler, and wired maintainability checks intoverify initso new projects get code quality gates from the start. -
v0.48 - Continued restructuring and complexity defaults
Continued the maintainability-driven restructuring from yesterday, breaking apart more modules across the codebase —
computeRewrites,planFileMoves,parseVtt,displayPaginated, and others were split into focused sub-modules. This was another round of using the restructure command on the codebase itself.Added a default action to the
complexitycommand so running it without arguments gives useful output immediately. Also added SHA validation toprs fixedto match whatwontfixalready had, and allowedgh pr viewandgh pr diffin the permissions allow list. Improved the maintainability error message to be clearer about what needs attention. -
v0.46 - Restructure command and codebase reorganisation
Added a
refactor restructurecommand that analyses import graphs, clusters tightly-coupled files, and generates a plan to reorganise them into cohesive directories. It builds an import graph, clusters files by coupling, computes file moves, and can execute the plan — all without needing AI assistance. Also exposed it as a/restructureClaude command for interactive use.Then I ate my own dogfood and used it to restructure the
assistcodebase itself. Large modules likecomplexity/shared.ts,prs/listComments.ts,transcript/parseVtt.ts, andindex.tswere broken apart into focused sub-modules. The mainindex.tswent from a monolithic command registration file to thinregister*.tsfiles. This brought the codebase maintainability scores above 60 across the board.Also added a
readmeCLI command (previously only a Claude command) and cappedwontfixreasons to 15 words. -
v0.42 - Maintainability index as a verification step
Expanded the complexity command into a proper verification step. The maintainability index can now run as part of
verify, failing the build when files drop below a configurable threshold. When a file fails, it includes an explanation of what the maintainability index measures and what’s dragging the score down, which makes the output actionable rather than just a number.Added
complexity.ignoreto the config schema so specific files or patterns can be excluded from checks. Also added support for custom lint verify scripts, letting projects define their own lint commands alongside the built-in ones. -
v0.37 - Config command and settings sync
Added a
configcommand backed by Zod schema validation. It lists current configuration values with their defaults applied from the schema, so you can see effective values even when they’re not explicitly set. This builds on the existingassist.ymlconfig file andloadConfig()infrastructure.Introduced a
syncsubcommand that copies user-level Claude instructions (CLAUDE.md) to the home directory, keeping project-specific settings in sync across workspaces. Also madenotifyconfigurable via the new config system with a default-enabled flag.Fixed packaging issues where Claude commands weren’t being included in the published package, and added type checking to the CI release pipeline to catch build errors earlier.
-
v0.33 - Meeting transcript processing commands
Added a suite of transcript commands for processing meeting recordings. The
transcript formatcommand parses VTT subtitle files into clean markdown transcripts, handling speaker identification and timestamp formatting. Thetranscript summarisecommand uses a staged workflow — it first generates a summary via a Claude command, then saves it alongside the original transcript with a link back to the source file. Iterated on the summary output a few times to get the file paths and links right, including URL encoding and using relative paths.Also improved the PR review workflow —
prs list-commentsnow includes resolved comments (marked as such) for better context, andwontfixvalidates commit SHAs before responding. Updated the/review-commentsClaude command docs to enforce backticks for code references and clarify the markdown link syntax. -
v0.30 - Fixed and wontfix PR comment responses
Continued building out the PR review workflow with
prs fixedandprs wontfixcommands. These replace the earlierreplyandresolvecommands with more opinionated actions —fixedreplies with a message about the fix and resolves the thread, whilewontfixexplains why the comment won’t be addressed and resolves it. This better matches how I actually respond to review feedback.Improved the
list-commentsflow to handle the case where all review threads are already resolved — it now drops the comment cache and prints a clear message instead of showing an empty list. -
v0.27 - PR review workflow and readme checks
Built out the PR review workflow with
prs replyandprs resolvecommands, so I can respond to review comments and mark threads as resolved directly from the CLI. Updated the/review-commentsClaude command to take advantage of these — it now filters out already-resolved threads so Claude only focuses on what still needs attention.Added a
/readmeClaude command that checksREADME.mdfor missing command documentation. This ties into the project convention of keeping the README in sync whenever CLI or Claude commands change.Small fix to use 7-character SHAs in commit output for consistency, and enforced LF line endings across the repo via
.gitattributes. -
v0.22 - Complexity analysis and PR review comments
Added a
complexitycommand that calculates maintainability metrics for source files — cyclomatic complexity, Halstead measures, and SLOC — giving a quick code health overview without needing external tools.Built out PR review comment support in two parts. First, a
prs commentssubcommand that fetches and displays review comments from GitHub PRs in a human-readable format, with proper error handling for missing repos. Second, a/review-commentsClaude command that lets Claude Code process PR review comments interactively. Iterated on the comments output to handle Windows path compatibility and 404s gracefully.Tightened up the codebase with a lint rule to catch
.jsimport extensions in TypeScript files and renamed source files to follow camelCase conventions enforced by Biome. Fixedknipto properly fail verification on config hints instead of silently passing. Removed the unusedenable-ralphcommand and updated the README. -
v0.16 - Desktop notifications and package.json versioning
Added a
notifycommand that integrates with Claude Code’s notification hooks to show desktop notifications when Claude needs attention. It handles different notification types like permission prompts and idle prompts, displaying the project name and relevant message. The command works across platforms - usingnode-notifieron native systems and calling SnoreToast directly from WSL to show Windows notifications. Fixed an issue on macOS where notifications would disappear immediately by setting a long timeout and enabling wait mode.Improved the
devlog nextcommand to read the version directly frompackage.jsonat the last commit whencommit.conventionalis enabled. Previously it relied on parsing devlog entries to determine the current version, but for repos using semantic-release the version is already tracked inpackage.json. This makes the version suggestions more accurate for projects that don’t have a devlog entry for every release. -
v0.15 - Commit workflow, status line, and deploy features
A productive day with several new features for the
assistCLI.Added a
status-linecommand that formats Claude Code’s status JSON into a readable status line showing the model name, token counts (input/output), and context window usage percentage. This integrates with Claude Code’s custom status line feature.Enhanced the
commitcommand with conventional commit validation. Whencommit.conventionalis enabled inassist.yml, messages must follow the standard format likefeat: add featureorfix(scope): fix bug. Also added configurablepullandpushoptions so commits can automatically sync with the remote.The
deploycommand gained aredirectsubcommand that injects a trailing slash redirect script intoindex.html, useful for static site deployments. Thedeploy initcommand now prompts to installnetlify-cliif it’s missing.Updated VS Code settings generation to configure Biome’s organize imports on save, replacing the per-language formatter overrides with a single global config.
Fixed a WSL compatibility issue where enquirer’s confirm prompts displayed incorrectly. Replaced the Unicode symbols with ASCII
[x]and[ ]markers. Also extracted the ESLint removal logic into a shared utility so bothlint initandnewcommands can use it. -
v0.12 - Run command for configured scripts
Added a new
runcommand that executes configured commands stored inassist.yml. You can define named commands with optional default arguments, then invoke them withassist run <name>. Any extra arguments passed get appended to the configured ones. There’s alsoassist run addto quickly register new configurations without editing the YAML manually.The config loader now checks
.claude/assist.ymlfirst before falling back toassist.ymlin the project root, allowing the configuration to live alongside other Claude-related settings.Fixed an issue where
run addwould mangle arguments containing colons or other special characters due to Commander’s argument parsing. The fix bypasses Commander and parsesprocess.argvdirectly to preserve the original argument values. -
v0.11 - PR listing command and automated npm releases
Added a new
prscommand that lists pull requests for the current repository using the GitHub CLI. It supports filtering by state (--openor--closed) and paginates results with interactive navigation when there are more than 10 PRs. Each entry shows the PR number, title, author, status with date, and changed file count.Also set up semantic-release for automated npm publishing. When commits land on main, the release workflow analyzes commit messages and automatically bumps the version, updates the changelog, publishes to npm, and creates a GitHub release. The package is now published as
@staff0rd/assistwith public access. Added conventional commit guidance toCLAUDE.mdto ensure proper version bumping. -
v0.10.2 - Lint init now propagates overrides
Fixed a bug in the
lint initcommand where biome overrides weren’t being copied to the target project’sbiome.json. Previously only the linter rules were propagated, but now any overrides defined in the template (like allowingconstants.tsfiles to use kebab-case naming) get copied over too.Also tweaked the
verify:testscript to use vitest’s dot reporter, which only shows output for failing tests rather than listing every test file. Makes the verify output much cleaner when everything passes.Did some internal refactoring as well, extracting each verify setup function into its own file to keep things organized.
-
v0.10.1 - Devlog command refinements
Made several small improvements to the devlog workflow. Added support for overriding the project name in assist.yml via
devlog.name, useful when the git repo name doesn’t match what I want in devlog entries.Also refined the Claude Code command prompt: improved tag selection guidance to prefer existing tags over creating new ones, added a diff check before skipping entries to ensure nothing meaningful gets missed, and reordered the tag fetch to happen later in the workflow.
-
v0.10 - New project scaffolding commands
Added a
newcommand for scaffolding fresh projects. It sets up the basic structure and automatically runs initialization commands to get a project ready to go. Also added vite base configuration to new projects so they’re ready for building out of the box.Created two new init commands:
lint initsets up biome with my preferred linting configuration, anddeploy initadds a GitHub Actions workflow for automated builds and deployments. The new project command chains these together so a freshly created project has linting and CI/CD configured from the start. -
v0.9 - Major refactoring and filename conventions
Spent the day on a significant refactoring pass. Extracted large modules into smaller, focused files - the verify init command alone went from a monolithic 377 lines down to several purpose-built modules like
detectExistingSetup,setupKnip, andinstallPackage. Did the same for devlog, refactor, and vscode commands.Added filename convention enforcement via biome, requiring files to use either camelCase or be named
index.ts. This prompted renaming several files likedevlog.ts→index.tsandfileNameCheck.ts→runFileNameCheck.ts.Also improved jscpd integration with quieter output and detection of outdated configurations, plus deduplicated package.json reading logic into a shared utility.
-
v0.8 - Refactor check now runs verify scripts
Enhanced the refactor check command to automatically run any
verify:*scripts from package.json before reporting results. This catches issues that static analysis might miss by running the project’s actual verification suite. The verify scripts run quietly in the background and only show output on failure.Also added devlog as a Claude Code skill for easier access, and updated documentation.
-
v0.7 - New init and verify commands
Added a suite of new initialization and verification commands today. The main addition is
vscode init, which sets up VS Code configuration for a project. I also created a generalinitcommand framework to organize these setup utilities.On the verification side, I built
verify hardcoded-colorsto detect hardcoded color values in code (with example fixes), and significantly improvedverify init. The init verification now properly handles package installation, supports vitest for testing, and works with vite-only builds that don’t use a separate build script. -
v0.6 - Devlog command enhancements
Continued refining the devlog workflow today. Added a
--reverseoption todevlog diffso I can view changes in chronological order instead of reverse-chronological, which is more natural when reviewing a sequence of work.Extended the config system with a skip day feature and git permissions, making it easier to manage which dates get skipped and controlling git operations. Also updated the README with documentation for all the new devlog commands.
-
v0.5 - New devlog command for tracking releases
Built out a comprehensive
devlogcommand system today. The main feature isdevlog next, which shows commits since the last versioned devlog entry and suggests the next patch and minor version numbers. This makes it easy to see what needs documenting and pick the right version bump.Added
devlog skipfor marking dates as intentionally skipped (trivial changes that don’t warrant an entry), anddevlog difffor reviewing changes with filtering options like--sinceand--verbose. The diff command also shows devlog status per date so I can see at a glance what’s been documented.Made several supporting improvements: the sync command now shows line-by-line diffs when copying settings, verify got a
--timeroption for performance tracking, and I added verify/commit to the global permissions list so they run without confirmation prompts.Also did some internal cleanup, extracting the devlog functionality into separate modules and adding VSCode settings for biome.
-
v0.4.1 - Fixed verify command path resolution
Fixed an issue with the verify command where it would fail to find the package.json file when running from a subdirectory of the project. The command now walks up the directory tree to locate the nearest package.json, matching the behavior users expect when working in nested folders.
-
v0.4 - Configurable max-lines for refactor checks
Added a
--max-linesoption to the refactor check command, making the file length threshold configurable rather than hardcoded. This lets me adjust the limit based on project needs or temporarily raise it when I’m not ready to split a file yet.Also updated the README to better clarify what the tool does.
-
v0.3 - Git filters for refactor check
Added git filter options to the
refactor checkcommand. The new--modified,--staged, and--unstagedflags let me focus the check on files I’m currently working on rather than scanning the entire codebase. This makes the command much more useful during active development when I only care about files I’ve touched.Also removed the unused
refactor check nextsubcommand that showed the single largest violation - the main check command with sorting already handles this use case well enough. -
v0.2 - Refactor command improvements
Spent the day polishing the refactor command. Fixed stderr handling in the verify command so errors don’t clutter the output, and made the refactor ignore system use the maxLines setting properly.
Added a new static import linting check to catch cases where dynamic imports could be converted to static ones. Also introduced a
refactor nextsubcommand that shows just the next violation to fix, making it easier to work through issues one at a time.Did some cleanup on the violation output, moving extraction tips inline and creating a shared logViolations helper to reduce duplication. Test files are now excluded from refactor checks since they often have legitimate reasons for patterns we’d normally flag.
-
v0.1 - Assist CLI genesis
Started building a CLI tool called
assistto streamline my development workflow. The core features include a commit helper that stages and commits with AI-generated messages, a sync command for updating global commands and settings, and a verify command that runs all project checks in parallel.Added code quality tooling with lint and refactor commands. The refactor command runs various checks (unused exports, file naming conventions, etc.) and supports pattern filtering for targeted analysis. There’s also an ignore mechanism for suppressing false positives.
Switched from plain tsc to tsup for bundling, which should make the CLI easier to distribute. Wrote up documentation including installation instructions and a CLAUDE.md for AI context.