diff --git a/marketing/drafts/agent-done-signal/copy.md b/marketing/drafts/agent-done-signal/copy.md new file mode 100644 index 0000000..06954b4 --- /dev/null +++ b/marketing/drafts/agent-done-signal/copy.md @@ -0,0 +1,87 @@ +# How do you know when your coding agent is done? + +> **Status: draft — not approved, not published.** Sponsors fact-check the claims +> table at the bottom; the page moves `pending/` → `approved/` only after that. +> This page never names a product of ours and never names a competitor. +> Internal target: first page of the FRE-199 pair, Thu 2026-11-06. + +Often, you don't — not from the terminal alone. A coding agent's turn can end in +silence: the prompt returns, the cursor blinks, and a finished turn looks exactly +like one that stalled, is still running, or is waiting on you. The fix is to stop +trusting silence and wire the two moments that matter — *the turn ended* and *the +agent needs you* — to something you will actually see. + +## Why silence is the failure mode + +A terminal coding agent ends a turn by printing a prompt. If you are in another +window, another room, or running several agents at once, nothing in that output +distinguishes "finished" from "blocked on a permission prompt" from "dead". The +task being done and you finding out are two different events, and the second one +has no default signal. + +Practitioners keep rediscovering this. One operator running a self-hosted queue +of autonomous agent sessions described sessions that "finished their work but +never sent the done signal, and held their slots for hours" — their fix was to +derive "done" from git state plus an idle transcript instead of trusting the +agent's own signal. A public service post about a code-review plugin described +the mirror image: a green checkmark and "No findings" when the review had not +run at all. An empty result and a successful result rendered identically. + +That is the trap in one sentence: **zero looks exactly like success.** + +## What the turn-ending signal actually is + +Claude Code gives you two hooks that bracket the moments worth surfacing: + +- **`Stop`** fires when the agent finishes responding — the end of a turn. +- **`Notification`** fires when Claude Code sends a notification. A permission + prompt is one of these: the hook's payload carries a `notification_type` of + `permission_prompt` and a message like "Claude needs your permission". +- **`StopFailure`** fires instead of `Stop` when the turn ends on an API error — + rate limits, authentication problems, and the like. + +All three can run a command of your choosing. The hooks reference documents the +events and includes a desktop-notification example built on macOS's `osascript`. + +## What to check or do + +1. **Wire turn-end to a notification you will actually notice.** A `Stop` hook + that calls `osascript -e 'display notification …'` (or your terminal's + notification escape) turns the silent prompt-return into a visible event. + A terminal bell is not this — it is mute the moment you switch windows. +2. **Route permission waits separately from completions.** The `Notification` + hook's payload tells you which kind it is. A permission wait means the agent + is *blocked on you*; treating it as "done" hides the one state that costs the + most time. +3. **Don't trust the exit signal alone.** Check the artifacts: `git status`, + `git log`, whether the transcript has gone idle. The queue operator's rule + generalises — a "done" that has to name what it is waiting on is a "done" + you can act on. +4. **Surface the failure path too.** A turn that ends on an API error fires + `StopFailure`, not `Stop` — an alert wired to the wrong one misses exactly + the runs that need attention. + +One next step: take the agent command you run most often and give its end-of-turn +a notification you would notice from across the room. That single wire closes the +most expensive silence in the workflow. + +--- + +## Fact-check table (not part of the page) + +Every technical claim above, with its primary source. Claims about Claude Code's +behaviour come from its own documentation, re-read 2026-11-05. + +| # | Claim in the page | Source | +|---|---|---| +| 1 | `Stop` fires when the agent finishes responding (end of a turn); hook cadence is "per turn: UserPromptSubmit, Stop, StopFailure" | Claude Code hooks reference — https://docs.anthropic.com/en/docs/claude-code/hooks | +| 2 | `Notification` fires "when Claude Code sends a notification"; example payload carries `notification_type: "permission_prompt"`, message "Claude needs your permission" | same hooks reference (Notification event section) | +| 3 | `StopFailure` "runs instead of Stop when the turn ends due to an API error" (rate limits, authentication) | same hooks reference (StopFailure section) | +| 4 | Hooks run a command of your choosing; a desktop-notification example using `osascript` is in the reference | same hooks reference (desktop notification example) | +| 5 | Operator anecdote: sessions that finished work but never signalled done, holding slots for hours; fix = derive done from git + idle transcript | r/ClaudeCode thread 1xjb3j0 ("Are you running a self-hosted queue of autonomous Claude Code sessions?", 2026-10-31), quoted in `drafts/listening.md` Scan 4 addendum. Quoted as one operator's described practice, not a measurement. | +| 6 | PSA anecdote: code-review plugin showed green check + "No findings" without running | r/ClaudeCode 1xmnz2c (2026-11-03), logged in `drafts/listening.md` Scan 6. | +| 7 | "Zero looks exactly like success" | Verbatim buyer phrasing, three independent instances (1xm09fs, 1xmnz2c, plus HN repeats) in `drafts/listening.md` Scans 5–8. Used as the problem's name, attributed to no one. | + +**Ban compliance:** no product of ours named · no competitor named · no +superlatives · no benchmark numbers · no invented testimonials (anecdotes are +real threads, described without handles) · no price · no roadmap dates. diff --git a/marketing/drafts/agent-done-signal/rationale.md b/marketing/drafts/agent-done-signal/rationale.md new file mode 100644 index 0000000..e05fcd8 --- /dev/null +++ b/marketing/drafts/agent-done-signal/rationale.md @@ -0,0 +1,72 @@ +# Rationale — "How do you know when your coding agent is done?" + +FRE-199 item 1, page 1 of the first pair. Drafted 2026-11-05 by CMO. + +## The phrase + +Primary: **"how do you know when your coding agent is done"** (variants: "agent +finished silently", "claude code waiting for permission" overlaps on the +blocked-half; this page owns the *done*-half). + +Chosen by the FRE-199 selection rule: strongest buying intent we can answer +honestly without naming a product. It is on the standing phrase list +(`drafts/listening.md` §The phrase list: "how do I know when my agent is done"). + +## Why this phrase won the slot + +- **Recurrence with independence.** The "zero looks exactly like success" + pattern appears in at least four separate sources across Scans 5–9: 1xm09fs, + the code-review PSA (1xmnz2c), and two HN commenters (fhub, sadilek), plus + the queue operator's done-signal workaround (1xjb3j0). Four independent + formulations of one pain in seven days is the strongest recurrence the + backlog shows. +- **Buying intent.** The people describing it are running agents unattended + right now and are losing time to the gap — they are past curiosity. +- **Answerable honestly, generically.** The mechanism (Stop / Notification / + StopFailure hooks) is documented in the agent's own reference; every claim in + the page traces to it. Nothing about our product is needed to answer it. +- **Wedge-aligned.** "An agent blocked is the most expensive kind of idle" — + the done-half of that sentence (idle you never learn about) is this page. + +## Evidence trail + +| Thread | Date | What it showed | +|---|---|---| +| r/ClaudeCode 1xjb3j0 — "self-hosted queue of autonomous Claude Code sessions" | 2026-10-31 | Sessions "finished their work but never sent the done signal, and held their slots for hours"; operator derives done from git + idle transcript; "a waiting one has to name what it's waiting on" | +| r/ClaudeCode 1xm09fs | 2026-11-02 | First "zero looks exactly like success" instance (verbatim buyer phrasing) | +| r/ClaudeCode 1xmnz2c — code-review plugin PSA | 2026-11-03 | Green check + "No findings" when the review never ran; third independent instance | +| HN comments (fhub, sadilek) | 2026-11-04/05 | Human-attention concurrency ceiling quantified twice more | + +All rows live in `drafts/listening.md` (The-Nook local master line, single +canonical copy per FRE-748) with URLs and verbatim quotes. + +## Gates before this page ships + +1. **Sponsor fact-check** of the claims table in `copy.md` (owner: Michael + Freno). Page moves `pending/` → `approved/` on his read, per the marketing + tree's hard rule. +2. **CTO eyes on the agent-behaviour claims** — all four are sourced to the + Claude Code hooks reference re-read 2026-11-05, but anything asserted about + an agent's behaviour is CTO-verifyable, and the FRE-199 plan routes it to + him. +3. **Publish path:** `pending/` → `approved/` → a human places it on + nook.freno.me (blog route). Nothing posts itself. + +## Ban compliance (FRE-199 + positioning.md rule 1) + +- The Nook: not named. The notch, the island, the companion: not mentioned. +- Competitors (notch apps, agent monitors, Remote Control–style tools): not + named. Remote Control is not mentioned either — the page answers the done-half + without touching the away-from-desk half. +- Claude Code is named only as the subject whose documented behaviour the page + explains, with its own docs as the source — the same status the listening + phrase list already gives it. It is the agent, not a competitor. +- No superlatives, no benchmark numbers, no invented testimonials, no price, + no roadmap dates. + +## Cadence note + +This page and `agent-waiting-on-permission/` are the first pair. The queue +behind them (multiple-agents tracking, invisible-permission cluster) holds well +above the three-candidate floor, so the two-a-week cadence holds without +inventing phrases. diff --git a/marketing/drafts/agent-waiting-on-permission/copy.md b/marketing/drafts/agent-waiting-on-permission/copy.md new file mode 100644 index 0000000..3d9af33 --- /dev/null +++ b/marketing/drafts/agent-waiting-on-permission/copy.md @@ -0,0 +1,81 @@ +# Why is my coding agent sitting on a permission prompt? + +> **Status: draft — not approved, not published.** Sponsors fact-check the claims +> table at the bottom; the page moves `pending/` → `approved/` only after that. +> This page never names a product of ours and never names a competitor. +> Internal target: second page of the FRE-199 pair, Fri 2026-11-07. + +Because it tried to do something its permission settings don't allow, and the +default is to wait — indefinitely and quietly — for you. The prompt is not the +expensive part; the hour you spent not knowing it was waiting is. The way out is +not to approve faster, it's to make the prompts rare and the waiting visible. + +## The mechanism + +Claude Code's permission system decides, per tool call, whether to run, refuse, +or stop and ask. In its `default` mode, it prompts for permission on the first +use of each tool. Modes are set with `defaultMode` in the settings files, and a +session's rules come from allow / ask / deny lists evaluated in that order — +the first match wins. + +You can see the whole rule set at any time with `/permissions`, which lists +every permission rule and the settings file each one came from. Rules can name +a specific use — `Bash(npm run build)` matches exactly that command — or a +wildcard, like `Bash(git log *)`. + +So the prompt you came back to an hour later is not a malfunction. It is the +system working as configured, on a call your rules never covered — and the +"waiting" state being invisible is what turned ten seconds of approval into a +lost hour. + +## What to check or do + +1. **Read the prompt before automating it away.** It names the tool and the + input. The right response to "it keeps asking" is usually a rule, not a + wider mode. +2. **Allowlist the undoable, prompt on the irreversible.** Reads, tests, and + status commands are safe to allow — `git` is the undo for edits. Anything + that reaches another person or another system — network calls, deletes, + deploys — is worth keeping on ask. Rule syntax is in the permission docs; + `/permissions` shows what you already have. +3. **Consider `acceptEdits` before anything broader.** It auto-accepts file + edits and common filesystem commands inside the working directory. That is + usually the difference between ten prompts a session and two — without + handing over network or delete. +4. **Bound the blast radius instead of removing the gate.** If you do widen + what runs unattended, do it where a mistake is recoverable: a worktree per + task, commits pushed early, nothing irreversible in reach. Operators who run + agents unattended describe exactly this split — free hand on what git can + undo, confirmation on what it can't. +5. **Make the wait visible.** Claude Code fires a `Notification` hook when it + sends a notification, and a permission prompt is one — the payload carries a + `notification_type` of `permission_prompt`. A hook on that event, wired to a + desktop notification you'd see from another window, turns the silent wait + back into a ten-second approval. + +One next step: run `/permissions` today and add allow rules for the three +commands you find yourself approving most. The prompts that remain will be the +ones that deserve a read. + +--- + +## Fact-check table (not part of the page) + +Every technical claim above, with its primary source. Claims about Claude +Code's behaviour come from its own documentation, re-read 2026-11-05. + +| # | Claim in the page | Source | +|---|---|---| +| 1 | In `default` mode Claude Code "prompts for permission on first use of each tool" | Claude Code permissions doc — https://docs.anthropic.com/en/docs/claude-code/permissions (Permission modes table) | +| 2 | `defaultMode` in settings files sets the default mode for new sessions | same permissions doc (Permission modes section) | +| 3 | Rules are evaluated deny → ask → allow, first match wins | same permissions doc (Permission rule syntax) | +| 4 | `/permissions` lists all permission rules and the settings.json each comes from | same permissions doc (Manage permissions) | +| 5 | `Bash(npm run build)` matches the exact command; `Bash(git log *)` wildcard form | same permissions doc (Use specifiers for fine-grained control) | +| 6 | `acceptEdits` "automatically accepts file edits and common filesystem commands such as mkdir, touch, mv, cp for paths in the working directory" | same permissions doc (Permission modes table) | +| 7 | A `Notification` hook fires when Claude Code sends a notification; permission prompts carry `notification_type: "permission_prompt"` and a message like "Claude needs your permission" | Claude Code hooks reference — https://docs.anthropic.com/en/docs/claude-code/hooks (Notification event) | +| 8 | Undo-split practice ("free hand on what git can undo, confirmation on what it can't") | r/ClaudeCode 1xkoz06 (2026-10-31, u/tomm3hshipp thread), commenter's described practice, logged in `drafts/listening.md` Scan 3 addendum. Described as one operator's approach, not a rule. | +| 9 | The 55-minutes-lost framing | r/ClaudeAI 1xhbc71 (2026-10-28): "coming back an hour later to find it's been sitting on a permission prompt for 55 minutes". Used as the problem's shape, not quoted as a person. | + +**Ban compliance:** no product of ours named · no competitor named · no +superlatives · no benchmark numbers · no invented testimonials · no price · no +roadmap dates. diff --git a/marketing/drafts/agent-waiting-on-permission/rationale.md b/marketing/drafts/agent-waiting-on-permission/rationale.md new file mode 100644 index 0000000..7b8730b --- /dev/null +++ b/marketing/drafts/agent-waiting-on-permission/rationale.md @@ -0,0 +1,77 @@ +# Rationale — "Why is my coding agent sitting on a permission prompt?" + +FRE-199 item 1, page 2 of the first pair. Drafted 2026-11-05 by CMO. + +## The phrase + +Primary: **"claude code waiting for permission"** and the away-from-desk variant +("approvals when you're away from the computer"). First phrase on the standing +list (`drafts/listening.md` §The phrase list). + +## Why this phrase won the slot + +- **The strongest single thread in the backlog.** r/ClaudeAI 1xhbc71 (2026-10-28, + 47 comments and moving) asks the buying question outright: kicked off a long + task, came back an hour later, agent had been sitting on a permission prompt + for 55 minutes. The thread's own answers (remote control, tmux+SSH, + skip-permissions, allowlists) prove demand; none of them makes the wait + visible at the machine — that is the honest gap this page answers without + naming anyone. +- **The week's objection vocabulary.** Scans 1–9 keep returning "the model keeps + handing control back" and "stops and waits for me" — permission friction is + the category's core complaint, not a niche one. +- **Recurring independent accounts.** The invisible-permission theme has three + independent accounts in one week (1xksutq — gh used without a visible prompt; + 1xkejsp's Linux panel; the scheduled-tasks silent-stall finding), so the + search demand is not one loud thread. +- **Wedge-aligned.** This is the literal wedge sentence's territory — "an agent + blocked on a permission prompt is the most expensive kind of idle" — answered + with the agent's own documented mechanism. + +## Deliberate scoping + +This page owns the **blocked-half** of the approval problem (why prompts happen, +how to make them rare, how to make the wait visible at the machine). The +**away-half** (controlling a remote agent from elsewhere) is a different phrase, +a different page, and one where the honest answer is dominated by the agent +vendor's own remote feature — the page deliberately does not go there +(`drafts/listening.md` Scan 1 category intel #1). + +## Evidence trail + +| Thread | Date | What it showed | +|---|---|---| +| r/ClaudeAI 1xhbc71 — "How do you handle Claude Code approvals when you're away from your computer?" | 2026-10-28 | 55-minute wait on a permission prompt; 47 comments of demand; "what's still annoying about your setup?" | +| r/ClaudeCode 1xkoz06 — "How permissive are you with AI and for how long?" | 2026-10-31 | The undo-split: "file edits, tests and branches get a free hand, since git is the undo. Anything that reaches another person … stays on confirm" | +| r/ClaudeCode 1xksutq — gh used without visible prompt | 2026-11-01 | Third independent invisible-permission account of the week | +| r/ClaudeCode 1xkejsp — Linux panel app | 2026-10-31 | Per-session "Needs You" differentiation shipping elsewhere; the need is real and cross-platform | + +All rows live in `drafts/listening.md` with URLs and verbatim quotes. + +## Gates before this page ships + +1. **Sponsor fact-check** of the claims table in `copy.md` (owner: Michael + Freno); page moves `pending/` → `approved/` on his read. +2. **CTO eyes on the agent-behaviour claims** — all eight doc-sourced claims + re-read 2026-11-05; the FRE-199 plan routes anything asserted about an + agent's behaviour to the CTO. +3. **Publish path:** `pending/` → `approved/` → a human places it on + nook.freno.me (blog route). Nothing posts itself. + +## Ban compliance (FRE-199 + positioning.md rule 1) + +- The Nook: not named; notch/island/companion not mentioned. +- Competitors: not named — including the agent vendor's remote feature, which + the page never needs to mention because it stays on the at-the-machine half. +- Claude Code is named only as the subject whose documented permission system + the page explains, with its own docs as the source — same status the + listening phrase list already gives it. +- No superlatives, no benchmark numbers, no invented testimonials, no price, + no roadmap dates. + +## Cadence note + +Second page of the first pair. Queue behind it: multi-agent tracking ("How do +you keep track of multiple coding agents running in parallel?", 1xm6frp, +2026-11-03) and the invisible-permission cluster — the queue holds above the +three-candidate floor, so the two-a-week cadence holds. diff --git a/marketing/drafts/newsletter-postmortem-pitch/copy.md b/marketing/drafts/newsletter-postmortem-pitch/copy.md new file mode 100644 index 0000000..f3d7747 --- /dev/null +++ b/marketing/drafts/newsletter-postmortem-pitch/copy.md @@ -0,0 +1,82 @@ +# Newsletter pitch — post-mortem shape (placeholders; numbers gated) + +> **Status: draft — placeholders only. No figure in this file is a measurement.** +> FRE-199 item 2. Drafted 2026-11-05 by CMO; the plan's date was Fri 2026-11-06. +> **Send gate:** no figure ships until FRE-202 (weekly metrics job) or a direct +> read of the relay store provides it **and** the CTO confirms the query. Paid +> placements stay out (TLDR ≈ $3k/placement, no verifiable CPC to buy against). + +## Audience & channel + +Editors of free dev-tool newsletters (the ones that run post-mortems and +"what we learned" pieces). Direct email, one editor at a time, personalised. +No paid placements at any budget without a CoS + sponsor decision. + +## The claim the pitch goes out with + +A post-mortem pitch, not a product pitch: *here is what shipping a Mac utility +alone actually broke, and what we changed because of it.* The product is the +setting; the breakage and the fix are the story. + +## The pitch (shape — every figure is a placeholder) + +**Subject:** What shipping a Mac utility alone broke (post-mortem) + +Hi , + +We build The Nook, a $10 Mac utility that surfaces coding-agent approvals at +the notch. I'm not pitching the app — I'm offering a post-mortem your readers +usually only get from funded startups, because shipping alone broke things in +ways bigger teams don't hit: + +- **The silent update.** In October we shipped a release whose appcast published + cleanly — while every delta it named 404'd, so users on older builds were + being offered updates that didn't exist. The publish path deleted files + before the feed that named them was live. Nothing alerted; the feed just + lied quietly. (Documented in our own changelog discipline: the fix — upload + the feed's enclosures, verify every URL, *then* prune — is now ordered so + the deletion can't run first.) +- **[PLACEHOLDER — second breakage: the launch-incident story with a real + number attached. Candidates from the engineering journal: the 0.13.x + appcast-item loss (changelog blanking on prune), or the relay regression + that shipped behind a passing suite. Pick the one FRE-202's data can + quantify.]** +- **The numbers, as they are.** activations and % trial→paid as of + — small numbers, real ones, and the interesting part is the funnel + shape, not the size. + +The angle for your readers: solo distribution is a chain of quiet failure +modes, each one invisible until it costs a user. We kept the receipts. + +Happy to send the full write-up, screenshots of the broken feed, and the +exact publish-order change. + +— , FrenoCorp + +## Where the numbers come from (and the caveats that travel with them) + +- **Preferred source:** FRE-202, the weekly metrics job (CTO owns the query). +- **Fallback:** a direct read of the relay store — `installs` (one row per + activated install, `created_at`) for activations; `admissions` + (`license_id` non-empty = licensed, empty = trial) for the trial→paid split. +- **Caveats that go in the pitch, not a footnote:** + - a conversion figure is per *install* (install cap is 3), not per person; + - DMG downloads (S3 side) and activations (relay store) are two different + numbers — the pitch says which one it quotes; + - "1,900 downloads, 6% trial→paid" is the *shape* of a pitch, never a figure + we hold. No number is estimated to fill a placeholder. + +## Gates before anything is sent + +1. Figures exist (FRE-202 or CTO-confirmed direct read) — owner: CTO. +2. CTO confirms the query behind every figure quoted — owner: CTO. +3. Sponsor approves the send and holds the sending account (humans hold every + account) — owner: Michael Freno. +4. The second breakage paragraph is fact-checked against the engineering + journal before send — owner: CMO, evidence to CTO for verdict. + +## Target dates (internal) + +- Draft with placeholders: **done 2026-11-05** (plan date was 2026-11-06). +- Figures dropped in: when FRE-202 or the direct read exists — no date promised. +- Send: only after gates 1–4. Sponsor submits. diff --git a/marketing/drafts/newsletter-postmortem-pitch/rationale.md b/marketing/drafts/newsletter-postmortem-pitch/rationale.md new file mode 100644 index 0000000..a6a6a82 --- /dev/null +++ b/marketing/drafts/newsletter-postmortem-pitch/rationale.md @@ -0,0 +1,49 @@ +# Rationale — newsletter post-mortem pitch (shape) + +FRE-199 item 2. Drafted 2026-11-05 by CMO (plan date was 2026-11-06; FRE-201 +landed today, which was the only gate on drafting the shape). + +## Why draft now + +The Chief of Staff's sequencing had the pitch drafted when FRE-201 landed. It +landed 2026-11-05 (row closed `done` 18:45Z; the daily scan routine +`2553b201` has been producing the backlog since 2026-10-30). The figures were +never gated on FRE-201 — only the shape was — so the shape ships now and the +figures stay placeholders behind their own gate. + +## Why a post-mortem and not a product pitch + +The issue text's own thesis: "1,900 downloads, 6% trial→paid, here's what +broke" outperforms a product pitch. Editors of free dev-tool newsletters run +post-mortems; a solo shop shipping a Mac utility and keeping receipts is a +story they can run without us asking for a review. + +## The breakage is real, not invented + +The lead paragraph is the 0.13.4 delta incident (FRE-542): the appcast stayed +at 0.13.4 while its five delta files 404'd — the publish path pruned before +the feed was up. The fix (upload enclosures, verify URLs, copy the appcast, +then prune) is in `scripts/upload-release.sh` and is engineering-verified by +the FRE-542 record. The second breakage paragraph is a named placeholder with +two candidate incidents — it stays a placeholder until one can carry a real +number. + +## Hard rules honoured + +- Every figure is `[PLACEHOLDER]` and labelled as such; the file says in its + header that no figure in it is a measurement. +- No invented number, no estimated conversion, no user counts. +- The two caveats (per-install conversion with install cap 3; downloads ≠ + activations) are written to travel inside the pitch, not a footnote. +- Paid placements: out, per the issue text and the plan (TLDR ≈ $3k, no + verifiable CPC). No placement is bought without CoS + sponsor. +- Price appears once ($10, what the app actually charges) to identify the + product — no discount, no countdown, no price-change copy (FRE-204 holds). + +## Gates before send + +1. Figures from FRE-202 or a CTO-confirmed direct relay-store read — CTO. +2. CTO confirms the query behind every figure — CTO. +3. Sponsor approves the send; a human holds the account and sends — sponsor. +4. Second-breakage paragraph fact-checked against the journal — CMO drafts, + CTO verifies.