An opinionated agent command center for extreme productivity. Runs on localhost.
by colinhacksHTML
Last 12 weeks · 2170 commits
2 of 6 standards met
With several threads running in one project, the queue holds all of them at once in the right-hand pane. It is easy to scroll from the focused thread onto a different one without meaning to. Current workaround: collapse, then snooze, every thread except the one in focus. This works, but it takes several steps, and it has to be redone each time the focus changes. One possible fix: a focus view that shows only the selected thread in the right-hand pane. A click in the left-hand queue would still move the focus; scrolling in the pane would not. This could sit next to the current behavior rather than replace it. I do not have a full design for this — flagging the underlying problem in case it is worth a look.
The bug On a phone, tapping a link in a thread opens the built-in markdown reader, and the reader does not scroll, not by touch and not by wheel. The document renders; it just never moves. Why Below 800px renders a modal Radix dialog (). Radix locks the page with , whose document-level listener cancels every / outside the dialog. The markdown reader, like every plain (sub-agent, background shell, frizz-doc), stacks over the thread as a sibling layer, not inside the dialog, so its scrolling gets cancelled. On the live app (390px, opened from a thread): the reader's scroller holds 12,529px of content in a 744px box and the touch lands inside it, but , , and is set by the thread's dialog. The fix lets exactly one lock decide: the one that mounted last. Just giving the reader its own lock isn't enough, because mount order isn't reliable here. Radix mounts its lock a commit late (its waits for a layout effect), so when the thread turns modal in the same commit as the sheet above it, the thread's lock still lands on top. Rotating a tablet below 800px with a reader open does exactly this, and so does the fixture below. So the lock follows the top of the drawer stack instead of mount order: wraps its panel in (same 2.7.2 module instance Radix uses, one ), enabled only while it holds the lock on a narrow screen. matches Radix. The holder () is the topmost live layer. When no layer is live, it's the last layer still exiting, so the final thread keeps the page locked through its 210ms slide-out. A closing layer above a live one never holds it. , while it doesn't hold the lock, renders its scrim as a plain div instead of , the element that carries Radix's lock. stays modal, because toggling would swap Radix's content component and remount the transcript. The stand-in keeps like Radix's overlay, so taps on the dimmed area behave as before. moves from into beside a new , so both layers read the same breakpoint and the same "top" definition. becomes a direct dependency of (it was already installed through Radix at the same version; the lockfile change is the three-line importer entry). Desktop is unaffected: above 800px is non-modal and Radix renders no , and never enables its lock. Recordings Left: before. Right: after. Same fixture, same gesture, 390×844 phone emulation. !Before and after: the reader over a thread on a 390px phone. Before, all 72 touchmoves are cancelled and it stays at the top; after, none are cancelled and it scrolls 1224px The bug on a live Frizz (installed build) with a real repo document: MP4s: side-by-side · live, before · fixture, before · fixture, after How the gesture was driven: headless Chrome (DevTools MCP) with phone + touch emulation, recorded from a performance trace's own screenshots (real time). The browser tooling available to me exposes no trusted touch input, so the finger is a script dispatching real cancelable s at the reader. Whether each one is cancelled is decided by the page's own listeners, including react-remove-scroll's. The script applies the finger's travel as scroll only when the event was not cancelled, which is the browser's default action. The status line counts cancellations as they happen. Verification | scroll locks on `ef91617epnpm typecheckpackages/web/src/*/.test.tsboard/.test.mjssync-portable-monitors --checkmonitors/.test.mjsmobile-sheet-scroll-fixture.htmlDrawerStackThreadSheetMarkdownDrawermobileSheetScroll.e2e.test.tspage.touchscreenInput.dispatchTouchEventInput.synthesizeScrollGesturelisten()pnpm testpnpm test:e2e`. Its setup mirrors the probe I did run through the DevTools MCP. 🤖 Generated with Claude Code
What I want I keep the project sidebar open all the time (Settings → Project sidebar, "Always shown"). I currently have 8 projects on it, and each project can have several threads in flight. The sidebar shows an icon for each project, and each icon carries a badge with the size of that project's queue: the threads that need me. I want the sidebar to also show, at a glance, which projects have threads that are still running. Why The value of frizz, for me, is that I do not have to scan several terminals to find out what needs attention. I would struggle without it. The queue badge covers "what needs me now". It does not cover "what is still in progress". Today I have to click into each of the 8 projects to see whether any of its threads are still active. A signal on the sidebar would extend the same at-a-glance model to running work. Example Of my 8 projects, 2 have an agent working. The sidebar shows the same plain icon for all 8 until one of the agents rests and puts a card in the queue. I would like to see which 2 projects are busy without opening them. Scope This is a request only. I do not propose a design. How the sidebar shows it (a second mark, a change to the icon, a tooltip, or something else) is your call, if you decide to make a change at all. Seen on frizz-server 0.14.3.
Frizz doesn't start on Linux or WSL. in WSL (Ubuntu, x64) dies at boot: Cause publishes prebuilt addons for darwin and win32 only. On Linux its script compiles one (). The server-release installer runs npm with , so that never happens: every Linux/WSL generation is staged without , and the server crashes on its first . macOS and Windows are unaffected, which is why it hasn't shown up there. Fix . stays for the tree. (npm adapter): if node-pty has no addon this host can load (checked exactly where node-pty's own loader looks), run only node-pty's install via . is explicit so a user npmrc can't turn it into a silent no-op. On macOS/Windows the prebuild is found and nothing runs. Called in on the staging prefix, before validation and the rename, so a generation that can't open a pty is never selectable. Called in for an already-committed generation, so installs staged by an older launcher heal in place rather than staying broken behind the selection pointer. It only adds the missing addon, so a worker already running that generation is unaffected. A failed build throws a message naming the platform and the toolchain to install ( on Debian/Ubuntu/WSL) plus npm's own output, not the raw loader error. Own 10m timeout for the source build, matching the reasoning in . What I ran (linux-x64, Node 22.22) : 22/22, with 5 new tests covering the loader-mirror check, repair-before-select, in-place repair on load, adapter scoping/idempotence and the failure message. Negative control: with the repair disabled, the 4 behavioral tests fail. (new, real-subsystem): the real npm adapter installs the real from the registry and spawns a real pty from the generation. It then strips the addon to recreate an older launcher's generation, confirms in a fresh process (negative control), and confirms repairs it in place and a pty opens. End to end in a sandbox : published reproduces the crash (). The patched shell, run through over the same failed state, reaches with mapped in the server process. clean. The three CI checks pass. Not run: the full suite (it needs real provider CLIs and a browser), and macOS/Windows, where the code path is a prebuild-found no-op covered by the unit test. Note: my sandbox blocks nodejs.org, so the node-gyp builds above used pointing at local headers. On a normal network node-gyp downloads them itself.
Repository: colinhacks/frizz. Description: An opinionated agent command center for extreme productivity. Runs on localhost. Stars: 25, Forks: 5. Primary language: HTML. Languages: HTML (54.1%), TypeScript (39.7%), JavaScript (5.8%), CSS (0.4%), Shell (0%). License: MIT. Homepage: https://www.npmjs.com/package/frizz Topics: agents, ai, claude-code, codex, developer-tools, orchestration. Latest release: v0.13.5 (3d ago). Open PRs: 0, open issues: 1. Last activity: 2d ago. Community health: 42%. Top contributors: colinhacks, amikofalvy, 8r4x, pullfrog[bot], ssalbdivad.