#+TITLE: Cross-Project Broadcast Workflow #+AUTHOR: Craig Jennings & Claude #+DATE: 2026-05-29 * Overview Fan out a single message to every AI project's inbox in one operation. Discovers projects by fingerprint (any directory with =.ai/protocols.org=) and delivers via the existing =inbox-send.py= per-target. The point is announcing a new capability or shared change once, instead of hand-walking 20+ projects. * When to Use This Workflow User triggers: - "broadcast this to every project" - "notify every project about " - "fan out this announcement" - "let every project know X is available" Automatic invocation: - *New machine-global capability landed.* A new script in =~/.local/bin/=, a new MCP server registered, a new tool installed (e.g. =signal-cli=, =page-signal=). Projects need to know it's available so their agents can use it. - *Shared rule or protocol change.* When a change to =claude-rules/= or =claude-templates/.ai/= materially affects how every project's agent should behave, broadcast a heads-up so the next session of each project picks it up explicitly rather than discovering it on rsync. - *Deprecation notice.* When a script, workflow, or rule is going away, give every project a chance to migrate before the removal lands. * When NOT to Use This Workflow - *Project-specific work.* A handoff intended for one project goes through =inbox-send= directly, not broadcast. - *Routine status updates.* The session log and todo.org cover routine work. Broadcast is for capability- or rule-level changes. - *Bulk noise.* Every broadcast adds N inbox files. Use sparingly; ask whether projects actually need to know. * The Workflow ** Phase A — Discover targets Run the discovery helper: #+begin_src bash python3 .ai/scripts/cross-project-broadcast.py --list #+end_src The helper scans =~/code/=, =~/projects/=, =~/.emacs.d= for any directory containing =.ai/protocols.org=. Prints the basename and full path of each, in sender-excluded order (the current project never receives its own broadcast). ** Phase B — Compose the message Write the broadcast body to =/tmp/broadcast-.org=. Required structure: #+begin_example ,#+TITLE: ,#+DATE: YYYY-MM-DD ,#+SOURCE: ,* What's new ,* How to use it ,* Why this matters / when to use ,* Action required - =FYI=, no action required (most broadcasts) - =Update workflow X= to reference the new capability - =Deprecate workflow Y= by date Z #+end_example The structure is rigid on purpose. Every project's next session has to read 20+ broadcasts as efficiently as possible. The standard headings let the agent scan in seconds. ** Phase C — Confirm scope with the user Surface the discovered project list and the message inline. Ask: #+begin_example Broadcast scope: - Target projects: (list) - Message: <2-line summary> - Action required: 1. Send to all targets (recommended) 2. Exclude specific projects (name them) 3. Cancel — message stays at /tmp/broadcast-.org #+end_example ** Phase D — Fan out Run the broadcast helper with the composed message: #+begin_src bash python3 .ai/scripts/cross-project-broadcast.py \ --file /tmp/broadcast-.org \ [--exclude project1 --exclude project2 ...] #+end_src The helper iterates over targets, runs =inbox-send.py --file = per target, captures success/failure per project. The =from-= prefix in the resulting filename traces provenance. ** Phase E — Report Summarize the fan-out: - Total targets discovered - Sent successfully (count) - Failed (list with reason) - Excluded (list with reason) If any failures, surface them — silent failure on a broadcast means some projects never learn about the change. ** Phase F — Cleanup Delete =/tmp/broadcast-.org=. The content lives in each target's inbox now. * Common Mistakes 1. *Broadcasting project-specific work.* Each broadcast costs N inbox files across the fleet. Routine handoffs go through =inbox-send= directly. 2. *Skipping Phase B's structure.* Free-form broadcasts force every recipient to parse them differently. Use the rigid headings. 3. *Sender-includes-itself.* The discovery helper excludes the sender automatically. Don't override it — broadcasting to your own inbox creates a self-reply loop. 4. *Forgetting Phase E.* A broadcast that partially succeeded is the failure mode you'll never notice. Always check the per-target results. 5. *Broadcasting without an "Action required" line.* Recipients need to know whether this is FYI or whether their project has to do something. The line is non-optional. 6. *Using broadcast as a substitute for documentation.* Capability announcements should be paired with a rule or workflow update so the next-next session can rediscover the capability from canonical docs, not from a stale inbox file. * Living Document If the discovery roots change (a new top-level directory for AI projects), update =cross-project-broadcast.py='s =SEARCH_ROOTS=. If the per-broadcast structure proves too rigid or too loose, tune Phase B. If the recipient projects start complaining about broadcast noise, the rule is "broadcast less," not "structure broadcasts harder."