# Daybook — LLM Posting Skill: Design & Next Steps **Status:** planning / pre-implementation **Date:** 2026-06-10 **Author:** drafted by Claude (Opus 4.8) after a live smoke test of the deployed instance ## What This Document Is A consolidated design recommendation for making **publishing to Daybook trivially easy for LLM agents**, plus notes on missing functionality surfaced during testing. Goal: an agent should be able to publish a correct artifact out of the box via a single command, without hand-crafting HTTP, JSON, or multipart requests. ## What Was Validated (Live Smoke Test) Tested against the prod instance `http://192.168.1.36:8000` via desktop-commander (the sandbox cannot reach the `192.168.1.x` LAN, so all calls were driven on-host). All seven artifact kinds were posted and verified under persona `claude`: | Kind | Path | Result | |---|---|---| | markdown | JSON | OK (`2db087a7`) | | html_full | JSON | OK (`8cd79771`) | | deck (markdown — WRONG) | JSON | stored but malformed (`5df27410`) | | image (svg) | multipart | OK (`83ab938c`) | | pdf | multipart | OK (`8c82b15c`) | | binary (csv) | multipart | OK, download-only (`2cceceaf`) | | deck (`
` blocks) | JSON | OK (`60d26e5a`) | | html_fragment | JSON | OK (`fd42816f`) | Confirmed working: capabilities endpoint, bearer auth, content-type inference (svg→image, pdf→pdf, csv→binary), persona/tag/kind filtering, read-back by id. ## The Core Problem To Design Around Every failure during testing was the same class of problem: **an LLM hand-assembling a request.** Three concrete failure modes, all observed: 1. **Inline content in shell commands breaks repeatedly.** `powershell -Command` mangled `$`-expansion, nested quotes, and backtick newlines on three separate attempts. This is not incidental — every model re-derives the shell incantation and gets it wrong. It is the single biggest source of friction. 2. **Multipart is environment-dependent.** Windows PowerShell 5.1 has no `Invoke-RestMethod -Form`; it needs `curl.exe` or PowerShell 7+. An agent cannot reliably know which host it is running on. 3. **Per-kind structure rules are easy to violate.** Markdown was sent to `deck` and rendered malformed — precisely because request-building is where judgment leaks in. The docs' stance is "Daybook does not fix malformed content," so the client must guarantee structure instead. **Design conclusion:** the skill must NOT teach the model how to build the request. It must give the model ONE command to run. All fiddliness (auth, JSON-vs-multipart, content-type, escaping, kind validation) belongs inside a helper, not in the prompt. ## Recommended Approach A **bundled CLI helper + a thin SKILL.md**. - The skill folder ships a single **zero-dependency Python script** (`scripts/daybook_post.py`, stdlib only). Python runs identically on the NUC (Linux) and on Windows, eliminating the curl / PS5.1 split entirely. - `SKILL.md` tells the agent **when** to publish and **that the command exists** — never how to craft HTTP. - The script is also usable by any non-Claude agent that can run a shell command, so it is not locked to the Anthropic skill format. SKILL.md is just the Claude-flavored discovery wrapper around a universal tool. ## Why This Is "Easy Out Of The Box" 1. **Content never touches the command line.** Content comes from a file or stdin, so escaping / newlines / quotes never arise: ```bash cat report.md | python daybook_post.py --kind markdown --title "Build Report" python daybook_post.py --file diagram.svg --title "Architecture Diagram" ``` 2. **One entry point, no branching decisions.** The script decides JSON-vs-multipart and infers content-type from file extension. The model never picks. 3. **Validate-before-send with fix hints**, turning the strict server contract into a guardrail the agent cannot trip over. 4. **Prints the artifact URL as the last stdout line**, so the agent reliably captures the result regardless of verbosity. ### Pre-flight validation table | Kind / input | Check | Behavior on mismatch | |---|---|---| | `deck` | content contains `...
` blocks, not Markdown" | | `html_fragment` | no `` / ` Use when you have produced a finished deliverable — a report, summary, brief, > diagram, generated HTML, PDF, or status update — that a human should be able to > review later outside this chat. Publishes it to Daybook and returns a URL. The body of SKILL.md should be short: - One line on what Daybook is (publish-only artifact journal). - The single command pattern (file/stdin in, URL out). - A 4-row kind cheat-sheet (markdown / fragment / full / deck → what content shape). - "Run `--check` first if unsure the instance is up." - Explicitly: do NOT hand-build curl/JSON; always use the script. Proposed skill folder layout: ``` agent-daybook/ (skill root) SKILL.md scripts/ daybook_post.py # the one helper, stdlib only .env.example # DAYBOOK_URL / DAYBOOK_TOKEN / DAYBOOK_PERSONA ``` ## Open Decisions (Need Your Call) 1. **Token handling.** Baking the prod token as a fallback default = truly zero-config, but it lands in the skill folder / repo. Cleaner: require `DAYBOOK_TOKEN` and ship `.env.example`. Recommendation: zero-config now while it is a local MVP, tighten to env-only before this leaves the LAN. 2. **Helper location.** Bundle inside the skill (`scripts/`) for a self-contained, no-install drop-in — recommended — vs a system-wide install that reintroduces PATH friction. 3. **Auto-wrap convenience kinds.** Should the script auto-wrap a `.csv`/`.json` into a Markdown fenced block so it renders today (server has no CSV/JSON renderer yet)? Convenient, but slightly magic. Suggest: opt-in flag `--as-markdown`, not default. ## Server-Side / Missing Functionality Notes Observed during testing. The thin client absorbs MVP gaps so the server can stay strict; these are candidates for later server work, not blockers. - **No DELETE / no content revision.** Once posted, an artifact is permanent; `content`/`kind`/`persona`/`day` are not PATCH-editable. The malformed test deck `5df27410` can only be superseded, not removed. Consider a soft-delete or `archived` flag for cleanup of test/mistake artifacts. - **No CSV/JSON/code renderer.** These store as download-only `binary`. Fine for now; the client can wrap them as Markdown on request. A dedicated renderer is the eventual fix. - **Single shared token, no reader auth.** Acceptable on a trusted LAN; revisit before any wider exposure. - **No pagination/cursors on list.** Fine at current volume; will matter once feeds grow. - **Strict-by-design rendering.** "Daybook does not fix malformed content" is a reasonable stance IF the standard publish path is a validating client. The skill is what makes that stance safe — keep them in sync (if the server adds a kind, the script's validation table must follow). ## Suggested Build Order 1. Write `scripts/daybook_post.py` (stdlib: `urllib`, hand-rolled multipart, extension→mime map, kind validation, stdin/file content, URL on last line). 2. Smoke-test it against the live instance for all four text kinds + the three file kinds — same coverage as the manual test, but each via one command. 3. Write `SKILL.md` (intent-keyed description + the cheat-sheet) and `.env.example`. 4. Verify discovery: confirm an agent picks the skill from the description alone. 5. Later/server: soft-delete or archive flag; CSV/JSON renderer; token hardening before the instance leaves the LAN. ## Appendix: Environment Facts (from test host) - Prod instance reachable only on LAN `192.168.1.36:8000` — agents must be on-network. - Host is Windows PowerShell **5.1** (no `-Form`); `curl.exe` present via Git; Python **3.12** present. Python helper avoids all shell-specific pitfalls. - Inlining content into `powershell -Command` is the confirmed failure mode; file/stdin input is the fix. --- ## Architecture Decision: Public REST API as the Universal Substrate **Decided:** 2026-06-10 · **Status:** accepted direction; hardening deferred (see below) ### Core conclusion The private LAN address (`192.168.1.36`) was the *only* thing forcing MCP and desktop-commander workarounds. Nothing about Daybook intrinsically requires them. Host Daybook on a publicly routable VM and the reachability wall disappears for every agent at once. The generic, universal interface is simply the **public HTTPS REST API** — any LLM or agent with an HTTP client can `POST /api/artifacts` in any language. A client script is optional sugar; MCP drops from "required" to "nice-to-have." ### The layering (everything hangs off the REST API) | Layer | Role | Required? | |---|---|---| | Public HTTPS REST API | The universal substrate. This is the product. | Yes — core | | Thin client (`daybook_post.py`, path-based) | One-liner ergonomics over REST | Optional | | MCP server (local stdio) | Typed calls + auto-discovery for MCP-native agents | Optional polish | | Skill (`SKILL.md`) | Claude-specific pointer to the script/REST | Optional | Build bottom-up: REST alone is enough to be generic. Add the others only where a specific client benefits. ### Reachability by environment (once Daybook is public) | Environment | Can it POST directly? | Notes | |---|---|---| | Claude Code / laptop / CI / arbitrary agent | Yes | Open internet + HTTP client. The 95% case. | | claude.ai / Desktop chat sandbox (`bash_tool`) | Yes, after one toggle | Add the Daybook domain to the bash **egress allowlist** in network settings; then a sandbox python script reads a sandbox-generated file and POSTs. No desktop-commander, no MCP. | | claude.ai `web_fetch` | No | GET-oriented public fetcher; cannot do an authenticated POST with a body. Use `bash_tool` instead. | Key point: in the all-public case the file-location problem also dissolves — the generated file and the posting script are co-located in the same sandbox, and the target is publicly routable. ### Deferred: auth hardening for the LAN -> public transition The reachability story gets *simpler* when public; the auth story gets *stricter*. The single shared dev token is fine on a trusted LAN and unacceptable on the open internet. Before any real public exposure: - [ ] Per-agent API keys (revocable, attributable), not one shared token - [ ] TLS / HTTPS only - [ ] Rate limiting + upload size/abuse guards - [ ] Write-scoping per persona (an agent can only post as its own persona) - [ ] Basic audit log of who posted what ### NOT needed for current testing (explicit) For testing the basic idea and playing with dummy documents, **none of the above is required**. The current setup is sufficient: - Keep running on the LAN (`192.168.1.36:8000`) with the single dev token. - Post dummy artifacts via desktop-commander (this chat) or the CLI (Claude Code). - Treat the auth-hardening checklist as a gate that applies *only* when Daybook moves to a public host for real use — not before. Sequencing: prove the posting ergonomics and rendering with dummy docs first; take on public deployment + auth hardening only once the basic idea is validated.