claude-do-it 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,47 @@
1
1
  {
2
2
  "name": "claude-do-it",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "description": "A Markdown todo that you and Claude edit at the same time: a CRDT daemon, a versioned CLI for agents, a browser editor, and a Claude Code skill.",
5
+ "keywords": [
6
+ "claude",
7
+ "claude-code",
8
+ "agents",
9
+ "todo",
10
+ "markdown",
11
+ "crdt",
12
+ "cli"
13
+ ],
14
+ "license": "MIT",
15
+ "author": "Dominique Rau",
16
+ "homepage": "https://github.com/DomiR/claude-do-it#readme",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/DomiR/claude-do-it.git"
20
+ },
21
+ "bugs": {
22
+ "url": "https://github.com/DomiR/claude-do-it/issues"
23
+ },
24
+ "type": "module",
25
+ "bin": {
26
+ "do-it": "bin/do-it.js"
27
+ },
28
+ "files": [
29
+ "bin",
30
+ "web",
31
+ "skill",
32
+ "NOTICE"
33
+ ],
34
+ "engines": {
35
+ "bun": ">=1.3"
36
+ },
37
+ "os": [
38
+ "darwin",
39
+ "linux"
40
+ ],
41
+ "dependencies": {
42
+ "@effect/platform-bun": "4.1.2",
43
+ "effect": "4.1.2",
44
+ "diff": "9.0.0",
45
+ "loro-crdt": "1.17.1"
46
+ }
47
+ }
package/skill/SKILL.md ADDED
@@ -0,0 +1,263 @@
1
+ ---
2
+ name: do-it
3
+ description: "Run a Markdown todo as the user's only interface to a team of agents. `/do-it [file]` opens the todo (default TODO.md, created when missing) in the browser; `/do-it <request>` first runs the request read only and writes its result into the todo as one task per item, which wait until the person writes under them. Then this session becomes the conductor: it watches the file, sizes every task line, plans it with Fable or GPT-6 Astra, delivers it through worker agents in their own worktrees and one shared tester, and writes status, questions, and results back under each task. Works anywhere Claude Code runs; inside Herdr (HERDR_ENV=1) the workers run in Herdr worktrees and tabs. Also the reference for reading and changing any do-it document with versioned `do-it` commands. Trigger on '/do-it', 'do-it', 'do it from my todo', 'work through TODO.md', 'conduct this todo'."
4
+ ---
5
+
6
+ # do-it
7
+
8
+ Arguments: **$ARGUMENTS**. When the first line is empty, or names an existing file, or ends in `.md`, it is the todo file (empty means `TODO.md` in the current directory). Anything else is a **seed request** (for example "list the PRs I am tagged in today"): the todo is `TODO.md` in the current directory, and Step 1b turns the request into tasks.
9
+
10
+ You are the **conductor**. The person only looks at the todo in their browser. Everything they want done arrives as lines in it, and everything they need to know (status, plans, questions, results) goes back into it, under the task it belongs to. Never ask them to relay anything between agents, and do not expect them to read this chat.
11
+
12
+ ## The do-it commands
13
+
14
+ Every open file is a CRDT document held by the do-it daemon, shared by the person's browser tab and every agent. Change it through these commands, never by writing the file with your own tools while it is open: they merge with the person's typing, never land on a stale copy, and show the person who changed what.
15
+
16
+ ```bash
17
+ D=do-it # not on PATH: see below
18
+ $D read TODO.md # "Version: 7" then the text
19
+ $D read TODO.md --section tasks # one section; IDs are heading slugs
20
+ $D sections TODO.md
21
+ $D todo list TODO.md # "3. [x] Ship" per task
22
+ $D todo add TODO.md --version 7 --section tasks "Write tests"
23
+ $D todo start TODO.md --version 8 --section tasks -- "Write tests" # add the PlainTasks start time
24
+ $D todo check TODO.md --version 9 -- "Write tests" # by text; also uncheck, cancel, uncancel
25
+ $D append TODO.md --version 10 --section notes -- "- found: flaky CI"
26
+ $D edit TODO.md --version 10 --old "ship friday" --new "ship monday"
27
+ $D diff TODO.md --since 9 --wait 100 # waits for the next change, exit 4 when none came (keep it under the Bash tool's 120 s default)
28
+ $D watch TODO.md --todos # every change, as task lines
29
+ ```
30
+
31
+ - Every reply starts with the document's version; every change by anyone takes the next number. Always pass the version you last saw: the one in the reply to your last change, or `do-it read FILE --json | jq .version`. Two changes in a row to the same section need two versions (the second names the first one's reply).
32
+ - `Updated. Version: 8`: done. `Updated section "tasks". Version: 8. Other sections changed since 5:` plus a diff: done, and the diff is what others did elsewhere. `Version mismatch, nothing changed. Latest version: 9. Changes since 7:` plus a diff (exit 1): read it, decide whether your change still makes sense, and send it again with `--version 9`. When it says to run `do-it read`, do that. Never retry with a guessed number.
33
+ - Pass `--section ID` when a change belongs to one section: then you conflict only with changes to that section.
34
+ - Text starting with `-` goes after `--`. `-` alone reads standard input (multi line blocks).
35
+ - `edit --old` must match exactly one place; add context until it does.
36
+ - Name yourself: `--as NAME` or `export DO_IT_AGENT=NAME`. The person sees the name next to your changes, and `watch --as NAME` skips your own changes.
37
+ - When `do-it` is not on PATH, define it as a shell function at the top of every Bash call (functions do not survive between calls, and `D="bun ..."` breaks in zsh because `$D` is not word split): `do-it() { bunx claude-do-it "$@"; }` (from a repo checkout: `do-it() { bun "<repo>/packages/cli/src/bin.ts" "$@"; }`). Monitor commands spell out the `bunx claude-do-it` (or `bun .../bin.ts`) call in full.
38
+ - Exit codes: 0 done, 1 refused or version mismatch, 2 invalid arguments, 3 daemon not running and could not start, 4 nothing yet, 9 the document was deleted.
39
+
40
+ ## Step 1. Open the todo
41
+
42
+ ```bash
43
+ command -v do-it >/dev/null || echo "do-it is not on PATH: define the do-it function (see above)"
44
+ export DO_IT_AGENT=conductor
45
+ ARG='<the todo file from the arguments, empty for a seed request>'
46
+ TODO=$(cd "$(dirname "${ARG:-TODO.md}")" && pwd)/$(basename "${ARG:-TODO.md}")
47
+ SLUG=$(printf '%s' "$TODO" | shasum | cut -c1-10)
48
+ STATE=${DO_IT_HOME:-$HOME/.do-it}/runs/$SLUG # inbox.md, tests.md, plans/, logs/, state.json
49
+ mkdir -p "$STATE/plans" "$STATE/logs"
50
+ ```
51
+
52
+ Open it for the person. It starts or reuses the daemon, creates the file from a template when missing, opens the browser, and returns at once:
53
+
54
+ ```bash
55
+ if [ "${HERDR_ENV:-}" = 1 ] && [ -x /Applications/Sheprd.app/Contents/MacOS/sheprd ]; then
56
+ DO_IT_BROWSER="/Applications/Sheprd.app/Contents/MacOS/sheprd browser open" do-it open "$TODO"
57
+ else
58
+ do-it open "$TODO"
59
+ fi
60
+ do-it read "$TODO"
61
+ ```
62
+
63
+ Tell the person in one line that the todo is open and that they can add tasks there. Create the two agent channels with your Write tool if missing (nobody has them open yet): `$STATE/inbox.md` (`# Inbox`, `## Messages`) and `$STATE/tests.md` (`# Tests`, `## Queue`). If `$STATE/state.json` exists, this is a resume: reconcile it with what still runs (Herdr: `herdr agent list`, `herdr worktree list --json`; otherwise the worktrees in `git worktree list`) and only dispatch tasks that have no live worker and are not delivered.
64
+
65
+ ## Step 1b. Seed from a request
66
+
67
+ Only when the arguments were a seed request. Do the request yourself, read only (or with one read only `Explore` agent): fetch, search, list. Change nothing, message nobody, start no worker. Then write the result into `## Tasks` as one task per item, so the person can act on each one:
68
+
69
+ ```markdown
70
+ - [x] <the request, as they wrote it>
71
+ - **t1** seeded: 12 PRs below (7 open). Write a note under one to act on it
72
+ - **Ada Lovelace**
73
+ - [ ] [#101](https://github.com/org/repo/pull/101) Add CSV export to reports (open)
74
+ - [ ] [#104](https://github.com/org/repo/pull/104) Fix the login redirect loop (merged)
75
+ - **Grace Hopper**
76
+ - [ ] [#102](https://github.com/org/repo/pull/102) Cache search results (open)
77
+ ```
78
+
79
+ - When the request asks for a grouping ("group by user"), each group is a plain bold bullet (`- **Name**`, no checkbox), with its items as indented `- [ ]` lines under it. Never use headings for groups: they become their own sections and fall out of `--section tasks`.
80
+ - One item per line: link first, a few words, the state that matters in parentheses. Put the item's details in the item line, not in sub bullets.
81
+ - The request line is checked off with `todo check` after the items are written; items stay unchecked.
82
+ - Record every item in `state.json` with status `listed`. Listed items are **not** tasks for Step 3: they wait. They become a task only when the person writes a note under one (or edits its text): then triage that item with their note as the instruction, and give it the next `tN`. A listed item the person checks off is done: do nothing.
83
+
84
+ ## Step 2. Watch
85
+
86
+ Start each watch with the Monitor tool; every printed line is an event:
87
+
88
+ ```bash
89
+ do-it watch "$TODO" --as conductor --settle 25 # one line once the person stopped typing for 25 s
90
+ do-it watch "$STATE/inbox.md" --as conductor --section messages
91
+ do-it watch "$STATE/tests.md" --as conductor --todos # outside Herdr only: when to start the tester
92
+ ```
93
+
94
+ Use `--quiet` to skip the initial `Watching PATH at version N` line instead of filtering it with grep. A filter must be line buffered, or lines arrive late. `Settled at version N by the user` means the person changed the todo and paused. Then `do-it read "$TODO"` once and compare it with your picture of the file. Never act on a half typed line. `Missed changes, now at version N: run do-it read` means the watch history was forgotten, so read the current todo before acting. `Daemon restarted, now version N` needs nothing but a fresh read. When re-arming a watch, pass `--since` the last version you have read, not the original one. Exit 9 means the todo was deleted or moved: stop and report in chat.
95
+
96
+ ## Step 3. Triage each new task
97
+
98
+ A task is any `- [ ]` line (or plain non empty line under `## Tasks`) that has no `**tN**` status line under it and is not a `listed` item from Step 1b. A `- **Name**` bullet without a checkbox is a group label, never a task. An empty `- [ ]` line is the person's typing spot (the new file template has one): leave it alone. Give it the next id `tN` and size it from its text and a quick look at the code it names (delegate a search to `Explore` when unsure, keep only the conclusion):
99
+
100
+ | Size | Looks like | Planner | Worker |
101
+ | --- | --- | --- | --- |
102
+ | S | one file or setting, obvious change, no design choice | `fable-advisor`, short plan | one worker |
103
+ | M | a feature or fix in one area, a few files, needs tests | `fable-advisor` | one worker |
104
+ | L | crosses packages or services, protocol or data migration, concurrency, security, unclear root cause, or the person calls it big | GPT-6 Astra at `xhigh`, then one `fable-advisor` pass over that plan | one worker, Astra for the hard pieces |
105
+ | Q | a question, research, or a decision, no code | none | none: answer it yourself or with one read only `Explore` agent, and write the answer under the task |
106
+
107
+ Repo: the one containing the todo, unless the task names another. If you cannot tell, ask under the task instead of guessing.
108
+
109
+ Write the status line at once, then dispatch while fewer than 3 workers are active (otherwise status `queued`, dispatched in todo order as workers finish):
110
+
111
+ ```bash
112
+ do-it edit "$TODO" --version $V --section tasks \
113
+ --old "<the exact task line>" \
114
+ --new "<the exact task line>
115
+ - **t3** M, planning with Fable"
116
+ ```
117
+
118
+ Immediately after writing the status line, start the task with the version returned by that edit:
119
+
120
+ ```bash
121
+ $D todo start "$TODO" --version $V --section tasks -- "<exact task text>"
122
+ ```
123
+
124
+ Never rewrite the person's own task text. Your lines are indented sub bullets starting with `**tN**`; there is exactly one status line per task, which you replace as the task moves, plus any `**tN question:**` lines. Record every task in `$STATE/state.json` (id, text, size, repo, branch, worktree, agent id or name, status) after every transition; it is how you resume.
125
+
126
+ ## Step 4. Deliver
127
+
128
+ The roles are the same in both transports:
129
+
130
+ | Role | Who | Count | Writes code | Runs builds or tests |
131
+ | --- | --- | --- | --- | --- |
132
+ | Conductor | this session | 1 | no | no |
133
+ | Planner | `fable-advisor` (S, M) or GPT-6 Astra (L) | per task | no | no |
134
+ | Worker | one agent per task, in its own worktree, named `tN` | at most 3 at once | yes | **no** |
135
+ | Tester | one agent | **exactly 1** | no | **yes, the only one** |
136
+
137
+ The single tester is the compute budget. Nobody else runs a compiler, test suite, linter, type checker, dev server, or browser. Formatters are the exception. Workers queue a test request and wait:
138
+
139
+ ```bash
140
+ do-it todo add "$STATE/tests.md" --version <v> --section queue --as tN \
141
+ "tNrK tN: <command> in <absolute worktree path>"
142
+ do-it diff "$STATE/tests.md" --since <v> --wait 100 # loop on exit 4; read the answer under your request
143
+ ```
144
+
145
+ ### Outside Herdr: Claude Code subagents
146
+
147
+ Subagents cannot start subagents and cannot be prompted while they run, so you call every agent yourself, always with `run_in_background: true` so watch events keep arriving.
148
+
149
+ 1. **Plan.** S and M: `Agent(subagent_type: "fable-advisor")` with the task, the repo, and what triage found; ask for a plan in under 300 words. L: `Agent(subagent_type: "astra-implementer")` with a brief that forbids edits and asks only for a plan at effort `xhigh`, then one `fable-advisor` pass over it (when `astra-implementer` is not among your agent types or reports the codex CLI unavailable, plan L tasks with `fable-advisor` and say so in the status line). Save the plan to `$STATE/plans/tN.md` and set the status line to `**tN** planned by <Fable or Astra>: <summary in a few words>`.
150
+ 2. **Build.** `Agent(subagent_type: "general-purpose", isolation: "worktree", run_in_background: true)` with the worker brief below. Keep the agent id in `state.json`.
151
+ 3. **Test.** When the `tests.md` watch shows an open request and no tester runs, start one: `Agent(subagent_type: "general-purpose", run_in_background: true)` with the tester brief. It drains the queue one request at a time, oldest first, and exits; start it again for the next requests.
152
+ 4. **Questions.** A worker that needs the person appends a `question` to the inbox and ends its run with `QUESTION: ...`. Write it under the task (` - **tN question:** ...`, status `waiting for you`). When the person answers under it, resume that same worker with `SendMessage` to its agent id: `From the TODO: <their answer>`.
153
+ 5. **Review.** When a worker ends with `DONE`, verify (below), then run `fable-advisor` on the branch diff against the task. `ship`: delivered. `fix-first`: resume the worker with the findings.
154
+
155
+ Worker brief:
156
+
157
+ ```
158
+ TASK tN (size S|M|L): <the person's task line, verbatim, plus their sub notes>
159
+ REPO: <repo root>. You run in your own git worktree on your own branch; commit there.
160
+ PLAN: <the plan from $STATE/plans/tN.md>
161
+ NAME: export DO_IT_AGENT=tN before any do-it command.
162
+ TASK TARGET: keep the person's task text verbatim. For todo start and todo check, target that exact text after --, never a remembered task number. If the text is unavailable, run do-it todo list immediately before choosing a target.
163
+ COMPUTE RULE: never run builds, tests, linters, type checkers, dev servers, or browsers yourself.
164
+ Formatters are fine. To test, queue one request and wait for the answer:
165
+ do-it todo add <STATE>/tests.md --version <v> --section queue "tNrK tN: <command> in <your worktree>"
166
+ do-it diff <STATE>/tests.md --since <v> --wait 100 (repeat on exit 4; the Bash tool stops a call at 120 s by default)
167
+ Batch what you need into one request; the queue is shared by every task.
168
+ PROGRESS: at real milestones only, append to <STATE>/inbox.md section messages:
169
+ do-it append <STATE>/inbox.md --version <v> --section messages -- "- tN progress: <one line>"
170
+ QUESTIONS: when the person must decide, append "- tN question: <question>" there, then end your
171
+ run with "QUESTION: <question>". You will be resumed with the answer.
172
+ DONE: commits on your branch, the final test request PASSED. End with
173
+ "DONE: branch <name>, worktree <path>, commits <shas>, tests <request ids>".
174
+ Do not push, open a PR, or merge unless the task line asks for it in words. Never edit the todo file.
175
+ ```
176
+
177
+ Tester brief:
178
+
179
+ ```
180
+ You are the only agent allowed to build, test, lint, type check, start dev servers, or drive a
181
+ browser. export DO_IT_AGENT=tester. Requests are the open tasks in TESTS=<STATE>/tests.md, section
182
+ queue, each "- [ ] rN tN: <command> in <absolute path>". Run them one at a time, oldest first:
183
+ run exactly that command in that path with output to <STATE>/logs/rN.log, then under the request
184
+ do-it edit <TESTS> --version <v> --old "<request line>" --new "<request line>
185
+ - PASS in 3m12s, log <path>"
186
+ or FAIL in 1m05s, log <path>: <the first error, at most 15 lines, and the cause in one sentence>
187
+ and check the request off (do-it todo check). Never edit code, never commit, never fix failures.
188
+ If a command would run longer than 30 minutes or needs a desktop you do not have, answer BLOCKED
189
+ with the reason. When no open request is left, end your run with "QUEUE EMPTY".
190
+ ```
191
+
192
+ ### Inside Herdr (`HERDR_ENV=1`): worktrees and tabs
193
+
194
+ The same roles as herdrdocwatch, with `do-it` commands in place of Herdr's `doc` commands. Load the [[herdr]] skill for the CLI; never split your own pane.
195
+
196
+ - **Tester**: one tab in your workspace, started once, watching the queue itself:
197
+ ```bash
198
+ TAB=$(herdr tab create --workspace "$HERDR_WORKSPACE_ID" --cwd "$STATE" --label tester --no-focus)
199
+ PANE=$(jq -r .result.root_pane.pane_id <<<"$TAB")
200
+ herdr agent start do-tester --kind claude --pane "$PANE" -- --model claude-sonnet-5 --effort high --dangerously-skip-permissions
201
+ herdr agent prompt do-tester "$TESTER_BRIEF"
202
+ ```
203
+ Use the tester brief above, but instead of ending on an empty queue it keeps watching with `do-it watch <TESTS> --todos --as tester` (Monitor tool). Check `herdr agent list` first: reuse a live `do-tester` only when its cwd is this `$STATE`; on `agent_name_taken` pick `do-<SLUG first 4>-tester`.
204
+ - **Worker per task**: a Herdr worktree and space (see [[herdrworktree]], `--no-focus`), then a Claude architect in its root pane named `do-tN` (`claude-opus-5-5[1m]`, effort high, xhigh for L) that follows [[orchestration]]: it plans with `fable-advisor` (S, M) or a read only Astra tab (L), routes the typing to Codex lanes in herdr tabs, and gets a `fable-advisor` review before reporting done. Its brief is the worker brief above with `CWD: <worktree> BRANCH: <branch> BASE: <base branch> REPO RULES: read CLAUDE.md/AGENTS.md` in place of the REPO line, plus: "Talk to the conductor only through the inbox; answers arrive as prompts starting From the TODO. Wait for lanes with `herdr agent wait <lane> --timeout 1800000`, never by grepping a screen." Start and brief it as herdrdocwatch does:
205
+ ```bash
206
+ herdr agent start do-tN --kind claude --pane "$ROOT_PANE" -- --model 'claude-opus-5-5[1m]' --effort high --dangerously-skip-permissions
207
+ herdr agent prompt do-tN "$BRIEF" --wait --until working --timeout 20000
208
+ herdr workspace focus "$HERDR_WORKSPACE_ID" # if focus moved
209
+ ```
210
+ - **Answers** go to the architect as `herdr agent prompt do-tN "From the TODO: <their text>"`; it keeps working while it waits.
211
+ - **Parked architects**: when no inbox message came from a task for 30 minutes, read its screen (`herdr agent read do-tN --source recent-unwrapped --lines 80`) and its lanes'; if a lane finished and the architect still waits, prompt it to continue.
212
+
213
+ ## Step 5. React to events
214
+
215
+ | Event | Do |
216
+ | --- | --- |
217
+ | New task line | Step 3 |
218
+ | The person writes a note under a `listed` item, or edits its text | triage it now (Step 3) with their note as the instruction |
219
+ | The person adds a section whose text is an instruction ("all PRs in this section: ...") | a standing rule: apply it to every item moved or added into that section, as that item's instruction; an empty section waits |
220
+ | The person edits or adds notes under an active task | forward them: `SendMessage` to the worker (outside Herdr, once it has stopped) or `herdr agent prompt do-tN "From the TODO: ..."` |
221
+ | The person answers a question (an indented line under `**tN question:**`) | forward it the same way, then remove your question line |
222
+ | The person deletes a task, or writes "stop" under it | tell its worker to stop and commit its work in progress; status `stopped`, keep the worktree |
223
+ | The person unchecks a delivered task | their new note under it is a follow up for the same worktree and worker |
224
+ | Inbox `progress` | update the status line only, in a few words |
225
+ | Inbox `question` | add ` - **tN question:** <question>` under the task; status `waiting for you` |
226
+ | Inbox `blocked` or `failed`, or a worker ended without DONE | read what it said; fix the brief and resume it, or escalate a twice failed S or M task to Astra; tell the person only what they must decide |
227
+ | Worker DONE | verify (below), Fable review, write status `delivered`, then run `todo check` for the task |
228
+ | Tester BLOCKED or a long queue | one line under the affected task; never start a second tester |
229
+
230
+ **Verify before `delivered`.** A done message is not proof:
231
+
232
+ ```bash
233
+ git -C "<worktree>" log --oneline "<base>..HEAD"
234
+ git -C "<worktree>" diff --stat "<base>...HEAD"
235
+ ```
236
+
237
+ and the final request in `tests.md` says PASS for that commit. The delivered line reads:
238
+
239
+ ```
240
+ - **t3** delivered: branch `fix-sidebar-ports` (2 commits, a1b2c3d), tests t3r2 passed, Fable: ship. Worktree `.claude/worktrees/fix-sidebar-ports`
241
+ ```
242
+
243
+ Keep your lines short: the todo is a dashboard, not a log. Full detail lives in `plans/`, `logs/`, and the worktrees.
244
+
245
+ After writing the delivered status line, mark the task done with the version returned by that status edit:
246
+
247
+ ```bash
248
+ $D todo check "$TODO" --version $V --section tasks -- "<exact task text>"
249
+ ```
250
+
251
+ ## Ending
252
+
253
+ Run until the person says in chat to stop, or the todo goes away. On stop: stop the watches, tell every working worker to commit its work in progress and say where it stopped, leave the tester idle, write a final status line per open task, and finish in chat with Completed, Verification, Unresolved, and Retained (worktrees kept).
254
+
255
+ ## Rules
256
+
257
+ - **The todo is the interface.** Every event the person should know about lands in it.
258
+ - **One writer per channel role.** Only you write status into the todo; workers write only to the inbox and the test queue; only the tester answers test requests. Always through `do-it` commands naming the version.
259
+ - **One tester, one test at a time.** A worker caught running a build or test is stopped and reminded of the compute rule.
260
+ - **Three workers at most** unless the person writes otherwise in the todo. Each owns its worktree; no two writers share a checkout.
261
+ - **No outward actions by default.** Pushing, PRs, merges, deploys, and messages to other people happen only when the task line asks in words.
262
+ - **Never close what you did not create**, and keep every worktree holding unmerged work.
263
+ - **No dash separators** in lines you write into the todo: use commas, colons, or parentheses.
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
2
+ @layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.collapse{visibility:collapse}.absolute{position:absolute}.relative{position:relative}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.block{display:block}.hidden{display:none}.inline{display:inline}.table{display:table}.uppercase{text-transform:uppercase}}:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--pt-paper:#efe9b7;--pt-prose:#858266;--pt-ink:#000;--pt-resolved:#00000090;--pt-project:#bc644a;--pt-project-bg:#00000010;--pt-link:#003e7290;--pt-delimiter:#0004;--pt-selection:#00000029;--pt-active-row:#f7dc8688;--pt-marker-open:#0006;--pt-marker-done:#00723e;--pt-marker-cancelled:#b60101;--pt-tag:#a02e2b99;--pt-tag-resolved:#00000050;--pt-tag-today:#eadd4e;--pt-tag-high:#ff7f00;--pt-tag-low:#222;--pt-tag-critical:red;font-family:Menlo,Consolas,Liberation Mono,monospace}*{box-sizing:border-box}html,body{background:var(--pt-paper);min-width:320px;min-height:100%;color:var(--pt-ink);margin:0}body,button,input,textarea{font-family:Menlo,Consolas,Liberation Mono,monospace}body{font-size:17px;line-height:1.6}button,input,textarea{font-size:inherit}button{cursor:pointer}.pt-shell{background:var(--pt-paper);width:100%;height:100dvh;color:var(--pt-ink);font-variant-ligatures:none;font-feature-settings:"liga" 0, "clig" 0;grid-template-rows:40px minmax(0,1fr) 28px;font-size:17px;line-height:1.6;display:grid;overflow:hidden}.pt-header{border-bottom:1px solid var(--pt-delimiter);background:var(--pt-project-bg);align-items:center;min-width:0;padding:0 16px;font-size:13px;line-height:20px;display:flex}.pt-file-name{border:1px solid var(--pt-delimiter);border-bottom-color:var(--pt-paper);background:var(--pt-paper);min-width:0;max-width:min(52vw,520px);color:var(--pt-ink);text-overflow:ellipsis;white-space:nowrap;align-self:stretch;align-items:center;margin:0;padding:0 14px;font-size:13px;font-weight:400;line-height:38px;display:flex;overflow:hidden}.pt-header-actions{align-items:center;gap:18px;margin-left:auto;padding-left:20px;display:flex}.pt-header-button{min-height:28px;color:var(--pt-prose);background:0 0;border:0;padding:3px 0;font-size:13px;line-height:20px}.pt-header-key{border:1px solid var(--pt-delimiter);min-width:1.5em;color:var(--pt-prose);text-align:center;vertical-align:1px;margin-left:7px;padding:0 4px;font-size:11px;line-height:18px;display:inline-block}.pt-header-button:hover,.pt-header-button-active{color:var(--pt-ink)}.pt-header-button-active{background:var(--pt-project-bg);text-underline-offset:3px;text-decoration:underline;text-decoration-thickness:1px}.pt-workspace{background:var(--pt-paper);grid-template-rows:minmax(0,1fr);grid-template-columns:minmax(0,1fr);min-height:0;display:grid;overflow:hidden}.pt-workspace-with-activity{grid-template-rows:minmax(0,1fr) minmax(0,35%)}.pt-editor-host{background:var(--pt-paper);min-width:0;min-height:0;overflow:hidden}.pt-activity{border-top:1px solid var(--pt-delimiter);background:var(--pt-paper);min-width:0;min-height:0;color:var(--pt-prose);font-size:12px;line-height:18px;overflow:auto}.pt-activity-title{color:var(--pt-prose);letter-spacing:.12em;text-transform:uppercase;margin:0;padding:12px 14px 8px;font-size:11px;font-weight:700;line-height:16px}.pt-activity-list{margin:0;padding:0 14px 12px;list-style:none}.pt-activity-item{border-top:1px solid var(--pt-delimiter);padding:9px 0}.pt-activity-header{color:var(--pt-ink);font-size:12px;line-height:18px}.pt-activity-line,.pt-activity-empty{color:var(--pt-prose);font-size:12px;line-height:18px}.pt-activity-empty{margin:0;padding:0 14px 12px}.pt-status-bar{border-top:1px solid var(--pt-delimiter);background:var(--pt-project-bg);min-width:0;height:28px;color:var(--pt-prose);white-space:nowrap;grid-template-columns:minmax(max-content,1fr) auto minmax(max-content,1fr);align-items:center;padding:0 16px;font-size:13px;line-height:28px;display:grid}.pt-status-left,.pt-status-right{flex-shrink:0;align-items:center;gap:16px;min-width:max-content;display:flex;overflow:visible}.pt-status-right{font-variant-numeric:tabular-nums;grid-column:3;justify-content:flex-end}.pt-status-center{flex-shrink:1;grid-column:2;justify-content:center;justify-self:center;align-items:center;gap:14px;min-width:0;padding:0 16px;display:none;overflow:hidden}.pt-status-left{grid-column:1}.pt-hint{min-width:0;color:var(--pt-prose);flex-shrink:1;align-items:center;gap:5px;display:inline-flex}.pt-hint-key{border:1px solid var(--pt-delimiter);color:var(--pt-ink);padding:0 4px;font-size:11px;line-height:17px}.pt-hint-label{font-size:12px}.pt-status-item{text-overflow:ellipsis;overflow:hidden}.pt-status-saving{color:var(--pt-prose)}.pt-status-reconnecting{color:var(--pt-marker-cancelled)}.pt-notice{color:var(--pt-ink);text-overflow:ellipsis;overflow:hidden}.pt-palette-backdrop{z-index:20;background:0 0;position:fixed;inset:0}.pt-palette{border:1px solid var(--pt-delimiter);background:var(--pt-paper);width:min(600px,92vw);max-width:100%;color:var(--pt-ink);position:absolute;top:10vh;left:50%;overflow:hidden;transform:translate(-50%);box-shadow:0 12px 28px #00000029}.pt-palette-input{border:0;border-bottom:1px solid var(--pt-delimiter);width:100%;min-height:44px;color:var(--pt-ink);background:0 0;outline:0;padding:10px 12px;font-size:15px;line-height:22px;display:block}.pt-palette-input::placeholder{color:var(--pt-prose)}.pt-palette-list{max-height:50vh;margin:0;padding:4px 0;list-style:none;overflow:auto}.pt-palette-item{text-align:left;width:100%;min-width:0;color:var(--pt-ink);font:inherit;background:0 0;border:0;grid-template-columns:minmax(0,1fr) auto;gap:12px;padding:6px 12px;display:grid}.pt-palette-item-active{background:var(--pt-active-row)}.pt-palette-item>span:first-child{align-items:baseline;gap:12px;min-width:0;display:flex}.pt-palette-title,.pt-palette-detail{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.pt-palette-title{color:var(--pt-ink)}.pt-palette-detail{color:var(--pt-prose);font-size:12px}.pt-palette-keys{color:var(--pt-prose);justify-content:flex-end;align-self:center;align-items:center;gap:4px;display:flex}.pt-palette-key{border:1px solid var(--pt-delimiter);color:var(--pt-prose);padding:0 4px;font-size:11px;line-height:17px}.pt-palette-empty{color:var(--pt-prose);margin:0;padding:12px}.pt-palette>.pt-palette-detail{border-top:1px solid var(--pt-delimiter);white-space:normal;margin:0;padding:10px 12px 12px;line-height:18px}.pt-editor-host .cm-editor,.pt-editor-host .cm-scroller,.pt-editor-host .cm-content{font-variant-ligatures:none;font-feature-settings:"liga" 0, "clig" 0;font-family:Menlo,Consolas,Liberation Mono,monospace}.pt-editor-host .cm-editor{background:var(--pt-paper);height:100%;color:var(--pt-ink);font-size:17px;line-height:1.6}.pt-editor-host .cm-scroller{line-height:1.6;overflow:auto}.pt-editor-host .cm-content{--pt-content-inset:24px;min-height:100%;padding-block:28px 40px;padding-inline:var(--pt-content-inset) max(24px, calc(100% - 46rem - var(--pt-content-inset)));color:var(--pt-ink);white-space:pre-wrap;overflow-wrap:anywhere;caret-color:var(--pt-ink);line-height:1.6}.pt-editor-host .cm-line{min-height:1.6em;padding:0;line-height:1.6}.pt-editor-host .pt-hang{margin-left:calc(var(--pt-content-inset) * -1);padding-left:calc(var(--pt-hang) * 1ch + var(--pt-content-inset));text-indent:calc(var(--pt-hang) * -1ch)}.pt-editor-host .cm-cursor,.pt-editor-host .cm-dropCursor{border-left:2px solid var(--pt-ink)}.pt-editor-host .cm-activeLine{background:var(--pt-active-row)}.pt-editor-host .cm-selectionBackground,.pt-editor-host .cm-focused .cm-selectionBackground{background:var(--pt-selection)}.pt-editor-host .cm-content::selection{background:var(--pt-selection)}.pt-editor-host .cm-editor.cm-focused{outline:0}.pt-editor-host .cm-panels,.pt-editor-host .cm-search{border-color:var(--pt-delimiter);background:var(--pt-paper);color:var(--pt-ink);font-family:Menlo,Consolas,Liberation Mono,monospace;font-size:13px}.pt-editor-host .cm-panels-top{border-bottom:1px solid var(--pt-delimiter)}.pt-editor-host .cm-panels-bottom{border-top:1px solid var(--pt-delimiter)}.pt-editor-host .cm-search{align-items:center;gap:6px;padding:5px 8px;display:flex}.pt-editor-host .cm-panels input,.pt-editor-host .cm-search input{border:1px solid var(--pt-delimiter);background:var(--pt-paper);min-width:12em;color:var(--pt-ink);outline:0;padding:2px 4px;font:13px/20px Menlo,Consolas,Liberation Mono,monospace}.pt-editor-host .cm-panels input:focus,.pt-editor-host .cm-search input:focus{border-color:var(--pt-ink)}.pt-editor-host .cm-button{border:1px solid var(--pt-delimiter);background:var(--pt-project-bg);color:var(--pt-ink);padding:2px 6px;font:12px/18px Menlo,Consolas,Liberation Mono,monospace}.pt-editor-host .cm-button:hover{border-color:var(--pt-ink);background:var(--pt-paper)}.pt-editor-host .pt-line-project{color:var(--pt-project);font-weight:700}.pt-editor-host .pt-line-project.pt-level-1{font-size:1.6em;line-height:1.45}.pt-editor-host .pt-line-project.pt-level-2{font-size:1.35em;line-height:1.45}.pt-editor-host .pt-line-project.pt-level-3{font-size:1.18em;line-height:1.5}.pt-editor-host .pt-line-project.pt-level-4,.pt-editor-host .pt-line-project.pt-level-5,.pt-editor-host .pt-line-project.pt-level-6{font-size:1.05em;line-height:1.55}.pt-editor-host .pt-heading-title{background:var(--pt-project-bg);box-shadow:2px 0 0 var(--pt-project-bg), -2px 0 0 var(--pt-project-bg);color:var(--pt-project)}.pt-editor-host .pt-heading-marks,.pt-editor-host .pt-bullet,.pt-editor-host .pt-bullet-hidden,.pt-editor-host .pt-strong-mark,.pt-editor-host .pt-em-mark,.pt-editor-host .pt-strike-mark,.pt-editor-host .pt-code-mark,.pt-editor-host .pt-link-mark,.pt-editor-host .pt-line-rule{color:var(--pt-delimiter)}.pt-editor-host .pt-bullet-hidden{color:#0000}.pt-editor-host .pt-line-editing .pt-strong-mark,.pt-editor-host .pt-line-editing .pt-em-mark,.pt-editor-host .pt-line-editing .pt-strike-mark,.pt-editor-host .pt-line-editing .pt-code-mark,.pt-editor-host .pt-line-editing .pt-link-mark{color:var(--pt-delimiter)}.pt-editor-host .pt-line-task,.pt-editor-host .pt-line-task-open,.pt-editor-host .pt-line-task-open .pt-label{color:var(--pt-ink)}.pt-editor-host .pt-line-task-done .pt-label,.pt-editor-host .pt-line-task-cancelled .pt-label{color:var(--pt-resolved);font-style:italic;text-decoration:none}.pt-editor-host .pt-line-status,.pt-editor-host .pt-line-note,.pt-editor-host .pt-line-prose,.pt-editor-host .pt-line-quote{color:var(--pt-prose)}.pt-editor-host .pt-strong{color:inherit;font-weight:700}.pt-editor-host .pt-em{color:inherit;font-style:italic}.pt-editor-host .pt-strike{color:inherit;text-decoration:line-through;text-decoration-thickness:1px}.pt-editor-host .pt-code{background:var(--pt-project-bg);color:inherit;font-size:.94em}.pt-editor-host .pt-link{color:var(--pt-link);text-underline-offset:2px;text-decoration:underline;text-decoration-thickness:1px}.pt-editor-host .pt-tag{color:var(--pt-tag);font-weight:700}.pt-editor-host .pt-tag-today,.pt-editor-host .pt-tag-high,.pt-editor-host .pt-tag-low,.pt-editor-host .pt-tag-critical{background:var(--pt-tag-today);color:var(--pt-ink);font-weight:700}.pt-editor-host .pt-tag-high{background:var(--pt-tag-high)}.pt-editor-host .pt-tag-low{background:var(--pt-tag-low);color:#fff}.pt-editor-host .pt-tag-critical{background:var(--pt-tag-critical)}.pt-editor-host .pt-tag-done,.pt-editor-host .pt-tag-cancelled{color:var(--pt-tag-resolved);font-weight:400}.pt-editor-host .pt-tag-project,.pt-editor-host .pt-tag-started{color:var(--pt-tag);font-weight:700}.pt-editor-host .pt-bullet-dot{color:var(--pt-prose);text-indent:0;white-space:nowrap}.pt-editor-host .pt-line-code{background:var(--pt-project-bg);color:var(--pt-ink)}.pt-editor-host .pt-line-archived{opacity:.7}.pt-editor-host .pt-marker{cursor:pointer;text-align:center;text-indent:0;white-space:nowrap;width:3ch;display:inline-block}.pt-editor-host .pt-marker-symbol{font-family:Apple Symbols,Segoe UI Symbol,DejaVu Sans,Menlo,sans-serif;font-size:1.15em;line-height:1}.pt-editor-host .pt-marker-open,.pt-editor-host .pt-marker-empty{color:var(--pt-marker-open);font-weight:400}.pt-editor-host .pt-marker-done{color:var(--pt-marker-done);font-weight:700}.pt-editor-host .pt-marker-cancelled{color:var(--pt-marker-cancelled);font-weight:700}.pt-editor-host .cm-tooltip.pt-link-popover{border:1px solid var(--pt-delimiter);background:var(--pt-paper);width:min(360px,86vw);color:var(--pt-ink);text-indent:0;gap:8px;padding:10px 12px;font-family:Menlo,Consolas,Liberation Mono,monospace;font-size:13px;line-height:18px;display:grid;box-shadow:0 12px 28px #00000029}.pt-link-popover-field{grid-template-columns:4ch minmax(0,1fr);align-items:center;gap:8px;display:grid}.pt-link-popover-caption{color:var(--pt-prose);font-size:12px}.pt-link-popover-input{border:1px solid var(--pt-delimiter);min-width:0;color:var(--pt-ink);font:inherit;background:0 0;outline:0;padding:4px 6px}.pt-link-popover-input:focus{border-color:var(--pt-link)}.pt-link-popover-input::placeholder{color:var(--pt-prose)}.pt-link-popover-actions{justify-content:flex-end;gap:6px;display:flex}.pt-link-popover-button{border:1px solid var(--pt-delimiter);color:var(--pt-ink);font:inherit;cursor:pointer;background:0 0;padding:2px 8px}.pt-link-popover-button[type=submit]{background:var(--pt-active-row)}.pt-link-popover-button:hover,.pt-link-popover-button:focus-visible{border-color:var(--pt-ink)}.pt-editor-host .pt-remote-highlight{animation:3s ease-out forwards pt-remote-highlight}@keyframes pt-remote-highlight{0%{background:#f7dc86}to{background:0 0}}.empty-shell,.loading-shell,.message-shell{background:var(--pt-paper);min-height:100dvh;color:var(--pt-ink);align-content:center;justify-items:start;gap:12px;margin:0;padding:10vw;display:grid}.empty-mark,.eyebrow{color:var(--pt-delimiter);letter-spacing:.12em;text-transform:uppercase;font-size:12px;font-weight:700;line-height:18px}.empty-title,.loading-title,.message-title{max-width:28ch;color:var(--pt-ink);margin:0;font-family:Menlo,Consolas,Liberation Mono,monospace;font-size:clamp(1.5rem,4vw,2.6rem);font-weight:700;line-height:1.2}.empty-copy,.loading-copy{max-width:48rem;color:var(--pt-prose);margin:0;font-size:14px;line-height:24px}.message-title{max-width:44ch;font-size:clamp(1.25rem,3vw,2rem)}.file-name{color:var(--pt-ink);margin:0;font-family:Menlo,Consolas,Liberation Mono,monospace;font-size:15px;font-weight:700;line-height:24px}.file-path{overflow-wrap:anywhere;color:var(--pt-prose);font-size:12px;line-height:18px}.connection-status{color:var(--pt-prose);font-size:12px;line-height:18px}.connection-deleted{color:var(--pt-resolved)}.connection-reconnecting{color:var(--pt-marker-cancelled)}@media (width>=900px){.pt-workspace-with-activity{grid-template-rows:minmax(0,1fr);grid-template-columns:minmax(0,1fr) 280px}.pt-activity{border-top:0;border-left:1px solid var(--pt-delimiter)}}@media (width>=1100px){.pt-status-center{display:flex}}@media (prefers-reduced-motion:reduce){.pt-editor-host .pt-remote-highlight{background:#f7dc86;animation:none}}@media (forced-colors:active){.pt-editor-host .pt-bullet-hidden{color:#0000}.pt-editor-host .pt-marker{color:canvastext}}