PawWork
A Chrome extension that turns the page you are already logged into into the starting point of a task: you select the part of the live page that matters, describe the outcome you want in the side panel, and the agent works from that selection and hands back an editable office file, with your own model key, no hosted service, and the model-written JavaScript confined to a QuickJS sandbox inside the browser.

What it is
PawWork is a Chrome MV3 extension, loaded unpacked rather than installed from the Web Store, that treats the browser you are already logged into as the machine an agent works on. The order of operations is the point: you select a region of the live page first, and that selection becomes user-owned context — one of the environment groups the side panel holds as selections, clipboard pins and page items, which only the interface may change and which the model’s tools are explicitly forbidden to mutate. You then describe the outcome, and a tool loop in an offscreen document aims its inventory at what the session actually holds — inspect, acquire, run, clarify, action, task, sheet, doc, web — before calling your own OpenAI-compatible model. Deliverables are files you can keep editing: sheets, Univer documents and site HTML open in preview tabs, and the session store, the model loop and the sandbox that runs model-written JavaScript all live inside the extension. No package.json and no build step, no hosted model and no server.
Who built itThe account behind 17 of the repository’s 20 commits, all of them in September 2026; two of those were made under the name 0xYN from the same email address. A Cursor agent accounts for one commit, an address at ByteDance for one, and a workflow bot for the last. 15 of the 20 commits carry a co-author trailer and 14 of those name Cursor. The recon report carries no profile text, follower count or other biography for the owner.
How it is put together
The parts · 6An unpacked Chrome extension that treats the logged-in browser as the computer, layered strictly by what each Chrome process is allowed to do. The agent loop never lives where it can be killed, so the service worker holds only the permission surface — tabs, downloads, cross-frame fan-out, opening preview tabs and the workspace_sys route — while the session store, the tool loop and the sandbox sit in an offscreen document that talks to the side panel over an RPC facade. Selection enters as data rather than as text: it is captured in the content script on the page and then modelled as environment context owned by the user, readable by the model and off limits to its tools, which is what makes a selection-first flow enforceable rather than a convention. Deliverables are canvases — a sheet, a Univer document, a site page — rendered in preview tabs from tracked vendor runtimes, so the result of a task is something the user keeps editing instead of a message. All of it runs on the model key the user supplies, with the guest sandbox holding no extension privileges and reaching the browser only through a small ABI.
- Chrome host layer
src/background.jsat 76,439 bytes as the service worker, routing workspace RPC, page actions,sys, the sheet and canvas hosts, screenshots, downloads, previews and tab groups, with a 183,745-bytesrc/content_script.json all URLs in all frames for selection and per-frameaction, a 2,822-byte packer script, and a 2,207-byte manifest declaring the side panel, the sandbox, the content scripts and, as the architecture document lists them, twelve permissions.- src/agent/ — the session workspace
- 109 files: the RPC facade (
sessionWorkspaceService.js, 64,105 bytes), the tool loop (sendMessage.js24,681,sessionAgent.js23,217) and a 73,485-byte tool implementation file, plus the durable store, the artifact and office surface, prompts, skills and a render engine, with host primitives (acquire,run,webFetch,webSearch,netGuard), the browser host adapter (browserSysHost.js37,106) with tab leases and a task scheduler, and vendor loaders for QuickJS, esbuild and the AI SDK. - src/sandbox/ and src/offscreen/
- The 4,076-byte QuickJS guest runtime declared as
manifest.sandbox, embedded as an iframe by a 1,929-byte offscreen runtime that creates the session workspace service. The guest has nochrome.*and reaches the browser only through thesysABI served on theworkspace_sysroute, which is also the only reason theuserScriptsanddebuggerpermissions exist. - src/preview/ — the canvases
- 35 files carrying most of the repository’s weight: the tabs that render sheets, documents, sites and artifacts as editable canvases, including a 60,164-byte sheet runtime, 24,347 bytes of site motion, a 32,440-byte preview script and 8,078 bytes of sheet codec, beside tracked Univer bundles of 12,984,218 and 8,939,175 bytes and a 61,309-byte
fflatebundle. - src/sidepanel/ and the side panel shell
- A 494,430-byte
sidepanel.jsand a 182,057-byte stylesheet behind a 48,710-bytesidepanel.html, with 21 supporting modules — i18n at 22,805 bytes, task status, session isolation, tab-lease UI and trajectory UI among them — rendering the conversation, the selection context and the deliverables without running the agent loop. - Docs, tests and release
- The root
AGENTS.md(8,932 characters, 13,419 bytes) plus nested agent documents undersrc/(src/AGENTS.md8,194 bytes,src/agent/AGENTS.md11,504,src/preview/AGENTS.md1,990) and three READMEs of 5,600, 997 and 690 bytes, describing the layering, the tool contracts and the boundaries. Seven test files cover pure-Node regression logic (18,524 bytes), tab leases, the task model, scheduler, wiring and UI, alongside a 9,267-byte Playwright smoke test that CI does not run; the 1,513-byte workflow runs the same test glob plus pack-shape assertions, one of which requires the packed build to contain the TSV fix.
Choices, and what they beat
Bring your own key, with no hosted model in the middle over a hosted or proxied model that the project operates
The README states it in one line — no hosted model, bring your own key — and the key is pasted into the side panel and stored in
chrome.storage.local. The consequence is written down as well: the offscreen document starts without a key because the model is only resolved when a message is sent. The recon report records no account, pricing or backend surface anywhere in the tree.Run model-written JavaScript as a guest in a QuickJS sandbox over letting generated code call the extension APIs directly
The layering table gives the sandbox two prohibitions — it must not read extension storage and must not change a SelectionGroup — and the boundary section repeats that the guest has no
chrome.*and reaches the browser only through thesysABI. What that isolation costs is the subject of the September 16 pull request: no timers, a cap of about twenty seconds per evaluation, and a model working around both by hand.Keep the agent in an offscreen document and the service worker stateless over holding the session store and the model loop in the service worker
The architecture document reasons from the platform: the worker gets killed, so it must not hold the session store or run the loop, and it keeps only the permission surface — tabs, downloads, cross-frame fan-out, preview tabs and the
sysroute. The same choice shows up in the limits the project accepts, because a crashed execution is voided and live-page tab leases live in worker memory and go with it.Optional durable tasks instead of an exactly-once journal over a per-call journal with automatic recovery after a crash
The document is explicit that a task is a progress object kept with the session meta, that alarms only wake on the stored due time, and that the store is the authority. A normal message neither creates nor binds one; only a task run, an alarm or a resume from the interface attaches a turn to an existing task. The project calls this progress and alarms rather than a journal, and says exactly-once behaviour across a crash is not provided.
Wait inside the page rather than polling from the host over repeated short host evaluations with hand-rolled sleep chunks
The pull request that added the primitives argues from a real trajectory: the guest has no timers, every evaluation was capped at about twenty seconds, so a long poll was cut off and one streaming read had to be split into roughly ten runs. The wait primitive polls with the page’s own timers, which puts it outside that cap, lets it wait up to 120 seconds, and can hold until a value that keeps changing settles.
Read fromAGENTS.md (8,932 characters, 13,419 bytes) for the layering, the domain objects, the path of one user message and the list of unimplemented boundaries; README.md (2,189 characters) for the load steps, the Chrome version requirements, BYOK and the test commands; the complete 199-file tree with sizes; and the bodies of three pull requests.
Build log
5 stages- 01
Three unpacked builds in fifty minutes, then a version number
The repository was created on 2026-08-28 and everything in it happened in September: 20 commits between 2026-09-01 and 2026-09-17, the oldest a release build and the newest adding durable tasks and live-page tab leases. Six releases came out of that run. Four are named after their commits and all four landed on 2026-09-01 —
unpacked-9829868at 01:59:49,unpacked-f2a02f0at 02:07:37,unpacked-af56da4at 02:49:04 andunpacked-570482bat 15:03:12 — three builds inside fifty minutes, then eight hours to the fourth; after that camev1.0.0-unpackedon 2026-09-09 andv1.1.0on 2026-09-16. Around them sit 2,881 stars, 10 forks, 5 watchers, 0 open issues, MIT, JavaScript and 17,773 KB. 15 of the 20 commits carry a co-author trailer, 14 of them naming Cursor, and the contributor list has three entries: the owner with 17 commits, a Cursor agent with one and a workflow bot with one. The names in the materials do not line up: the repository the report describes is Player-YN/BrowserKitten, while the README is titled with a Chinese name followed by PawWork, the release titles say “Paw Work unpacked”, and AGENTS.md records the origin asPawWork_ZhuaZhua.git. BrowserKitten appears nowhere in those documents, and the older name PageWand survives inchrome.storage.localkeys while message targets are still prefixedpawwork-. - 02
The selection is the interface, and the model does not own it
The project calls itself selection-first, and the code for it sits at both ends of the extension. On the page side,
src/content_script.js— 183,745 bytes, registered on all URLs in all frames — does what AGENTS.md calls reaching out a paw to select, plus a per-frameactionsnapshot and mutate. On the session side a selection is not prompt text but a domain object:Group + WebItemis described as the environment context the user owns, listing selections, clipboard pins and page items, and the architecture document puts the rule plainly — only the interface RPC may change it, and the tools are forbidden from mutating a SelectionGroup. The model can read the context the user assembled but cannot quietly rewrite it, and the tool loop is aimed rather than exhaustive:sendMessagebuilds its inventory from what the session actually holds, in the document’s phrase aiming rather than hiding tools. That inventory is inspect, acquire, run, clarify, action, task, sheet, doc and web, chosen by an AI SDK 7 ToolLoopAgent, andsysis deliberately not among them — it is called from inside code thatrunexecutes. How the selected DOM reaches the model is not covered by the materials: the tree shows a 16,856-bytepickContext.jsand an 11,440-bytepageItems.jsamong the other context modules, butsrc/AGENTS.md, which explains that transport, is not part of the recon report. - 03
The file comes back as a canvas you keep editing
What the user gets at the end is not an answer but an artefact: the architecture document defines an Artifact as a session deliverable — sheet, Univer document, site HTML or file — created by
run, by the office tools or by the interface. The tree shows where that work lives:officeTools.jsat 33,341 bytes,sheetApply.jsat 45,764 andpptxExport.jsat 25,344 inside the session workspace, plusdocExport.js,sheetCodec.jsand a 60,164-bytesheet.jsin the preview tabs, next to tracked Univer bundles of 12,984,218 bytes for sheets and 8,939,175 for documents. Three canvas kinds exist: sheet, doc, andwebmarked withdata-paw-kind=site; the document is explicit that there is no Design or Slides canvas, even though the topics mention tldraw and a pptx module exists. Which code writes the Office container itself is not covered by the materials. The one format-level detail they carry is a bug: a pull request from 2026-09-15 reports that saving a TSV sheet whose cell held a tab character wrote the tab as a separator, so reopening it split one cell into two columns and shifted every value after it. The fix quotes tab-bearing values in the shared CSV/TSV escaper, and the regression runs the productionaoaToCsvtoparseDelimitedround trip: on the unchanged base the new test fails, turning three values into four, and with the fix the suite reports 16 passed, 0 failed. - 04
No server, no hosted model, and a guest with no chrome
The product does everything inside the browser. The extension has no
package.jsonand no build step; the only script outside it is a 2,822-byte Python packer that turns the trackedmanifest.json,icons/andsrc/into a release folder and a zip, which is how it ships. There is no hosted model and no proxy either: the user pastes an OpenAI-compatible key into the side panel and it is stored inchrome.storage.local, while the offscreen document starts without one because the model is resolved only when a message is sent. Model-written JavaScript gets none of the extension’s privileges: it runs as a guest in a QuickJS sandbox declared throughmanifest.sandbox(a 4,076-bytesrc/sandbox/runtime.js), embedded as an iframe by the offscreen document, with nochrome.*at all; to reach the browser it calls asysABI covering tabs, eval, fetch, cdp, download and screenshot, served by the service worker; theuserScriptsanddebuggerpermissions exist only for it. The guest runs whatever the model writes, and the bundling happens in the browser: a 45,789-byte runtime pulls a 13,978,850-byte esbuild wasm, a 902,483-byte QuickJS loader and a 1,162,837-byte AI SDK loader out of the tracked vendor directory, so agent code runs with no toolchain on the machine. The recon report records no server, deployment or container file in the tree. - 05
The friction the author called self-inflicted, and limits written down as limits
The most revealing document in the repository is the pull request that added two sandbox primitives on 2026-09-16. Its background says the author analysed a real trajectory, a conversation with a logged-in chat page, and found the agent spending most of its effort fighting its own sandbox rather than doing what no other tool could. The guest is QuickJS and has no timers, so waiting meant pushing sleep logic into page-evaluated code, and every evaluation was capped at about twenty seconds, so one streaming read had to be split into repeated short evaluations with hand-rolled sleeps. The author’s verdict is that this friction was self-inflicted rather than a physical limit, and the fix was two ABI primitives: a guest-level sleep the host provides, and a wait-for call polling inside the page with the page’s own timers, which escapes the per-evaluation cap, waits up to 120 seconds and can hold until a changing value settles. Sending a message and reading a streamed reply went from roughly ten runs to one send and one wait. The boundary section is written the same way, calling its limits limits rather than a to-do list: no durable per-call journal, tab leases held only in service worker memory and lost with it, and no way out of the browser at all — no native system control, no local commands, and, in the project’s words, no verified high-fidelity Office round trip.
Adjacent records
All records →No. 109
Whiteboard
A desktop app that puts an agent and a person on the same canvas: the agent draws the review — sequence diagrams, entity relationships, code peeks pinned to specific commits — and every shape on that canvas links back to the code it was drawn from.
No. 078
OpenChatCut
A local-first video editor whose editing surface is a conversation: the built-in agent and external Codex or Claude Code sessions call the same editing tools the interface itself uses, so every change lands on a real multi-track timeline as a clip, transition, caption, effect or audio item that can still be dragged, undone and exported. Projects and media stay on the machine, and preview and final render both come out of Remotion.
No. 114
Rome
A self-hosted agent runtime that treats the environment around a model as the thing worth growing: a Rome App packages an interface, executable actions, on-demand skills and a private database as git-tracked code an agent can reuse later, while the runtime gives every delegated subagent a child session of its own, forks a turn without letting it mutate its source, and fails a turn rather than quietly swapping the model that produced the conversation.