
Deepworkplan
- 81 installs
- 19 repo stars
- Updated July 16, 2026
- dailybothq/deepworkplan-skill
Makes a repository AI-agent-ready (AGENTS.md, docs, .agents) and runs structured multi-task Deep Work Plans an agent drafts, executes, and resumes.
About
A router skill that onboards a repo into an AI-first structure and drives durable multi-task Deep Work Plans through create, execute, refine, resume, status, and verify sub-skills. Developers use it to plan and run long-horizon coding work an agent can execute autonomously.
- Routes intent to create/execute/refine/resume/status/verify/onboard sub-skills
- Plan outputs land in a gitignored .dwp/ directory at repo root
Deepworkplan by the numbers
- 81 all-time installs (skills.sh)
- Ranked #1,442 of 3,282 Productivity & Planning skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/dailybothq/deepworkplan-skill --skill deepworkplanAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 81 |
|---|---|
| repo stars | ★ 19 |
| Last updated | July 16, 2026 |
| Repository | dailybothq/deepworkplan-skill ↗ |
What it does
Makes a repository AI-agent-ready (AGENTS.md, docs, .agents) and runs structured multi-task Deep Work Plans an agent drafts, executes, and resumes.
Files
DeepWorkPlan — Dailybot Addon
Connect the target repo to the developer's Dailybot team so that DWP work — especially a plan completion — surfaces to humans as a standup-style progress/milestone report. This is an opt-in addon; it is never required for a repo to be AI-first, and it never blocks the actual work.
## The rule that overrides everything: this addon DEFERS, it does not reinvent
>
The official Dailybot agent skill already owns install, consent, auth,
context detection, the writing style, and the non-blocking guarantee. This
addon's job is narrow: (1) offer to install the Dailybot skill/CLI through
their own consent flows, and (2) wire an optional report step into DWP
execute/plan-completion that routes through the dailybotreportsub-skill.
It MUST NOT duplicate, bypass, or weaken any Dailybot consent or auth flow —
it points at them. (Normative source: `SPEC.md`.)
Positioning guardrail (read before anything)
The core DeepWorkPlan methodology has ZERO Dailybot dependency. It is vendor-neutral, MIT, and agent-agnostic. A repo with zero addons — including this one — is fully conformant. This addon adds team visibility for developers who already use Dailybot; declining it leaves a fully AI-first repo. Never present Dailybot as a precondition for DWP, and never auto-install it for everyone.
Read these first (all relative inside the skill)
- `SPEC.md` — the normative (RFC-2119) contract: what is installed
(all opt-in), how auth is deferred, how the report step is wired, the never-block rule, and the vendor-neutral guardrail.
- `templates/INTEGRATION.md` — reasoning guidance
(NOT copy-paste): detect-if-already-installed, how to wire the optional report step into DWP execution, and the consent / never-block rules.
../README.md— the addon mechanism (opt-in, reconcile-don't-clobber, contract).
When this runs
- From `onboard` Phase 7b — after the core AI-first scaffolding,
onboard
offers this addon alongside devcontainer; if accepted it reads this SKILL and runs the flow below.
- Directly —
/deepworkplan-addon-dailyboton an already-onboarded repo to
add the Dailybot integration.
The flow
Step 0 — Consent + recommend-only-if-relevant
1. Confirm relevance. Offer this addon only when it makes sense: the developer or team already uses Dailybot, or explicitly asks for team reporting. In trust/auto mode you MAY recommend it only on that signal — do not auto-install for everyone. If the developer declines, stop cleanly; the repo stays baseline-conformant. 2. Detect existing setup (reconcile-don't-clobber). Before installing anything, check what is already present (see templates/INTEGRATION.md):
- Dailybot skill already installed at the agent's skills dir
(~/.<agent>/skills/dailybot/)?
dailybotCLI already on PATH (command -v dailybot)?- A repo identity already committed (
.dailybot/profile.jsonor
.dailybot_example/profile.json)?
- An existing report step already wired into the repo's DWP
executenotes? - Harness hook configs already carrying
dailybot hookentries
(.claude/settings.json, .agents/settings.json, .cursor/hooks.json, …)? If a piece already exists, do not redo it — record it and only fill gaps.
Step 1 — Offer the Dailybot skill + CLI install (OPT-IN, defer consent)
Present the install paths and let the developer choose; never run an installer without their explicit acceptance — and where the Dailybot skill's own consent flow applies, defer to it rather than prompting yourself.
- Dailybot agent skill (the recommended path — it brings the consent/auth
flow with it):
npx skills add DailybotHQ/agent-skill(cross-agent, recommended), or- OpenClaw native:
openclaw skills install dailybot, or git clone https://github.com/DailybotHQ/agent-skill.git+ run itssetup.sh.- Dailybot CLI (the underlying bridge, from
`DailybotHQ/cli`; the skill installs it on first use via its own SHA-256-verified consent flow — you generally do not install it separately, but these are the supported paths if asked):
curl -sSL https://cli.dailybot.com/install.sh | bash— pair with the
checksum/consent verification the Dailybot skill documents in shared/auth.md (cross-origin diff + .sha256 sidecar check; never run it unverified), or
pip install dailybot-cli(Python 3.10+), orbrew install dailybothq/tap/dailybot(macOS).
Do not reimplement the verified installer. If the Dailybot skill is being
installed, let its shared/auth.md flow drive the CLI install + checksumverification. Only surface the raw CLI commands when the developer explicitly
wants the CLI without the skill.
Step 2 — Auth: DEFER to the Dailybot skill's own consent flow
Do not prompt for email, OTP, or API keys yourself, and do not store any credential. Authentication is owned by the Dailybot skill's `shared/auth.md`: dailybot login (email OTP) or DAILYBOT_API_KEY / dailybot config key=.... Point the developer at that flow; the skill handles login, profile, and the HTTP fallback. If they decline auth, skip reporting — never block.
Step 3 — Wire the plan lifecycle events into DWP execution
This is the integration value. Reasoning guidance is in templates/INTEGRATION.md — adapt it to the repo; do not copy verbatim.
- Add a short, clearly-optional note to the repo's DWP execution docs (e.g. the
generated AGENTS.md reporting section and/or docs/AI_AGENT_COLLAB.md) describing the four lifecycle events (SPEC §5.1) that fire when the Dailybot skill is installed: 1. Kickoff (SHOULD, regular) — when a plan is materialized and approved, report what is being built and why ("Starting: …"). 2. Significant task (MAY, regular) — a feature/bug fix/major refactor completes; intermediate setup tasks are never reported. 3. Blocked (SHOULD, regular with blockers) — the plan halts on a stop condition and state.json.blocked is populated (typical of unattended runs): the team sees what is stuck and what it needs in the standup instead of discovering a silent overnight halt. 4. Completion (SHOULD, the only milestone) — via the dailybot report sub-skill (dailybot agent update ... --milestone --json-data ...), describing what was built, never "completed a plan."
- Where the plan carries the machine-readable state layer
(../../spec/PLAN_STATE.md), derive the --json-data payload from state.json: completed from completed tasks (phrased as outcomes), in_progress from the current task, blockers from state.json.blocked.
- Every event MUST be best-effort and conditional: it fires only if the
Dailybot skill/CLI is present and authenticated, and it MUST NOT block create or execute if Dailybot is absent, unauthenticated, or unreachable — warn once and continue (see SPEC §Never-block).
- Optionally commit a repo identity so every contributor/agent signs reports the
same way: .dailybot/profile.json (or the gitignore-friendly .dailybot_example/profile.json template) — never with a key field (credentials in that file are a hard error per the CLI). The same file MAY carry the committed report policy the hooks honor: "report": {"min_interval_minutes": 30, "nudge": true} ("nudge": false is the soft opt-out that keeps manual reporting available).
Step 3b — Offer deterministic hook enforcement (OPT-IN, defer to the Dailybot skill)
The lifecycle wiring above is prompt-layer: it relies on the model remembering to report. Since Dailybot agent skill >= 1.6.0 with dailybot-cli >= 1.12.0, the Dailybot skill also ships deterministic hook enforcement (report/hooks.md): harness lifecycle hooks (dailybot hook session-start | activity | post-commit | stop | dismiss) backed by a local per-repo report ledger, so the harness itself detects unreported work and reminds the agent at end of turn — even in the long unattended sessions where prompt instructions decay. This is the strongest version of the visibility this addon exists for.
- Offer it (consent-gated, show the exact config before writing) when the
installed Dailybot skill/CLI versions support it: commit the repo-level hook config — Claude Code .claude/settings.json (or .agents/settings.json where .claude → .agents), Cursor .cursor/hooks.json, other harnesses per the table in the Dailybot skill's report/hooks.md — so every contributor and fresh container gets autonomous reporting on clone; the only per-person step left is dailybot login.
- Defer the mechanics. The hook templates, output formats, anti-noise
gates, and uninstall path are owned by the Dailybot skill's `report/hooks.md` — point at it; do not duplicate or hand-roll the JSON beyond merging it in. Merge into existing config files, never overwrite (§Reconcile).
- The two layers compose — no double-reporting. A successful
dailybot agent update (any lifecycle event from Step 3) resets the hook ledger, so the hooks stay silent after a lifecycle report; they act as the deterministic backstop when a lifecycle event was missed. A hook reminder mid-plan is answered with either a lifecycle-appropriate report or dailybot hook dismiss — never ignored, never blocking.
- Degrade gracefully. Older skill/CLI → skip this step (the Step 3 wiring
stands alone) and mention dailybot upgrade once. The dailybot hook commands are local-only and always exit 0, so installing them cannot violate the never-block rule; they also respect .dailybot/disabled.
Step 4 — Validate (SPEC §Validation)
Run the validation checklist and report: whether the skill/CLI is present, that auth was deferred (not reinvented), that the report step is wired as optional + non-blocking, whether hook enforcement was offered/installed (and the versions that gated it), the identity source if any, and any deferred items. If nothing could be installed here (sandbox/CI), say why — do not silently skip, and do not fail the onboarding.
Failure-mode guardrails
- Never required, never blocking. If declined — or if Dailybot is missing,
unauthenticated, or unreachable — stop/continue cleanly. The repo stays baseline-conformant and execute is never blocked by reporting.
- Defer auth, never store secrets. No email/OTP/API-key prompting here; no
credential written to any file. Point at the Dailybot skill's shared/auth.md.
- Verified install only. Never recommend
curl ... install.sh | bash
without the checksum/consent verification the Dailybot skill owns.
- Reconcile, don't clobber. An existing skill/CLI/identity/report step is
preserved; only fill gaps. Any destructive change needs explicit approval.
- Vendor-neutral. Never imply DWP needs Dailybot. This addon is purely
additive team visibility for teams already on Dailybot.
SPEC.md — Dailybot Addon (Normative)
Abstract
This document is the normative specification of the DeepWorkPlan Dailybot addon: an opt-in capability that connects an AI-first repository to the developer's Dailybot team so DWP work — especially a plan completion — surfaces to humans as a standup-style progress/milestone report. It defines what the addon installs/configures (all opt-in), how it defers authentication to the Dailybot skill's own consent flow, how the optional progress-report step is wired into DWP execution, the never-block rule, the reconcile-don't-clobber behavior, and the vendor-neutral guardrail.
The addon is governed by `../README.md` and `methodology-spec/ADDONS.md`: it is never required for baseline AI-first conformance.
Status of This Document
| Field | Value |
|---|---|
| Version | 2.2.0 |
| Status | Stable |
| Companions | SKILL.md, templates/INTEGRATION.md, ../README.md, methodology-spec/ADDONS.md, ../../spec/PLAN_STATE.md |
| License | MIT |
Additive in 2.2.0. Reporting grows from a single completion hook into a
plan lifecycle event model (§5.1): kickoff, significant task, blocked, and
completion — with the report's --json-data payload derived from the plan'smachine-readable state layer (PLAN_STATE.md). All events remain opt-in,conditional, and non-blocking; the completion milestone is unchanged.
1. Conventions
The RFC 2119 keywords (MUST, MUST NOT, SHOULD, SHOULD NOT, MAY, OPTIONAL) are interpreted as in RFC 2119.
Throughout, the Dailybot skill is the official agent skill pack (`DailybotHQ/agent-skill`); the Dailybot CLI is its companion binary (`DailybotHQ/cli`, PyPI dailybot-cli).
---
2. Vendor-Neutral Guardrail (the rule that frames everything)
- The core DeepWorkPlan methodology MUST have zero dependency on Dailybot.
It is vendor-neutral, MIT, and agent-agnostic. A repository MUST be fully conformant to the AI-first baseline (DOCUMENTATION_STANDARD.md §§2–7) and to the DWP specification with zero addons — including this one.
- This addon MUST NOT be presented as a precondition for using DWP, and the
onboard flow MUST NOT auto-install it for everyone. It is offered, and applied only on explicit acceptance.
- Declining this addon MUST still produce a baseline-conformant repo.
- The addon's value is purely additive team visibility for developers/teams
who already use Dailybot.
---
3. What the Addon Installs / Configures (all OPT-IN)
When accepted, the addon MAY install or configure the following — each only with explicit acceptance, and each reconciled if already present (§7):
3.1 The Dailybot agent skill (recommended path)
- The addon SHOULD offer the Dailybot agent skill as the primary path,
because it brings its own install/consent/auth flow and the report sub-skill. Supported install methods (the addon MUST offer, not force):
npx skills add DailybotHQ/agent-skill(cross-agent, recommended), or- OpenClaw native:
openclaw skills install dailybot, or git clone https://github.com/DailybotHQ/agent-skill.git+ run itssetup.sh.
3.2 The Dailybot CLI (the underlying bridge)
- The Dailybot CLI is the bridge the skill uses. The Dailybot skill installs it
on first use via its own SHA-256-verified consent flow, so the addon SHOULD NOT install the CLI separately when the skill is being installed.
- When the developer explicitly wants the CLI directly, the supported paths are:
curl -sSL https://cli.dailybot.com/install.sh | bash— which the addon
MUST pair with the checksum/consent verification documented in the Dailybot skill's shared/auth.md (cross-origin diff against the GitHub source + .sha256 sidecar match, optional cosign). The addon MUST NOT recommend piping the script to a shell unverified, or
pip install dailybot-cli(Python 3.10+), orbrew install dailybothq/tap/dailybot(macOS).- The addon MUST NOT reimplement the verified installer; it points at the
Dailybot skill's flow.
3.3 Optional repo identity
- The addon MAY commit a repo identity so every contributor and agent signs
reports under the same name: .dailybot/profile.json (or the gitignore-friendly .dailybot_example/profile.json template the CLI documents).
- A
key(credential) field in that file is a hard error — the addon
MUST NOT write credentials anywhere.
- The same file MAY carry the committed report policy that the hook layer
(§3.4) honors: "report": {"min_interval_minutes": <n>, "nudge": true|false}.
3.4 Optional harness hook enforcement
- When the installed Dailybot agent skill is >= 1.6.0 and the Dailybot CLI
is >= 1.12.0, the addon SHOULD offer — and MAY, with explicit acceptance, commit — repo-level harness hook configs whose entries invoke the dailybot hook lifecycle commands (session-start, activity, post-commit, stop), e.g. Claude Code .claude/settings.json, Cursor .cursor/hooks.json.
- The hook templates, output dialects, anti-noise gates, and uninstall path are
owned by the Dailybot skill's report/hooks.md — the addon MUST defer to it and MUST NOT duplicate or diverge from those templates.
- The addon MUST NOT write hook configs without explicit acceptance, and
MUST merge into existing config files — never overwrite (§7). Existing dailybot hook entries MUST be preserved, not duplicated.
- When versions are older, the addon MUST skip this offer (the §5 wiring
stands alone) and MAY suggest dailybot upgrade once.
---
4. Authentication — DEFER, Do Not Reinvent
- The addon MUST defer all authentication to the Dailybot skill's own
consent flow (shared/auth.md): dailybot login (email OTP) or DAILYBOT_API_KEY / dailybot config key=..., including the CLI install consent and the HTTP fallback.
- The addon MUST NOT prompt for email, OTP, or API keys itself, MUST NOT
bypass or weaken that flow, and MUST NOT store any credential in any file it creates.
- If the developer declines authentication, the addon MUST skip reporting and
continue — auth issues MUST NOT block the primary work (§6).
---
5. The Integration Value — The Plan Lifecycle Event Model
This is the "why": when present, the full DWP plan lifecycle surfaces to the developer's Dailybot team as standup-style agent updates — what is starting, what is progressing, what is stuck, and what shipped.
5.1 The four lifecycle events
The addon MUST wire a clearly-optional report step into the repo's DWP execution documentation (the generated AGENTS.md reporting section and/or docs/AI_AGENT_COLLAB.md) describing these events. Every event is conditional (§5.3) and non-blocking (§6).
| Event | Trigger | Level | Requirement |
|---|---|---|---|
| Kickoff | A plan is materialized and approved (create Step 5), or its first execute turn begins | regular | SHOULD |
| Significant task | A task that is independently significant completes — a feature, a bug fix, a major refactor (execute Step 5). Intermediate setup tasks are not reported. | regular | MAY |
| Blocked | The plan halts on a stop condition and state.json.blocked is populated (AGENT_PROTOCOL.md §7.3, PLAN_STATE.md §4.4) — typical of unattended runs | regular, with blockers populated | SHOULD |
| Completion | All tasks [x]; the plan finishes (execute Step 7) | milestone | SHOULD |
- The kickoff report describes what is being built and why it matters
("Starting: …"), giving the team forward visibility — never "created PLAN_x with N tasks".
- The blocked report is the unattended profile's escalation made human: the
team sees what is stuck and what it needs in the standup channel instead of discovering a silent overnight halt. Its content MUST come from state.json.blocked (reason, needs).
- A plan completion is the only milestone; every other event is a
regular report. A plan MUST NOT emit more than one kickoff and one completion report.
5.2 Payload — derived from the plan state layer
The report command shape is dailybot agent update "<message>" [--milestone] --json-data '<completed/in_progress/blockers>' --metadata '<repo/branch/model>'.
- When the plan carries the machine-readable state layer (
PLAN_STATE.md),
--json-data SHOULD be derived from state.json: completed from the completed tasks (phrased as outcomes, not task numbers), in_progress from the task currently in_progress, and blockers from state.json.blocked. The state layer is the single source the payload is projected from — the addon MUST NOT invent a second progress-tracking mechanism.
- Without the state layer, the payload is derived from the plan README's
checkbox list. The message and payload MUST still follow the writing rules below.
- Report content MUST follow the dailybot
reportwriting rules: describe
what was built and why, in English, 1–3 sentences, never "completed a plan", never file paths / git stats / branch names / plan IDs.
5.3 How the events are emitted
- Every event is conditional: it fires only when the Dailybot skill/CLI
is present and authenticated. The addon MUST document the detection check (e.g. command -v dailybot, or the skill installed at ~/.<agent>/skills/dailybot/) and that the report routes through the dailybot report sub-skill, not a hand-rolled API call.
- The addon MUST NOT change the DWP
create/executepublic surface; it
only adds optional, conditional reporting hooks described in the repo's docs.
- The addon SHOULD respect Dailybot's per-repo opt-out
(.dailybot/disabled): if present, no report is sent — for any event.
- Synergy with hook enforcement (§3.4): a successful
dailybot agent update — any lifecycle event — resets the Dailybot hook ledger, so the two layers never double-report. The hooks are the deterministic backstop for a missed lifecycle event; a hook reminder mid-plan MUST be answered with either a lifecycle-appropriate report or dailybot hook dismiss, never ignored silently.
---
6. Never-Block Rule (mandatory)
- Reporting MUST NOT block the developer's primary work or DWP
execute. - If the Dailybot skill/CLI is absent, unauthenticated, the network is
down, or any command errors, the addon's wired step MUST: warn briefly once, continue the primary task, not retry automatically, and not enter a diagnostic loop. This mirrors the Dailybot skill's own non-blocking guarantee.
- Plan execution MUST succeed regardless of whether the report was sent.
- The
dailybot hookcommands (§3.4) read only local state and always exit
0 by contract, so installing hook enforcement cannot violate this rule; the hooks also honor .dailybot/disabled and the committed report policy.
---
7. Reconcile, Don't Clobber
- The addon MUST detect existing setup before acting: an already-installed
Dailybot skill, a dailybot CLI on PATH, a committed .dailybot/profile.json / .dailybot_example/profile.json, an existing report step in the repo's DWP docs, or harness hook configs already carrying dailybot hook entries.
- Where a piece already exists, the addon MUST preserve it and only fill
gaps — it MUST NOT reinstall, re-prompt auth, overwrite a working identity, or duplicate the report step.
- Any destructive change to an existing file MUST be approved by the user
first (AGENT_PROTOCOL.md); the addon MUST record what it changed.
---
8. Conformance + Validation Step
A repo is conformant to this addon when all hold (after acceptance):
1. The Dailybot skill or CLI is available (installed via one of the §3 opt-in paths), or the addon recorded why it could not install here (sandbox/CI) without failing onboarding. 2. Authentication was deferred to the Dailybot skill's shared/auth.md — no email/OTP/API-key prompting and no credential written by this addon. 3. The repo's DWP execution docs describe the optional, conditional, non-blocking lifecycle events (§5.1): kickoff, significant task, blocked, and the milestone on plan completion — all via the dailybot report sub-skill, with payloads derived from the plan state layer where present. 4. If a repo identity was committed, it is credential-free (no key field) and resolves consistently for all contributors/agents. 5. Existing skill/CLI/identity/report-step were reconciled, not clobbered. 6. The vendor-neutral guardrail holds: nothing in the repo implies DWP requires Dailybot; the repo is still baseline-conformant. 7. Smoke test (best-effort): if the CLI is present and authenticated, dailybot status --auth succeeds; otherwise note why. Never fail onboarding on this.
---
9. References
- RFC 2119
SKILL.md(the onboarding hook + flow),templates/INTEGRATION.md(reasoning aid)../README.md(addon mechanism), `../../spec/ADDONS.md` (concept + pointer)- Dailybot skill: `DailybotHQ/agent-skill`
— SKILL.md, shared/auth.md, report/SKILL.md, report/hooks.md (hook enforcement templates, >= 1.6.0)
- Dailybot CLI: `DailybotHQ/cli`, PyPI
dailybot-cli
— docs/AGENT_HOOKS.md (the dailybot hook command group + report ledger, >= 1.12.0)
- `../../spec/PLAN_STATE.md` (the state layer the payloads derive from),
../../spec/AGENT_PROTOCOL.md§7 (unattended profile + stop conditions)
---
Part of the DeepWorkPlan methodology v2.2.0, MIT License, by [Dailybot](https://dailybot.com) / dailybotops.
Template — Dailybot Integration (reason, don't copy-paste)
Reasoning guidance for wiring the Dailybot addon into a target repo. This is not a file to drop in verbatim — the commands and the doc wording are reasoned against the target repo (its agent host, its real DWP execution docs, whether it is public/private, whether a repo identity already exists). Keep the SPEC contract intact: opt-in, defer auth, never block, reconcile-don't-clobber, vendor-neutral.
---
1. Detect if Dailybot is already installed (reconcile-don't-clobber)
Run these before offering to install anything. Where a piece exists, do not redo it — record it and only fill gaps.
# Is the Dailybot CLI on PATH?
command -v dailybot && dailybot --version 2>&1
# Is the Dailybot skill installed for this agent? (adjust the path to the host)
# Claude Code: ~/.claude/skills/dailybot/ Cursor: ~/.cursor/skills/dailybot/
# Codex: ~/.codex/skills/dailybot/ Gemini: ~/.gemini/skills/dailybot/
ls -d ~/.*/skills/dailybot 2>/dev/null
# Is a repo identity already committed?
ls .dailybot/profile.json .dailybot_example/profile.json 2>/dev/null
# Is auth already good? (only meaningful if the CLI is present — never prompt here)
command -v dailybot >/dev/null 2>&1 && dailybot status --auth 2>&1
# Has Dailybot been disabled for this repo? (respect the opt-out — send nothing)
ls .dailybot/disabled 2>/dev/null
# Are harness hooks already wired? (the command string is the uninstall marker)
grep -l 'dailybot hook' .claude/settings.json .agents/settings.json .cursor/hooks.json 2>/dev/nullDecision notes:
- Skill present → do not reinstall. Just verify the report step is wired.
- CLI present but skill absent → the integration still works; the report
routes through the CLI (dailybot agent update ... --milestone). Offer the skill only if the developer wants the richer routing/writing guidance.
- Identity present → keep it. Never overwrite a working
profile.json; never
add a key field (credentials in that file are a hard error).
- `.dailybot/disabled` present → wire the step, but it stays silent for this
repo by design. Note it; do not remove the file.
---
2. Install paths to OFFER (opt-in — never run without acceptance)
Let the developer choose; defer the verified CLI install + auth to the Dailybot skill's own shared/auth.md flow.
| Want | Offer |
|---|---|
Dailybot skill (recommended — brings consent/auth + report) | npx skills add DailybotHQ/agent-skill · OpenClaw openclaw skills install dailybot · git clone https://github.com/DailybotHQ/agent-skill.git + ./setup.sh |
| Dailybot CLI only (developer explicitly wants the binary) | pip install dailybot-cli (Py 3.10+) · brew install dailybothq/tap/dailybot (macOS) · `curl -sSL https://cli.dailybot.com/install.sh \ |
Prefer installing the skill — it owns the SHA-256-verified CLI install and
the OTP/API-key auth flow. Only surface the raw CLI commands when the developer
wants the CLI without the skill. Never recommend curl ... | bash unverified.3. Auth — point at the Dailybot skill, do not reinvent
Do not prompt for email/OTP/API key, and do not store credentials. Tell the developer the Dailybot skill drives this:
dailybot login(email OTP), ordailybot config key=.../DAILYBOT_API_KEY.- Full flow: the Dailybot skill's
shared/auth.md. If they decline, skip
reporting and continue.
---
4. Wire the plan lifecycle events into DWP execution
The integration value: the plan lifecycle surfaces to the team when Dailybot is present (SPEC §5.1). Reason the exact wording for the repo, then add a short, clearly-optional note to the repo's reporting docs (the generated AGENTS.md reporting section and/or docs/AI_AGENT_COLLAB.md). The shape to convey:
Optional — Dailybot reporting (best-effort, never blocks): when the
Dailybot skill/CLI is installed and authenticated, DWP work emits agent
updates at four points — kickoff (plan approved: what is being built),
significant task (a feature/fix ships mid-plan), blocked (the plan
halts and state.json.blocked says what it needs), and completion (theonly milestone: what was built). If Dailybot is absent, unauthenticated,
or unreachable — or if .dailybot/disabled is present — skip silently andcontinue. Reporting MUST NOT blockcreateorexecute.
Reference command shapes (the actual content is reasoned from the work, not templated; route through the report sub-skill when the skill is installed):
# Guard shared by every event — only when the CLI is present and authed.
if command -v dailybot >/dev/null 2>&1 && [ ! -f .dailybot/disabled ]; then
# 1) Kickoff (regular) — plan materialized and approved
dailybot agent update "Starting: <what is being built and why it matters>" \
--json-data '{"completed":[],"in_progress":["<the goal, as an outcome>"],"blockers":[]}' \
--metadata '{"model":"<your-model>","repo":"<repo>","branch":"<branch>"}' \
|| echo "Dailybot report skipped (non-blocking)."
# 2) Significant task (regular) — a feature/fix shipped mid-plan
dailybot agent update "<what shipped, in plain standup English>" \
--json-data '{"completed":["<outcome>"],"in_progress":["<next outcome>"],"blockers":[]}' \
|| echo "Dailybot report skipped (non-blocking)."
# 3) Blocked (regular, blockers populated) — derive from state.json.blocked
dailybot agent update "<what is stuck and what it needs>" \
--json-data '{"completed":["<done so far>"],"in_progress":[],"blockers":["<reason> — needs <needs>"]}' \
|| echo "Dailybot report skipped (non-blocking)."
# 4) Completion (the only --milestone)
dailybot agent update "<what was built, in plain standup English>" \
--milestone \
--json-data '{"completed":["..."],"in_progress":[],"blockers":[]}' \
--metadata '{"model":"<your-model>","repo":"<repo>","branch":"<branch>"}' \
|| echo "Dailybot report skipped (non-blocking)."
fiDecision notes:
- Milestone vs regular: plan completion →
--milestone, and nothing else.
Kickoff, significant tasks, and blocked are regular reports.
- Payload from the state layer: when the plan carries
state.json
(PLAN_STATE.md), derive --json-data from it — completed from completed tasks phrased as outcomes, in_progress from the current task, blockers from state.json.blocked (reason, needs). Without the state layer, derive from the plan README's checkboxes. Never maintain a separate progress ledger just for reporting.
- One kickoff, one completion per plan — re-runs and resumes do not
re-announce the kickoff.
- Writing rules: describe outcomes + why, English, 1–3 sentences. Never
"completed a plan", never file paths / git stats / branch names / plan IDs. Let the dailybot report sub-skill enforce the style.
- Identity (optional): commit
.dailybot/profile.json(or the
gitignore-friendly .dailybot_example/profile.json template) so every contributor/agent signs the same way — credential-free, no key field.
- Reconcile: if the repo's DWP docs already mention a report step, correct or
keep it; do not duplicate it.
---
4b. Offer deterministic hook enforcement (skill >= 1.6.0, CLI >= 1.12.0)
The §4 wiring is prompt-layer — it relies on the model remembering. When the installed Dailybot skill/CLI versions support it, also offer (opt-in, show the exact config first) to commit the repo-level harness hook config so the harness itself reminds the agent about unreported work at end of turn:
# Version gate — only offer when both hold
dailybot --version # >= 1.12.0 (the `dailybot hook` command group)
grep -m1 'version:' ~/.*/skills/dailybot/SKILL.md # >= 1.6.0 (report/hooks.md)Reason against the repo, then merge (never overwrite) the config the Dailybot skill's report/hooks.md documents — Claude Code .claude/settings.json (or .agents/settings.json where .claude → .agents), Cursor .cursor/hooks.json, other harnesses per its table. Decision notes:
- Defer the mechanics — templates, output formats (
--format claude|cursor|generic),
anti-noise gates, and uninstall all live in the Dailybot skill's report/hooks.md; do not duplicate them into the repo docs.
- No double-reporting by construction: every successful
dailybot agent update (any §4 lifecycle event) resets the hook ledger. The hooks are the deterministic backstop for a missed lifecycle event.
- Document the response contract in the repo's reporting note: a hook
reminder is answered with a report (if a meaningful unit is done) or dailybot hook dismiss (if not) — never ignored silently, never blocking.
- Committed policy knobs live in
.dailybot/profile.json:
"report": {"min_interval_minutes": 30, "nudge": false} turns reminders off for the repo while keeping manual reporting.
- Older versions: skip the offer, suggest
dailybot upgradeonce, and let
the §4 wiring stand alone.
---
5. Consent + never-block rules (do not violate)
- Opt-in: install nothing, write no identity, and commit no hook config
without explicit acceptance.
- Defer auth: never prompt for or store credentials; point at the Dailybot
skill's shared/auth.md.
- Verified install only: never recommend
curl ... install.sh | bash
without the skill's checksum/consent verification.
- Never block: the wired report step is best-effort; absence, auth failure,
network errors, or .dailybot/disabled mean skip-and-continue — warn once, no retries, no diagnostic loop. execute always succeeds regardless.
- Vendor-neutral: never imply DWP requires Dailybot. A repo with zero addons
is fully conformant.
SPEC.md — Dependency-Upgrade Addon (Normative)
Abstract
This document is the normative specification of the DeepWorkPlan dependency-upgrade addon: an opt-in capability that safely upgrades a repository's dependencies with a batched, validated, revertible workflow. It defines package-manager detection (RFC-2119), semver classification, the batched-upgrade rule, the validate-after-each-batch gate, the revert-on-failure rule, the reconcile-don't-clobber behavior, and the validation step.
The addon is package-manager agnostic: it reasons about the repo's actual manager (npm/pnpm/yarn, pip/poetry/uv/pipenv, cargo, go mod, bundler, composer, and more) rather than assuming npm. It is governed by ../README.md and methodology-spec/ADDONS.md: it is never required for baseline AI-first conformance.
Status of This Document
| Field | Value |
|---|---|
| Version | 2.1.0 |
| Status | Stable |
| Companions | SKILL.md, templates/ecosystems.md, templates/upgrade-report.md, templates/lib-upgrade-command.md, ../README.md, methodology-spec/ADDONS.md |
| License | MIT |
1. Conventions
The RFC 2119 keywords (MUST, MUST NOT, SHOULD, SHOULD NOT, MAY, OPTIONAL) are interpreted as in RFC 2119.
Throughout, a batch is a small, coherent set of dependency upgrades applied and validated together, and the gate is the repo's real validation command set (lint + typecheck + build + test, as applicable).
---
2. Package-Manager Detection (the part the addon reasons about)
- The addon MUST detect the package manager(s) from the **manifest and
lockfile that actually exist in the repo. It MUST NOT** assume npm or any single ecosystem.
- Detection signals MUST be derived from real files, e.g.:
| Ecosystem | Manifest | Lockfile → manager |
|---|---|---|
| JS / TS | package.json | pnpm-lock.yaml → pnpm · yarn.lock → yarn · package-lock.json → npm |
| Python | pyproject.toml / requirements*.txt / Pipfile | poetry.lock → poetry · uv.lock → uv · Pipfile.lock → pipenv · pinned requirements*.txt → pip / pip-tools |
| Rust | Cargo.toml | Cargo.lock → cargo |
| Go | go.mod | go.sum → go modules |
| Ruby | Gemfile | Gemfile.lock → bundler |
| PHP | composer.json | composer.lock → composer |
- A repo MAY contain multiple ecosystems (e.g. a JS frontend + a Python
service). The addon MUST handle each ecosystem with its own manager and its own batches.
- For JS/TS,
ncu(npm-check-updates) MAY be used as the cross-manager
version checker, but the install/update verb MUST be the detected manager's (pnpm install, yarn install, npm install).
- The full per-ecosystem command reference is
templates/ecosystems.md; it is a
checklist, not an answer key — detected reality wins.
---
3. Semver Classification
- Every outdated dependency MUST be classified by semantic version against
its current pinned version:
- patch
X.Y.Z → X.Y.(Z+1)(safest), - minor
X.Y.Z → X.(Y+1).0(usually safe), - major
X.Y.Z → (X+1).0.0(breaking changes possible). - patch + minor upgrades MAY be batched automatically.
- major upgrades MUST require explicit developer approval before
inclusion; the addon MUST present them and wait.
- Tightly coupled packages (a tool + its plugins; a framework + its companion
packages) SHOULD be upgraded in the same batch so a peer-dependency constraint is not split across batches.
---
4. Batched Upgrade
- The addon MUST apply upgrades in small, coherent batches and **MUST
NOT** upgrade everything at once (an all-at-once upgrade makes a failure impossible to isolate or revert cleanly).
- A reasonable order is: patch batch → minor batch → each approved
major on its own.
- Each batch MUST update the manifest and regenerate the lockfile **via the
detected manager's install/update command. The addon MUST NOT** hand-edit a lockfile.
---
5. Validate-After-Each-Batch Gate
- After every batch, the addon MUST run the repo's real validation gate —
the actual lint / typecheck / build / test commands the repo uses.
- The gate MUST be discovered from the repo (
AGENTS.mdQuick Commands,
docs/DEVELOPMENT_COMMANDS.md, the manifest's scripts, or the devcontainer addon's codecheck/check/fix/test aliases if present). The addon MUST NOT invent a gate.
- A batch is accepted only if the gate passes. A batch whose gate fails
MUST be handled per §6.
---
6. Revert on Failure
- If a batch's gate fails, the addon MUST revert just that batch:
restore the manifest and lockfile (e.g. git checkout -- <manifest> <lockfile>), re-run install to resync, and confirm the gate passes again.
- The addon MUST record the reverted batch as skipped/failed with the failing
gate and reason. It MAY retry the batch one package at a time to isolate the culprit.
- A failing major upgrade MUST be set aside, never force-installed past a
broken gate.
- The addon MUST NOT auto-commit; it surfaces the diff and lets the developer
commit (suggested: chore(deps): …).
---
7. Reconcile, Don't Clobber
- The addon operates on the repo's existing manifests and lockfiles; it
MUST preserve every pin and constraint it does not deliberately upgrade.
- It MUST NOT delete or rewrite a lockfile wholesale, change the package
manager, or remove dependencies without explicit approval.
- It MUST record what it changed (in the upgrade report).
---
8. Onboarding Hook + /lib-upgrade Delegator
- The addon's onboarding hook (
SKILL.md) is offered byonboardPhase 7b as an
opt-in step and MUST NOT be applied without acceptance.
- Only when accepted, the addon MUST install a
/lib-upgradedelegator
command into the target repo's .agents/commands/ (template: templates/lib-upgrade-command.md) that delegates to this addon. A declined addon installs no command and leaves a baseline-conformant repo.
---
9. Validation Step (run after applying)
The addon is correctly applied when all hold:
1. The package manager(s) were detected from real manifests/lockfiles, not assumed (no npm/ncu run in a non-JS repo). 2. Upgrades were classified by semver and batched (never all-at-once); majors required explicit approval. 3. The repo's real gate ran after each batch and every accepted batch passes it. 4. Any failing batch was reverted (manifest + lockfile restored, install resynced, gate green) and recorded. 5. No lockfile was hand-edited; no auto-commit happened. 6. An upgrade report (templates/upgrade-report.md) summarizes upgraded / skipped / reverted / validated. 7. If accepted via onboarding, a /lib-upgrade delegator exists in the repo's .agents/commands/; if declined, none was installed.
---
10. References
- RFC 2119
SKILL.md(the onboarding hook + flow),templates/*(reasoning aids)../README.md(addon mechanism),methodology-spec/ADDONS.md(concept + pointer)- Semantic Versioning
- npm-check-updates
---
Part of the DeepWorkPlan methodology v2.1.0, MIT License, by [Dailybot](https://dailybot.com) / dailybotops.
Template — Per-Ecosystem Upgrade Reference (reasoning aid)
This is a reasoning aid, not a copy-paste script. Detect the repo's actual package manager from the manifest and lockfile that exist, then drive that manager's real commands. Match the row for the detected stack as a checklist and verify each command against the real repo — detected reality wins. A repo MAY have more than one ecosystem; handle each with its own manager, in its own batches.
How to detect the manager (lockfile is the tell)
| Ecosystem | Manifest | Lockfile present → manager |
|---|---|---|
| JS / TS | package.json | pnpm-lock.yaml → pnpm · yarn.lock → yarn · package-lock.json → npm |
| Python | pyproject.toml / requirements*.txt / Pipfile | poetry.lock → poetry · uv.lock → uv · Pipfile.lock → pipenv · pinned requirements*.txt → pip / pip-tools |
| Rust | Cargo.toml | Cargo.lock → cargo |
| Go | go.mod | go.sum → go modules |
| Ruby | Gemfile | Gemfile.lock → bundler |
| PHP | composer.json | composer.lock → composer |
Never assume npm. Never run a manager whose lockfile is absent. If two JS
lockfiles exist, the committed one wins; flag the inconsistency.
Per-ecosystem command reference
{pkg}= a single dependency ·{mgr}= the detected JS manager
(pnpm/yarn/npm). The gate in every row is the repo's real
validation command set, discovered fromAGENTS.md/docs// the manifest —
the examples below are illustrative, not prescriptive.
JS / TS (npm · pnpm · yarn) — ncu is the cross-manager checker
| Step | Command |
|---|---|
| Check outdated | ncu (or ncu --format json); fallback {mgr} outdated |
| Classify | parse current vs target semver from ncu output → patch / minor / major |
| Update manifest (patch) | ncu -u --target patch |
| Update manifest (minor) | ncu -u --target minor |
| Update manifest (chosen) | ncu -u --filter "{pkg-a} {pkg-b}" |
| Install / regenerate lock | {mgr} install (pnpm/yarn/npm) |
| Gate (example) | pnpm run biome:check && pnpm run astro:check && pnpm run build && pnpm run test |
| Revert a batch | git checkout -- package.json <lockfile> && {mgr} install |
Python — poetry · uv · pip / pip-tools · pipenv
| Step | poetry | uv | pip-tools | pipenv |
|---|---|---|---|---|
| Check outdated | poetry show -o | uv pip list --outdated | pip list --outdated | pipenv update --outdated |
| Update chosen | poetry update {pkg} | uv lock --upgrade-package {pkg} | bump in requirements*.in then pip-compile | pipenv update {pkg} |
| Install / sync | poetry install | uv sync | pip-sync / pip install -r … | pipenv install |
| Lockfile | poetry.lock | uv.lock | pinned requirements*.txt | Pipfile.lock |
| Revert | git checkout -- pyproject.toml poetry.lock && poetry install | git checkout -- pyproject.toml uv.lock && uv sync | git checkout -- requirements*.txt && pip-sync | git checkout -- Pipfile Pipfile.lock && pipenv install |
| Gate (example) | ruff check && mypy && pytest | (same) | (same) | (same) |
Rust — cargo
| Step | Command |
|---|---|
| Check outdated | cargo update --dry-run (or cargo outdated if installed) |
| Update chosen | cargo update -p {pkg} (minor/patch within semver) |
| Major bump | edit the version req in Cargo.toml, then cargo update -p {pkg} |
| Lockfile | Cargo.lock (regenerated by cargo update) |
| Gate (example) | cargo build && cargo test && cargo clippy -- -D warnings |
| Revert | git checkout -- Cargo.toml Cargo.lock |
Go — go modules
| Step | Command |
|---|---|
| Check outdated | go list -u -m all |
| Update chosen (minor/patch) | go get {module}@latest (or a specific tag) |
| Tidy | go mod tidy |
| Lockfile | go.mod + go.sum |
| Gate (example) | go build ./... && go test ./... && go vet ./... |
| Revert | git checkout -- go.mod go.sum |
Ruby — bundler
| Step | Command |
|---|---|
| Check outdated | bundle outdated |
| Update chosen | bundle update {gem} (conservative: --conservative) |
| Lockfile | Gemfile.lock |
| Gate (example) | bundle exec rubocop && bundle exec rspec |
| Revert | git checkout -- Gemfile Gemfile.lock && bundle install |
PHP — composer
| Step | Command |
|---|---|
| Check outdated | composer outdated |
| Update chosen | composer update {pkg} --with-dependencies |
| Lockfile | composer.lock |
| Gate (example) | composer lint && composer test |
| Revert | git checkout -- composer.json composer.lock && composer install |
Reasoning notes
- The lockfile is regenerated by the manager — never hand-edit it.
- Discover the gate, don't guess it. Read the repo's
AGENTS.mdQuick
Commands / docs/DEVELOPMENT_COMMANDS.md / manifest scripts, or use the devcontainer addon's codecheck/check/fix/test aliases if present.
- Batch + validate + revert is the same loop in every ecosystem; only the
detect / update / install / gate verbs change.
Template — /lib-upgrade delegator command (reasoning aid)
This is the delegator command the dependency-upgrade addon installs into the target repo's .agents/commands/lib-upgrade.md only when the addon is accepted during onboard Phase 7b (or when the addon is run directly). It is a thin delegator: it carries no upgrade logic of its own — it routes to the deepworkplan-addon-dependency-upgrade addon, which holds the real flow.
Fill the placeholders by reasoning about the target repo (its detected package manager and real validation gate); do not copy verbatim. Decline the addon → do not install this command.
---
name: lib-upgrade
description: Safely upgrade this repo's dependencies (batched, validated, revertible) via the DeepWorkPlan dependency-upgrade addon.
---
# /lib-upgrade
Bring this repository's dependencies up to date **without breaking the build**.
This command is a **thin delegator** to the DeepWorkPlan
`deepworkplan-addon-dependency-upgrade` addon — it does not contain the upgrade
logic itself.
## Steps
1. Invoke the `deepworkplan-addon-dependency-upgrade` addon (via
`/deepworkplan-addon-dependency-upgrade` or by reading the addon's `SKILL.md`).
2. Follow the addon's flow: detect this repo's package manager
(<e.g. pnpm via pnpm-lock.yaml>), classify upgrades (patch/minor/major),
upgrade in safe batches, run this repo's real gate after each batch
(<e.g. `pnpm run biome:check && pnpm run astro:check && pnpm run build`>),
revert any batch whose gate fails, and summarize.
3. Surface the upgrade report and the diff; do **not** auto-commit.
## Notes
- Detected package manager for this repo: <fill in — e.g. pnpm / poetry / cargo>.
- Real validation gate for this repo: <fill in the repo's actual commands>.
- Majors require explicit approval before they are included in a batch.
- The lockfile is regenerated by the manager — never hand-edit it.Template — Dependency Upgrade Report (reasoning aid)
This is the report shape to produce after the upgrade flow. Fill it by reasoning about what actually happened; keep the sections, drop rows that do not apply. Do not auto-commit — surface this report and the diff, and let the developer commit.
# Dependency Upgrade Report
**Date:** <YYYY-MM-DD>
**Ecosystem(s):** <e.g. JS/TS (pnpm), Python (poetry)>
**Package manager(s) detected from:** <manifest + lockfile that decided it>
## Summary
- Upgraded: <N> dependencies across <M> batches
- Skipped / reverted: <N> (see below)
- Majors: <approved N / deferred N>
## Upgraded (by tier)
### Patch
- <pkg>: <old> → <new>
### Minor
- <pkg>: <old> → <new>
### Major (developer-approved)
- <pkg>: <old> → <new>
## Skipped / Reverted
- <pkg>: <old> → <new> — **reverted**; gate failed: `<command>` (<reason>)
- <pkg>: <old> → <new> — **deferred** (major, awaiting review)
## Validation
- Gate used (the repo's real commands): `<command set>`
- Result per accepted batch: ✅ pass
## Files changed
- <manifest> (e.g. package.json / pyproject.toml / Cargo.toml / go.mod)
- <lockfile> (e.g. pnpm-lock.yaml / poetry.lock / Cargo.lock / go.sum)
## Recommended follow-ups
- <e.g. revisit the deferred major once upstream X lands>
- Suggested commit: `chore(deps): upgrade <N> dependencies (patch + minor)`SPEC.md — Design-System Addon (Normative)
Abstract
This document is the normative specification of the DeepWorkPlan design-system addon: an opt-in capability that gives a repository with a user-facing interface surface a `DESIGN.md` — placed under `docs/` alongside the repo's other specs and indexed from AGENTS.md — a Markdown design-system file that any coding agent reads to generate interface output consistent with the repo's own conventions. It defines the interface-surface gate (RFC-2119) and its three profiles (visual UI, CLI output, conversational), the location + `AGENTS.md` discovery rule, the canonical sections a DESIGN.md MUST carry per profile, the reason-don't-copy rule, the reconcile-don't-clobber behavior, the pragmatic-reference posture toward the upstream convention, the onboarding hook, and the validation step.
The addon is stack-aware: it reasons about the repo's actual design source (CSS custom properties, a Tailwind config, design-token files, component styles — or a CLI rendering layer, or message-composition conventions) rather than copying a third-party brand file. It is governed by ../README.md and methodology-spec/ADDONS.md: it is never required for baseline AI-first conformance — a repo with zero addons is fully conformant.
Status of This Document
| Field | Value |
|---|---|
| Version | 2.2.0 |
| Status | Stable |
| Companions | SKILL.md, templates/DESIGN.md.md, templates/presets.md, templates/agent_prompt_guide.md, ../README.md, methodology-spec/ADDONS.md |
| License | MIT |
Divergence from 2.1.0. Version 2.1.0 was frontend/UI-scoped and had a
hard exclusion: a CLI or backend repo MUST have the addon skipped. Version
2.2.0 generalizes the gate to interface surfaces and introduces
profiles (§3). The change is additive and backwards compatible: a
DESIGN.mdproduced under 2.1.0 is a valid single-profile (visual-ui)
DESIGN.md under 2.2.0, with zero migration required, and the visualprofile's recommendation strength is unchanged.
1. Conventions
The RFC 2119 keywords (MUST, MUST NOT, SHOULD, SHOULD NOT, MAY, OPTIONAL) are interpreted as in RFC 2119.
Throughout, `DESIGN.md` is the design-system file this addon produces (at docs/DESIGN.md by default, §2); an interface surface is any boundary where the product meets a person (a rendered visual UI, styled terminal output, or messages the product sends on a chat/email platform); a profile is the per-surface flavor of the addon (§3); a token is a named design value — for a visual surface a color, a type size, a spacing step, a radius, an elevation; for a CLI surface a semantic style (success, error, warning, dim) or an output component; for a conversational surface a voice rule or a message-shape convention; and the design source is the repo's real origin of those values (a stylesheet, a Tailwind config, a token file, the component styles, a CLI display/theme module, or message-composition helpers and their docs).
---
2. What the Addon Provides
- The addon MUST produce a single `DESIGN.md` — a Markdown file,
human-authorable and LLM-legible, that documents the repo's interface conventions so an agent generating interface output follows them instead of inventing statistically-common defaults. It MUST be version-controlled and reviewable in pull requests.
- The addon MUST NOT produce sibling files per surface (no
CLI_DESIGN.md,
no CONVERSATION_DESIGN.md): one repo, one DESIGN.md. Multiple accepted profiles stack as sections inside the same file (§4.1) — DESIGN.md is the canonical name agents discover.
- Location (DWP-native default): in a repo that follows the DWP documentation
standard — specs/docs centralized under docs/ and indexed by AGENTS.md — DESIGN.md SHOULD live at `docs/DESIGN.md`, alongside the other specs (ARCHITECTURE.md, STANDARDS.md, PRODUCT_SPEC.md, …), not scattered at the root. A repo with no docs/ tree (or one mirroring the upstream root convention) MAY instead place it at the repo root (./DESIGN.md).
- Discovery is by reference, not by physical location. Wherever it lives, the
addon MUST ensure AGENTS.md (and therefore CLAUDE.md) references DESIGN.md in its documentation index, so any agent discovers it the same way it discovers the rest of the docs/ specs. The location matters less than the AGENTS.md pointer being present.
- The file SHOULD stay compact: roughly 2–5K tokens for a single-profile
repo, and SHOULD NOT exceed roughly 8K tokens even when all three profiles apply — it must fit comfortably in an agent's context window alongside the task.
- The addon MUST NOT introduce a build dependency, a plugin, or an external
source of truth; DESIGN.md is plain Markdown readable by any agent.
---
3. Interface-Surface Gate (the part the addon reasons about)
- The addon is interface-surface-scoped. It MUST be offered (and
applied) only when the repo has at least one user-facing interface surface, detected as one or more of the profiles below.
- The agent MUST detect each profile from real files — never from the
repo's name or archetype alone:
3.1 Profile: visual-ui — rendered visual interfaces
| Signal | Example evidence |
|---|---|
| Stylesheet / tokens | *.css, *.scss, CSS custom properties, a tokens.* / theme.* file |
| Utility/theme config | tailwind.config.*, a Tailwind v4 @theme block in CSS, CSS-in-JS theme |
| UI components | .jsx/.tsx/.vue/.svelte/.astro components, a component library |
| Design assets | a brand/style guide doc, a design-tokens export, a Figma reference |
3.2 Profile: cli-output — styled terminal interfaces
| Signal | Example evidence |
|---|---|
| CLI/TUI rendering library | rich, textual, questionary (Python); chalk, ink, ora, prompts (Node); lipgloss, bubbletea (Go); colored, ratatui, indicatif (Rust) |
| A deliberate rendering layer | a display.* / output.* / ui.* helper module that centralizes printing; semantic print helpers (print_success, print_error, …) |
| Output conventions doc | an output/display best-practices doc; documented spinner/panel/prompt patterns |
| Interactive prompts | a picker/menu/confirm layer (questionary, inquirer, survey) |
A bare argument parser whose output is unstyled raw prints is a weak signal: the profile SHOULD NOT be offered when there is no deliberate rendering layer to document.
3.3 Profile: conversational — the product talks on a messaging surface
| Signal | Example evidence |
|---|---|
| Chat-platform SDK | slack-sdk/Bolt, discord.js/discord.py, botbuilder (Teams), Google Chat / Telegram / WhatsApp SDKs |
| Message composition layer | helpers or templates that build outbound messages (reports, notifications, replies); stable message-id / edit semantics |
| Voice conventions | documented tone/brevity/brand-naming rules for outbound messages (e.g. in AGENTS.md or a skill doc) |
| Other messaging surfaces | transactional email templates, SMS, voice/IVR prompt flows |
3.4 The gate
- A repo with no interface surface of any kind — a pure library with no
rendered output, a headless backend service, an infrastructure-only repo — MUST have this addon skipped; applying it there is a defect.
- A repo MAY match several profiles (a web app with an ops CLI; a Slack bot
with an admin UI). Detection MUST evaluate each profile independently, and each detected profile is offered independently (§3.5); the accepted profiles compose into the single DESIGN.md (§4.1).
- The addon is archetype-agnostic (
ARCHETYPES.md): it MAY be layered onto an
individual repo or onto a sub-repo of an orchestrator hub. No archetype is excluded a priori — only the absence of any interface surface excludes a repo.
- Backwards compatibility: a
DESIGN.mdcreated before profiles existed is
a valid single-profile visual-ui file. Re-running the addon on such a repo MUST NOT require restructuring it; new profiles are only added when detected and accepted (§6).
3.5 Recommendation Strength — per profile
This addon is never part of the zero-addon baseline (a repo with no addons is fully conformant — ADDONS.md §2). When a profile's signal is detected, its recommendation strength differs:
- `visual-ui` — default-on when detected (unchanged from 2.1.0):
- In trust mode, the
onboardflow SHOULD apply the profile
automatically (generate DESIGN.md), the same way it applies other detected-and-applicable setup — the developer MAY still decline.
- In guided mode, the flow MUST present it as a **strong
recommendation** and ask before applying.
- `cli-output` and `conversational` — recommend when detected:
- In both modes, the flow MUST present the detected profile as a
recommendation and MUST ask before applying — it MUST NOT be auto-applied, even in trust mode. These profiles document conventions that are less universal than visual design tokens; the developer confirms the repo's rendering/voice layer is worth capturing.
- When a profile's signal is not detected, the flow MUST NOT offer that
profile; when no profile is detected, the flow MUST NOT offer the addon at all (§3.4).
- Declining — any profile, or all of them — MUST always remain possible,
and a declined addon MUST leave a fully baseline-conformant repo. "Default-on when detected" raises the default for the visual profile; it does not make the addon mandatory.
This keeps design-system in the strongest conditional tier among the addons for visual repos — because a repo that has a design system almost always benefits from capturing it as DESIGN.md — while the newer profiles earn their way in explicitly.
---
4. Canonical Sections of DESIGN.md
4.1 Profile composition (one file, stacked sections)
- A single-profile
DESIGN.mdcarries that profile's canonical sections at
the top level — exactly the 2.1.0 shape for visual-ui.
- A multi-profile
DESIGN.mdMUST group each accepted profile's
sections under one top-level heading per profile (e.g. ## Visual UI, ## CLI output, ## Conversational), in any order that fits the repo.
- The file MUST carry exactly one Overview and exactly one Agent
Prompt Guide for the whole file, regardless of profile count; Do's & Don'ts MAY be per profile or combined, as long as every profile's guardrails are present.
- Section titles MAY be adapted to the repo's voice; the substance MUST be
present. Each section is filled by reasoning about the design source, never copied from a brand file or another product's conventions.
4.2 visual-ui canonical sections
1. Overview / Atmosphere — brand personality, emotional tone, the design's intent in one short paragraph. 2. Color Palette & Roles — semantic colors (primary, secondary, neutral, surface, accent, state colors) with values and their functional role; light and dark variants where the repo supports dark mode. 3. Typography — font families, the type scale (sizes/weights/line-heights), and when each level is used. 4. Layout & Spacing — the spacing scale (base unit + steps), grid/container strategy, and whitespace principles. 5. Elevation & Depth — shadow/surface hierarchy and how depth is expressed. 6. Shapes — border-radius scale and corner language; border/hairline treatment. 7. Components — the repo's key UI patterns (buttons, inputs, cards, nav, …) described in terms of the tokens above, including interaction states. 8. Responsive Behavior — breakpoints and touch-target expectations. 9. Do's and Don'ts — explicit guardrails for agent behavior, including accessibility constraints the repo enforces (see §7). 10. Agent Prompt Guide — a short "how to use this file" block telling a downstream agent to follow DESIGN.md and how to reference tokens.
4.3 cli-output canonical sections
1. Output Voice & Intent — how the tool talks in the terminal: terse or verbose, emoji policy, capitalization, error-message register. 2. Semantic Colors & Styles — the success/error/warning/info/highlight/dim roles mapped to the repo's real theme (the rich/chalk/lipgloss styles actually defined), never raw color names chosen ad hoc. 3. Output Components — the repo's rendering patterns: panels vs plain lines, tables, status spinners, progress bars, interactive prompts and pickers — named after the real helpers (print_success, print_panel, …). 4. Layout Conventions — blank-line policy, indentation, width handling, when to use a panel vs a one-liner. 5. Degradation & Environment — TTY vs piped output, NO_COLOR/forced color, narrow terminals, stdout-vs-stderr discipline, exit-code conventions, quiet/JSON output modes where they exist. 6. Do's and Don'ts — guardrails such as "all output goes through the display helper, never raw print() outside it" and the integrity rules of §7. 7. Agent Prompt Guide — shared with the file (§4.1).
4.4 conversational canonical sections
1. Voice & Register — tone, person, brevity targets, language policy, and brand-naming rules (exact product spellings) for outbound messages. 2. Message Anatomy — the envelope kinds the product sends (DM, channel post, thread reply, edit-in-place) and the structure of each: length targets, what a report leads with, what is never included. 3. Platform Rendering — how the same message renders per platform the repo actually targets (e.g. Slack mrkdwn, Discord markdown, Teams adaptive cards, Google Chat, email HTML/plain text). One section; per-platform rows. 4. Do's and Don'ts — guardrails such as audience rules (describe outcomes, never internals like plan IDs or file paths), brand-name spelling, and the plain-text-fallback rule of §7. 5. Agent Prompt Guide — shared with the file (§4.1).
- Values SHOULD be expressed as named tokens with human-readable usage
notes; the file MAY additionally carry a machine-readable token block (e.g. front matter) when the repo already maintains structured tokens, but a Markdown-first table is sufficient and preferred for authorability.
---
5. Reason, Don't Copy
- Every value in
DESIGN.mdMUST be **derived from the repo's real design
source** — the stylesheet, Tailwind config, token files, or component styles; the CLI display/theme module and its helpers; the message-composition layer and its documented voice rules — whatever actually exists.
- The addon MUST NOT paste a third-party brand's
DESIGN.md(e.g. a catalog
entry for Stripe, Linear, or any other product) into the target repo, and MUST NOT import another CLI's or bot's conventions wholesale. Reference catalogs are inspiration for structure, never the content.
- When a value is genuinely undefined in the repo, the addon SHOULD infer the
most consistent value from existing usage and MUST flag it as inferred (so a human can confirm), rather than fabricate an unrelated value.
---
6. Reconcile, Don't Clobber
- If a
DESIGN.md(or an equivalent design-token source) already exists, the
addon MUST reconcile additively — preserving values that already work and bringing the rest toward the canonical-section shape.
- Adding a newly accepted profile to an existing
DESIGN.mdMUST be
additive: append the new profile's sections (grouping per §4.1 when the file becomes multi-profile) without rewriting the existing profile's content.
- The addon MUST NOT overwrite or delete an existing
DESIGN.mdor token file
wholesale. Per AGENT_PROTOCOL.md, any destructive change to an existing file MUST be approved by the developer first.
- The addon MUST record what it changed (added sections/profiles, reconciled
values, inferred values flagged for confirmation).
---
7. Accessibility & Output Integrity
- The Do's and Don'ts MUST capture the repo's **real accessibility and
integrity rules** when the repo documents them, so agents do not regress them.
- `visual-ui`: documented color pairings intended for text SHOULD meet
WCAG AA contrast (4.5:1 normal, 3:1 large) and the addon SHOULD sanity-check the pairings it documents.
- `cli-output`: color MUST NOT be documented as the sole carrier of
meaning (output must stay legible when piped or with NO_COLOR); where the repo honors NO_COLOR/TTY detection, the degradation rules MUST be documented (§4.3.5).
- `conversational`: every documented rich rendering (blocks, cards, HTML)
SHOULD have a plain-text fallback noted for platforms or clients that strip formatting.
- Token references inside
DESIGN.mdMUST resolve — no orphaned or broken
references: a component referencing an undefined token, a documented CLI helper that does not exist in the code, or a documented platform the repo does not actually target.
---
8. Pragmatic Reference, Not Hard Binding
- The addon references the emerging
DESIGN.mdconvention (introduced by
Google Stitch; popularized by community catalogs) as the shape to follow, but MUST NOT hard-bind to that convention's evolving/Alpha format details. The cli-output and conversational profiles extend that shape to non-visual surfaces while keeping the same file and discovery convention.
- DWP's
DESIGN.mdis Markdown-first; adopting any specific machine-readable
token schema (e.g. W3C Design Tokens front matter) is OPTIONAL and applied only when it fits the repo.
---
9. Onboarding Hook + Optional /design-system Delegator
- The addon's onboarding hook (
SKILL.md) is offered byonboardPhase 7b as an
opt-in step, only for repos with a detected interface surface (§3), profile by profile (§3.5), and MUST NOT be applied without acceptance. A declined addon leaves a baseline-conformant repo.
- The addon MAY install a
/design-systemdelegator command into the target
repo's .agents/commands/ (to regenerate/refresh DESIGN.md later; template: templates/design-system-command.md). Installing the command is OPTIONAL; a declined addon installs no command.
---
10. Relationship to Per-Feature Design Docs (positioning)
- This addon provides a repo-level, persistent design-system file. It is
distinct from a per-feature technical design document (the "requirements → design → tasks" design.md of tool-bound spec-driven workflows).
- DeepWorkPlan deliberately does not ship a separate per-feature design-doc
archetype: a DWP plan's README (Goal + Context), each task's Context and Acceptance Criteria, and the validation gates already fulfill the per-feature design role. This addon fills the one gap that role does not cover — durable, repo-native interface design context.
---
11. Validation Step (run after applying)
The addon is correctly applied when all hold:
1. The repo was confirmed to have at least one interface surface (§3), each applied profile's signal was detected from real files, and the addon was skipped for repos with no interface surface of any kind. 2. A DESIGN.md exists with all canonical sections for each accepted profile (§4) — at `docs/DESIGN.md` for a repo with a docs/ tree (DWP-native default), or at the repo root for a repo without one (§2); no sibling per-surface files were created. 3. `AGENTS.md` references `DESIGN.md` in its documentation index (so agents discover it like the other docs/ specs) (§2). 4. Every documented value is traceable to the repo's real design source (§5); no third-party brand file was pasted; inferred values are flagged. 5. An existing DESIGN.md/token source, if present, was reconciled (§6), not clobbered — including when a new profile was added to it; destructive changes were approved. 6. Per-profile integrity holds (§7): documented text color pairings meet WCAG AA (visual-ui); color is not the sole carrier of meaning and degradation rules are documented (cli-output); rich renderings note plain-text fallbacks (conversational); token references resolve (no orphans/broken refs) in every profile. 7. The file is Markdown-first and compact (§2); no build dependency was introduced. 8. New profiles (cli-output, conversational) were asked about before applying — never auto-applied, even in trust mode (§3.5). 9. If a /design-system delegator was offered and accepted, it exists in the repo's .agents/commands/; if declined, none was installed (§9).
---
12. References
- RFC 2119
SKILL.md(the onboarding hook + flow),templates/*(reasoning aids)../README.md(addon mechanism),methodology-spec/ADDONS.md(concept + pointer)AGENT_PROTOCOL.md(approval gates),ARCHETYPES.md(archetypes)- W3C Design Tokens (optional token schema)
- NO_COLOR (CLI color-suppression convention)
---
Part of the DeepWorkPlan methodology v2.1.0, MIT License, by [Dailybot](https://dailybot.com) / dailybotops.
Reasoning template — the "Agent Prompt Guide" block
Every DESIGN.md ends with a short Agent Prompt Guide: a "how to use this file" block that tells a downstream coding agent to follow the design system. Adapt the wording to the repo, keep it to a few lines, and reference the repo's real token names.
---
Drop-in block (adapt the bracketed parts)
## Agent prompt guide
**For coding agents working in this repo:** this `DESIGN.md` is the source of truth
for every interface surface it covers (visual UI, CLI output, outbound messages).
Before generating or editing any user-facing output:
1. **Use the named tokens** in this file (colors, type, spacing, radius — or
semantic CLI styles and message conventions) — do not introduce ad-hoc values
outside it.
2. **Respect roles** — pick a color/style by its *role* (e.g. `color.accent` for
primary actions, the `success` style for completed operations), not by
eyeballing a value.
3. **Keep integrity** — text pairings must meet the contrast targets in Do's &
Don'ts; CLI output must stay legible when piped or colorless; rich messages
keep their plain-text fallback.
4. **Match the documented patterns** — reuse the Button/Input/Card patterns, the
display helpers (`print_success`, panels, spinners), or the message envelopes
and voice rules, with their states.
5. **When something isn't covered**, choose the option most consistent with the
conventions here and note the gap rather than inventing an unrelated style.
Suggested instruction to paste into an agent prompt:
> "Follow `DESIGN.md` strictly. Build [the output] using its tokens, roles, and
> documented patterns; keep the integrity rules (contrast / degradation /
> fallbacks) intact."---
Notes
- Reference the repo's actual token/helper names (e.g.
color.accent,
--color-ink, oxblood, print_success, mrkdwn) so the guidance is concrete, not generic — covering every profile present in the file.
- If the repo installed a
/design-systemdelegator, you MAY mention it here
("run /design-system to refresh this file after design changes").
- Keep this block short — its job is to point agents at the rest of the file, not to
repeat it.
Template — /design-system delegator command (reasoning aid)
This is the delegator command the design-system addon MAY install into the target repo's .agents/commands/design-system.md only when the addon is accepted during onboard Phase 7b (or when the addon is run directly) and the developer wants a one-command way to refresh DESIGN.md later. It is a thin delegator: it carries no logic of its own — it routes to the deepworkplan-addon-design-system addon, which holds the real flow.
Installing this command is optional (SPEC.md §9). Fill the placeholders by reasoning about the target repo (its real design source and accessibility rules); do not copy verbatim. Decline the addon → do not install this command.
---
name: design-system
description: Create or refresh this repo's DESIGN.md (design tokens + rules for AI agents; at docs/DESIGN.md, indexed from AGENTS.md) via the DeepWorkPlan design-system addon.
---
# /design-system
Create or refresh this repository's `DESIGN.md` (at `docs/DESIGN.md`, indexed from
`AGENTS.md`) so coding agents generate interface output — visual UI, terminal
output, or outbound messages — consistent with this repo's **own** conventions.
This command is a **thin delegator** to the DeepWorkPlan
`deepworkplan-addon-design-system` addon — it does not contain the logic itself.
## Steps
1. Invoke the `deepworkplan-addon-design-system` addon (via
`/deepworkplan-addon-design-system` or by reading the addon's `SKILL.md`).
2. Follow the addon's flow: locate this repo's real design source per profile
(<e.g. CSS custom properties in `src/styles/global.css` + a Tailwind `@theme`
block; or the CLI display module; or the message-composition helpers>), reason
out each accepted profile's canonical sections of `DESIGN.md` from that
source, and write or **reconcile** `DESIGN.md` at its location
(`docs/DESIGN.md` for a repo with a `docs/` tree; root otherwise), ensuring
`AGENTS.md` references it.
3. Run the addon's validation step (sections present per accepted profile, values
traceable to the real source, per-profile integrity — WCAG AA contrast /
degradation rules / plain-text fallbacks — and token references resolve).
## Notes
- Profiles in this repo: <fill in — e.g. visual-ui / cli-output / conversational>.
- Design source for this repo: <fill in — e.g. Tailwind config / CSS vars / token file / CLI display module / message helpers>.
- Integrity rules to enforce: <fill in — e.g. WCAG AA + approved/forbidden text colors; NO_COLOR degradation; plain-text fallbacks>.
- Reason about the real tokens — never paste a third-party brand's `DESIGN.md`.
- Reconcile an existing `DESIGN.md`; ask before any destructive change.Reasoning template — DESIGN.md skeleton
This is the annotated skeleton the addon fills by reasoning about the target repo's real design source (stylesheet, Tailwind config, token files, component styles — or a CLI display/theme module, or message-composition helpers). The shape below is fixed; every value is derived from the repo — see SPEC.md §4–§5. Replace each > how to fill note with real content and delete the notes. Keep the result compact (~2–5K tokens single-profile, ≤ ~8K multi-profile) and Markdown-first.
Do not paste a third-party brand's DESIGN.md here, and do not importanother CLI's or bot's conventions wholesale. Reference catalogs are
inspiration for structure only.
Profile composition (`SPEC.md` §4.1): a repo with one accepted profile keeps that profile's sections at the top level (for visual-ui that is exactly the pre-profile shape). A repo with several accepted profiles groups each profile's sections under one top-level heading (## Visual UI, ## CLI output, ## Conversational). Either way the file carries exactly one Overview at the top and exactly one Agent prompt guide at the end.
---
Shared sections (always exactly one of each)
# DESIGN.md — {Project} design system
> Interface-design context for AI coding agents. When generating or editing any
> user-facing output in this repo — UI, terminal output, outbound messages —
> follow this file. Prefer the named tokens below over ad-hoc values.
## Overview
> how to fill: one short paragraph — product personality, tone, the design's
> intent, and WHICH interface surfaces this file covers. Pull from the
> brand/style guide if one exists; otherwise infer and flag it.
<!-- …profile sections (below) go here… -->
## Agent prompt guide
> how to fill: see templates/agent_prompt_guide.md — a short "how to use this
> file" block for downstream agents, covering every profile in the file.---
Profile: visual-ui sections
## Colors
> how to fill: read the real palette (Tailwind theme colors / CSS `--` vars / token
> file). List SEMANTIC roles + values + usage. Include dark-mode variants if the repo
> supports dark mode. Note which pairings are for text (and their contrast).
| Token | Value (light) | Value (dark) | Role / usage |
|-------|---------------|--------------|--------------|
| `color.bg` | `#…` | `#…` | Page background |
| `color.text` | `#…` | `#…` | Primary body text |
| `color.accent` | `#…` | `#…` | Primary actions / links |
| `color.muted` | `#…` | `#…` | Secondary text (must meet WCAG AA) |
| … | | | |
## Typography
> how to fill: real font families + the type scale (size / weight / line-height) and
> when each level is used. Source: font config + heading/body styles.
| Level | Family | Size / weight / line-height | Used for |
|-------|--------|-----------------------------|----------|
| Display | `…` | `…` | Hero / h1 |
| Heading | `…` | `…` | h2–h4 |
| Body | `…` | `…` | Paragraphs |
| Mono | `…` | `…` | Code |
## Layout & spacing
> how to fill: base spacing unit + steps, container/grid strategy, whitespace rules.
- Spacing scale: `{base}` → `{steps}`
- Container / grid: `…`
- Whitespace principle: `…`
## Elevation & depth
> how to fill: shadow/surface hierarchy, how depth is expressed (or "flat, hairline
> rules instead of shadows" if that's the system).
## Shapes
> how to fill: border-radius scale + corner language; border/hairline treatment.
## Components
> how to fill: the repo's key UI patterns described IN TERMS OF the tokens above,
> with interaction states. Cover the components that actually exist.
- **Button (primary):** bg `color.accent`, text `…`, radius `…`, states: hover `…`, focus `…`, disabled `…`
- **Input:** …
- **Card / surface:** …
- **Nav / header:** …
## Responsive behavior
> how to fill: real breakpoints (from the config) + touch-target expectations.
| Breakpoint | Min width | Notes |
|------------|-----------|-------|
| sm | `…` | |
| md | `…` | |
| lg | `…` | |
## Do's and Don'ts
> how to fill: explicit guardrails INCLUDING the repo's accessibility rules
> (approved/forbidden colors, contrast targets). Pull from AGENTS.md / CLAUDE.md.
- DO use the tokens above; DO keep text contrast at WCAG AA (4.5:1 / 3:1).
- DON'T introduce new colors/fonts outside this file.
- DON'T `{repo-specific forbidden patterns}`.---
Profile: cli-output sections
## Output voice & intent
> how to fill: how the tool talks in the terminal — terse vs verbose, emoji
> policy, capitalization, error-message register. Source: existing output +
> any display best-practices doc.
## Semantic colors & styles
> how to fill: the repo's REAL theme — the styles its rendering library
> (rich/chalk/lipgloss/…) actually defines. Map role → style → usage; never
> invent ad-hoc colors.
| Role | Style (real) | Used for |
|------|--------------|----------|
| success | `…` (e.g. green bold) | completed operations |
| error | `…` | failures (stderr) |
| warning | `…` | recoverable issues |
| info | `…` | neutral status |
| highlight | `…` | emphasis (names, counts) |
| dim | `…` | secondary detail |
## Output components
> how to fill: the repo's rendering patterns, NAMED AFTER the real helpers in
> the display module (`print_success`, `print_panel`, spinners, tables,
> interactive prompts/pickers). Cover what actually exists, with when-to-use.
- **`{helper}`** — `…` (when to use)
- **Status spinner** — wraps `…` (e.g. HTTP calls)
- **Interactive prompt / picker** — `…`
## Layout conventions
> how to fill: blank-line policy, indentation, width handling, panel vs
> one-liner decision rule.
## Degradation & environment
> how to fill: TTY vs piped output, NO_COLOR / forced color, narrow terminals,
> stdout-vs-stderr discipline, exit-code conventions, quiet/JSON modes — only
> the behaviors the repo really implements.
## Do's and Don'ts
> how to fill: the integrity guardrails (SPEC §7) + repo rules, e.g.:
- DO route all output through `{display module}`; DON'T raw-`print()` outside it.
- DON'T use color as the only carrier of meaning (piped / NO_COLOR output must stay legible).
- DON'T `{repo-specific forbidden patterns}`.---
Profile: conversational sections
## Voice & register
> how to fill: tone, person, brevity targets, language policy, and EXACT
> brand-name spellings for outbound messages. Source: message helpers + any
> documented voice rules (AGENTS.md, skill docs).
## Message anatomy
> how to fill: the envelope kinds the product sends (DM, channel post, thread
> reply, edit-in-place) and the structure of each — length targets, what a
> message leads with, what is never included.
| Envelope | Structure | Notes |
|----------|-----------|-------|
| DM | `…` | |
| Channel post | `…` | |
| Thread reply | `…` | |
| Edit-in-place | `…` | stable message-id semantics |
## Platform rendering
> how to fill: ONLY the platforms the repo actually targets — how the same
> message renders on each (Slack mrkdwn, Discord markdown, Teams adaptive
> cards, Google Chat, email HTML/plain). Note the plain-text fallback.
| Platform | Rendering | Fallback |
|----------|-----------|----------|
| `…` | `…` | `…` |
## Do's and Don'ts
> how to fill: audience guardrails + integrity rules (SPEC §7), e.g.:
- DO describe outcomes for the audience; DON'T expose internals (plan IDs, file paths, tool names) unless the audience is technical by design.
- DO spell brand names exactly as documented above.
- DON'T document a rich rendering without its plain-text fallback.---
After filling
Run the validation step (SPEC.md §11): all sections present for each accepted profile; values traceable to the repo; inferred values flagged; per-profile integrity holds (WCAG AA pairings / degradation rules / plain-text fallbacks); token references resolve; one Overview + one Agent prompt guide; file compact and Markdown-first; no per-surface sibling files.
Reasoning presets — where a repo's design source lives
Match the row(s) for the detected stack as a starting checklist for where to read the repo's real design values, then verify every assumption against the actual files. Detected reality wins — a repo may combine several sources (and several profiles, SPEC.md §3).
These presets tell you where to look, not what to write. The values you
document come from the repo (SPEC.md §5), never from this file or a brand catalog.---
Profile: visual-ui
Tailwind (v3 config or v4 @theme)
- Tokens:
tailwind.config.{js,ts,cjs,mjs}→theme/theme.extend
(colors, fontFamily, fontSize, spacing, borderRadius, boxShadow, screens). For Tailwind v4, read the @theme { --color-…; --font-…; --spacing-…; } block inside the global CSS instead of a JS config.
- Dark mode:
darkModestrategy +dark:variants in components. - Breakpoints:
theme.screens(or@theme--breakpoint-*). - Components: utility classes in the components reveal real button/input/card patterns.
CSS variables / vanilla / SCSS
- Tokens:
:root { --… }(and a.dark/[data-theme]block) in the global
stylesheet — colors, spacing, radius, shadows, font stacks.
- Type scale: heading/body rules;
clamp()for fluid type. - Breakpoints:
@media (min-width: …)query values. - SCSS:
$variables/@usetoken partials (_tokens.scss,_variables.scss).
Component library / design tokens
- Tokens: a
tokens.{json,ts,js}/theme.{ts,js}export, a Style
Dictionary / W3C design-tokens file, or a theme provider (createTheme, MUI theme, Chakra theme, styled-components ThemeProvider).
- Components: the library's component source + stories (Storybook) show variants
and states; map these to the Components section.
- Reference syntax: if the repo already uses
{path.to.token}-style refs, mirror
that in DESIGN.md; otherwise plain named tokens are fine.
Brand / style guide + accessibility rules
- Brand doc: any
BRAND*.md,STYLE*.md, or design doc — use for the Overview
/ atmosphere and intent.
- Accessibility: contrast targets and approved/forbidden colors are often in
AGENTS.md / CLAUDE.md / an accessibility doc — these feed the Do's & Don'ts.
---
Profile: cli-output
Python CLI (rich / textual / questionary)
- Theme & styles: a central display module (
display.py,console.py,
output.py) — a rich.theme.Theme, semantic print helpers (print_success, print_error, print_panel, …), Console configuration.
- Components:
Panel,Table,Status/spinner wrappers,Progress,
questionary/inquirer prompt and picker wrappers.
- Degradation:
Console(no_color=…)/NO_COLORhandling, TTY checks
(sys.stdout.isatty()), --quiet/--json flags, stderr usage in error helpers.
- Conventions doc: any display/output best-practices doc under
docs/.
Node CLI (chalk / ink / ora / prompts)
- Theme & styles: a shared
colors.*/log.*/ui.*helper wrappingchalk
(or picocolors/kleur); ink components for TUI layouts.
- Components:
oraspinners,cli-table*,boxenpanels,
prompts/inquirer/enquirer wrappers.
- Degradation:
chalk.level/FORCE_COLOR/NO_COLOR,process.stdout.isTTY,
--json output modes, stderr discipline.
Go CLI (cobra / lipgloss / bubbletea)
- Theme & styles:
lipgloss.Styledefinitions (often astyles.go/ui/
package); cobra command output helpers.
- Components:
bubbleteamodels for interactive flows, spinner/table
components (bubbles), confirm/select prompts (survey, huh).
- Degradation:
lipglossprofile detection,NO_COLOR,-o json-style flags.
Rust CLI (clap / colored / indicatif / ratatui)
- Theme & styles:
colored/owo-colorsusage centralized in an output
module; clap help styling.
- Components:
indicatifprogress/spinners,comfy-table,dialoguer
prompts, ratatui TUI views.
- Degradation:
NO_COLOR/CLICOLORhandling,is_terminalchecks,--json.
Weak-signal rule (`SPEC.md` §3.2): a bare argument parser with raw
unstyled prints is NOT a cli-output surface — don't offer the profile whenthere is no deliberate rendering layer to document.
---
Profile: conversational
Slack (slack-sdk / Bolt)
- Voice & helpers: the message-composition layer (report/notify helpers,
block builders); documented tone/brand-naming rules in AGENTS.md or skill docs.
- Rendering:
mrkdwn(*bold*,_italic_), Block Kit blocks; note the
text plain fallback every block message should carry.
- Envelopes: DM vs channel vs thread (
thread_ts), edit-in-place
(chat.update + stored message ids).
Discord (discord.js / discord.py)
- Rendering: standard markdown (
**bold**), embeds; plain-content fallback. - Envelopes: channel messages, replies, ephemeral interaction responses.
Microsoft Teams (botbuilder)
- Rendering: Adaptive Cards JSON + the plain-text
textfallback. - Envelopes: personal vs channel scope, reply chains, activity updates.
Google Chat / Telegram / WhatsApp
- Rendering: per-platform markup subset (Google Chat formatting, Telegram
MarkdownV2/HTML, WhatsApp limited styling) + plain fallback.
Email / SMS / voice
- Rendering: HTML template + plain-text part (email); length limits (SMS);
prompt scripts and re-prompt rules (voice/IVR).
- Voice: transactional register, sender identity, subject conventions.
For every platform: document only the platforms the repo actually targets
(SPEC.md §7) — a documented platform with no code targeting it is a brokenreference.
---
Cross-check before writing
1. Did you read the actual design source (not a guess) for each accepted profile? 2. visual-ui: are dark-mode values captured if the repo supports dark mode? Do the breakpoints match the real config? 3. cli-output: are the degradation behaviors (TTY/pipe, NO_COLOR, stderr, exit codes) the ones the code really implements? 4. conversational: are the documented platforms exactly the ones the repo targets, each with a plain-text fallback? 5. Are the accessibility/integrity rules reflected in Do's & Don'ts? 6. Are any inferred values flagged for human confirmation?
SPEC.md — Devcontainer Addon (Normative)
Abstract
This document is the normative specification of the DeepWorkPlan devcontainer addon: an opt-in capability that gives a repository a compose-based, reproducible, isolated dev container with persistent AI-CLI authentication. It defines the common skeleton every conformant devcontainer shares (RFC-2119), the per-repo reasoning checklist for the parts that vary, project-identity precedence, the validation-in-container rule, the public-OSS variant, and the reconcile-don't-clobber behavior.
The addon is governed by ../README.md and methodology-spec/ADDONS.md: it is never required for baseline AI-first conformance.
Status of This Document
| Field | Value |
|---|---|
| Version | 2.1.0 |
| Status | Stable |
| Companions | SKILL.md, templates/* (reasoning templates + 7 presets), ../README.md, methodology-spec/ADDONS.md |
| License | MIT |
1. Conventions
The RFC 2119 keywords (MUST, MUST NOT, SHOULD, SHOULD NOT, MAY, OPTIONAL) are interpreted as in RFC 2119.
Throughout, {service} is the repo's primary devcontainer service name (e.g. hubvscode, djangovscode, clivscode, webvscode), and {user-home} is the home directory of the container's dev user.
---
2. The Common Skeleton (the stable ~85%)
Every conformant devcontainer MUST follow this skeleton. It was audited as identical across all Dailybot repos + the hub; it is the part the addon carries forward, not re-reasons.
2.1 Compose-based .devcontainer/devcontainer.json
- The repo MUST contain
.devcontainer/devcontainer.json. - It MUST be compose-based: it MUST set
dockerComposeFile
pointing at ../docker/local/docker-compose.{yaml,yml} (it MUST NOT use a bare image/dockerfile-only devcontainer).
- It MUST declare
name,service,workspaceFolder,remoteUser, and
runServices (the dev container service, e.g. ["{service}"]).
customizations.vscode.extensionsMUST include the AI tooling extensions
(Anthropic.claude-code and/or dailybot.dailybot) and SHOULD include stack-appropriate extensions (Python/Pylance for Python, etc.).
- The devcontainer service MUST NOT publish host ports (VS Code forwards
them); host port bindings live on the non-vscode service variants.
2.2 docker/local/{service}/ layout
The container build MUST live under a predictable layout:
.devcontainer/devcontainer.json
docker/
├── local/
│ ├── docker-compose.{yaml,yml} # services + named volumes + network
│ └── {service}/
│ ├── Dockerfile # base image + tooling (reasoned per stack)
│ └── entrypoint.sh # AI-CLI persistence (near-verbatim skeleton)
└── custom_commands.sh # codecheck/check/fix/test + claudex/codexx/cursorx + git aliasesdocker/custom_commands.shMUST exist and be sourced from the dev user's
.bashrc.
- The compose file MAY be accompanied by helpers (
docker.sh,utils.sh)
and OPTIONAL extra service files (e.g. a docker-compose.pgadmin.yaml).
2.3 AI-CLI persistence (the signature pattern — near-verbatim)
This is the highest-value, most stable piece — copy it near-verbatim, adjusting only {user-home} and the user. See templates/entrypoint.md for the full reference script.
- The compose service MUST mount named volumes for each AI/agent CLI:
claude_data, codex_data, cursor_data, gh_data, dailybot_data → {user-home}/.claude_data, .codex_data, .cursor_data, .gh_data, .dailybot_data.
- It MUST mount the host's
${HOME}/.sshand${HOME}/.gitconfig
read-only at {user-home}/.ssh_host and {user-home}/.gitconfig.
- The
entrypoint.shMUST implement seed-on-first-run, preserve-on-rebuild:
for each tool's real config dir (~/.claude + ~/.claude.json + ~/.config/claude-code, ~/.codex, ~/.cursor + ~/.config/cursor, ~/.config/gh, ~/.config/dailybot), if it is not already a symlink, seed the named-volume copy only when empty, remove the original, and symlink it into the persistent volume. SSH keys are copied from the read-only *.ssh_host mount into a writable ~/.ssh with chmod 600/700, only if not already present.
- The result MUST survive
docker compose build/rebuilds: auth and session
state persist in the named volumes. This is why agents stay logged in across container rebuilds.
- The entrypoint MUST end with
exec "$@"so the composecommandruns.
2.4 Shared external network
- The compose file MUST attach services to the shared external network named
`dailybot-project-network` (declared external: true). This lets a repo's container reach sibling services (e.g. the hub or another repo) on the same Docker network. A repo with no cross-service needs MAY still declare it for consistency.
2.5 DOCKER_DEV_ENV=vscode → sleep infinity
- The devcontainer service MUST set
DOCKER_DEV_ENV=vscodeand run
command: sleep infinity (the container stays up for VS Code/agents to attach; it does not run the app).
- A repo that also runs the app in Docker MUST keep a separate non-vscode
service (or compose variant) that runs the real app command and MAY publish host ports. The {service}vscode variant MUST NOT publish host ports.
2.6 custom_commands.sh validation + agent helpers
docker/custom_commands.sh MUST define:
- Validation aliases/functions mapped to the repo's real commands:
codecheck (or check), fix, test. These wrap the repo's actual lint / typecheck / test commands (e.g. ruff check && mypy && pytest, pnpm run eslint:check, astro check). They MUST be the verbatim real commands, never placeholders.
- AI-CLI wrappers
claudex/codexx/cursorx(full-permission /
resume-aware wrappers around claude / codex / agent).
- A git-aware prompt + git aliases + a
check_devcontainerhelper + a
welcome message.
---
3. The Reasoned ~15% — Per-Repo Reasoning Checklist
The addon MUST reason these from the target repo's actual stack, never hardcode one repo's choice. Verify each against detected reality (the matching preset in templates/presets.md is a checklist, not an answer key).
| Decision | How to reason it | Examples observed |
|---|---|---|
| Language → base image | From the manifest + lockfile actually present. | Node → node:24.x-trixie-slim; Python → python:3.x-slim-trixie (or -bullseye). |
| User | Match the base image's convention or create one. | node (node image) vs created dev-user (UID/GID 1000, sudoers). |
| `workspaceFolder` | The mount target for the repo. | /workspace, /app, /code/js. |
| Supporting services | Enumerate from the app's real dependencies — DB / cache / queue / object store / mail / emulators. Add only what the app uses. | postgres, pgvector, redis, mailpit, dynamodb (api-services); dynamodb + localstack-SNS (chatbot); none (web-app, dailybot.com, cli, hub). |
| Ports | The app's real listen ports + service admin UIs; only on non-vscode variants. | 8000 (Django), 5555 (Flower), 8025 (mailpit), 5433/5434 (postgres/pgvector). |
| Multi-stage build | Use when native deps need a build toolchain not wanted at runtime. | api-services: wheel build stage → slim run stage. |
| Extra tooling | Add CLIs the stack needs. | AWS CLI + dynamodb (lambda repos); chromium + Lighthouse (static sites); locales (api-services). |
| Secrets handling | Public vs private (see §5). | private: docker/local/hub/.env; public: secret-free .env.example + .dockerignore. |
A devcontainer is conformant to this addon when it satisfies the §2 skeleton and its §3 choices are demonstrably derived from the repo's real stack (no phantom services, real validation commands).
---
4. Project-Identity Precedence (standardized)
The audit found inconsistent project-name resolution. The addon MUST standardize on this precedence (highest wins):
1. `.dailybot/profile.json` — the committed, credential-free repo identity (project / name). If present, it is authoritative. 2. `DAILYBOT_PROJECT_NAME` — env var (or .dailybot.env / the repo's local env file). 3. `devcontainer.json` `name` — the fallback display name.
- The addon MUST resolve identity in this order and MUST NOT invent a new
name when one already resolves.
- When generating fresh, it SHOULD set a consistent
devcontainer.json name
and, if the repo uses Dailybot reporting, align it with .dailybot/profile.json.
- Credentials MUST NOT be written into
.dailybot/profile.jsonor
devcontainer.json (a key field in the profile is a hard error).
---
5. Public-OSS Variant
When the target repo is public (open source), the addon MUST additionally:
- Add a `.dockerignore` at the repo root (the build context) that
excludes secrets and AI-config: .env, .env.* (but !.env.example), .pypirc, .git, .claude/.claude_data/.codex/.cursor/.gh_data/ .dailybot_data, .devcontainer, node_modules, build/test caches, and OS cruft. This keeps the daemon context lean and secret-free.
- Use a repo-root build context (
build.context: ../..) so the Dockerfile
can COPY the manifest/lockfile, with the .dockerignore keeping it lean.
- Keep `.env.example` secret-free — stub keys with no values; never
commit a real secret.
- Never bake secrets into the image. Secrets arrive at runtime via
env_file / mounts, never via COPY or ENV of a real value.
- Pin dependencies via the lockfile for reproducibility:
COPYthe lock
(e.g. requirements/dev.txt from pip-compile, or pnpm-lock.yaml) and install from it in its own cache layer, so every container/dev/rebuild resolves identical versions.
A private repo MAY keep its real secrets in the canonical env file (e.g. docker/local/{service}/.env, gitignored) but the no-secrets-in-image and lockfile-pinning rules still apply.
---
6. Validation-in-Container Rule + Validation Step
6.1 Validation runs inside the container
- For repos whose validation requires the container (DB, native deps,
service emulators), the addon MUST document that the repo's validation (e.g. api-services' codecheck -f) runs inside the container, and the generated AGENTS.md Quick Commands / docs/DEVELOPMENT_COMMANDS.md MUST flag those commands as Docker-only.
- The
custom_commands.shvalidation aliases (codecheck/check/fix/test)
are the in-container entry points and MUST map to the repo's real commands.
6.2 Addon validation step (run after applying)
The addon is correctly applied when all hold:
1. .devcontainer/devcontainer.json exists, is compose-based, and points at docker/local/docker-compose.{yaml,yml}. 2. The compose file declares the AI-CLI named volumes (claude_data/codex_data/cursor_data/gh_data/dailybot_data), the read-only ${HOME}/.ssh + ${HOME}/.gitconfig mounts, and the dailybot-project-network external network. 3. The devcontainer service sets DOCKER_DEV_ENV=vscode + command: sleep infinity and publishes no host ports. 4. entrypoint.sh implements seed-on-first-run persistence for all five CLIs and ends with exec "$@". 5. custom_commands.sh defines real codecheck/check/fix/test + claudex/codexx/cursorx. 6. Only services the app actually depends on are present (no phantom DBs). 7. Project identity resolves per §4. 8. Public repos: .dockerignore excludes secrets and .env.example is secret-free. 9. Smoke test (best-effort): docker compose build {service} (or, if a build cannot run here, note why). Confirm the repo's validation command runs inside the container.
---
7. Reconcile, Don't Clobber
- On an existing
.devcontainer//docker/, the addon MUST reconcile
additively: keep working ports, network names, env flags, identity, and service definitions; bring missing skeleton pieces (AI-CLI persistence, DOCKER_DEV_ENV=vscode, validation aliases) up to standard.
- The addon MUST NOT overwrite or delete an existing file without explicit
user approval; back up before any unavoidable destructive change.
- It MUST record what it changed (in the onboarding/addon report).
---
8. References
- RFC 2119
SKILL.md(the onboarding hook + flow),templates/*(reasoning aids)../README.md(addon mechanism),methodology-spec/ADDONS.md(concept + pointer)methodology-spec/DOCUMENTATION_STANDARD.md§7 (reason-per-repo),
AGENT_PROTOCOL.md (approval gates), ARCHETYPES.md
---
Part of the DeepWorkPlan methodology v2.1.0, MIT License, by [Dailybot](https://dailybot.com) / dailybotops.
Template — docker/custom_commands.sh (reason, don't copy)
Reasoning template. The agent-CLI wrappers, git-aware prompt, and `check_devcontainer` helper are stable; the validation commands (codecheck/check/fix/test) are reasoned from the repo's real lint / typecheck / test commands.
Sourced from the dev user's .bashrc (the Dockerfile appends source {workspaceFolder}/docker/custom_commands.sh).
The stable parts (keep)
- AI-CLI wrappers —
claudex/codexx/cursorx: full-permission,
resume-aware wrappers around claude / codex / agent (Cursor). These give agents one-word entry points with --dangerously-skip-permissions / --dangerously-bypass-approvals-and-sandbox and -c/-r/-l resume flags.
- `check_devcontainer` — detects
/.dockerenv/REMOTE_CONTAINERS/
CODESPACES and prints whether you're inside the container (and how to get in if not).
- Git-aware prompt (
PROMPT_COMMANDshowing branch + dirty marker) + git
aliases (gs, ga, gc, gp, gl, gd, gco, gcob, ...).
- Welcome message (
show_welcome) for interactive shells.
The reasoned parts (fill from the repo's real commands)
Define codecheck / check, fix, and test as the repo's verbatim real commands. Never ship <your test command here>.
| Alias | Maps to (examples — pick the repo's REAL command) |
|---|---|
codecheck / check | Python: ruff check . && mypy .; Django (api-services): the in-container codecheck (black + mypy [+ pytest]); Node: pnpm run eslint:check && pnpm run type:check; Astro: astro check. |
fix | ruff check --fix . && black . / pnpm run eslint:fix / prettier --write .. |
test | pytest / pnpm test / vitest run / playwright test — the repo's real runner + naming convention. |
#!/bin/bash
# {Project} dev container — custom commands (sourced in .bashrc)
# --- reasoned: real validation commands ---
alias check='{REAL lint+typecheck command}'
alias codecheck='{REAL validation — for api-services this runs INSIDE the container}'
alias fix='{REAL autofix command}'
alias test='{REAL test command}'
# --- stable: agent CLI wrappers (claudex / codexx / cursorx), check_devcontainer,
# git-aware prompt, git aliases, show_welcome ---
# (copy the reference implementations near-verbatim)Decision notes
- Validation-in-container repos (api-services): make clear in the welcome
message and in the generated AGENTS.md that codecheck MUST run inside the container (DB/native deps required). The alias is the in-container entry point.
- Match the repo's package manager in
fix/test(pnpm vs npm vs poetry vs
uv) — infer from the lockfile, never habit.
- Reconcile mode: if
custom_commands.shexists, keep its wrappers/prompt
and only correct the validation aliases to the real commands if they're wrong or missing.
Template — .devcontainer/devcontainer.json (reason, don't copy)
This is a reasoning template, not a file to copy. Fill the {...} placeholders from the target repo's real stack (see presets.md).
What's fixed (the skeleton — keep as-is)
- Compose-based:
dockerComposeFile→../docker/local/docker-compose.{yaml,yml}. service= the vscode service (the one runningsleep infinity).runServices=["{service}"](start only the dev service by default; add
supporting services here only if the dev container needs them up to attach).
customizations.vscode.extensionsMUST include the AI tooling extension(s)
(Anthropic.claude-code, dailybot.dailybot).
What you reason per repo
| Field | Reason from | Examples |
|---|---|---|
name | Project identity precedence (SPEC §4) — .dailybot/profile.json → DAILYBOT_PROJECT_NAME → here. | "Core Hub", "API Services", "Dailybot CLI". |
service | The vscode service name in the compose file. | hubvscode, djangovscode, clivscode, webvscode. |
workspaceFolder | The repo's mount target. | /workspace, /app, /code/js. |
remoteUser | The container's dev user. | dev-user (created) or node. |
| extensions | Stack-appropriate IDE extensions + AI tooling. | Python+Pylance+even-better-toml for Python; ESLint/Volar for Node/Vue. |
Skeleton to adapt
{
"name": "{Project Name — resolved per SPEC §4}",
"dockerComposeFile": "../docker/local/docker-compose.yaml",
"service": "{service}vscode",
"workspaceFolder": "{/workspace | /app | /code/js}",
"runServices": ["{service}vscode"],
"remoteUser": "{dev-user | node}",
"customizations": {
"vscode": {
"extensions": [
// Always: AI tooling
"Anthropic.claude-code",
"dailybot.dailybot"
// + stack-appropriate (reason these): e.g.
// Python: "ms-python.python", "ms-python.vscode-pylance", "tamasfe.even-better-toml"
// Node: "dbaeumer.vscode-eslint", "esbenp.prettier-vscode"
// Vue: "Vue.volar"
// common: "eamodio.gitlens", "vscode-icons-team.vscode-icons"
]
}
}
}Decision notes
- Do not publish ports here. The vscode service publishes no host ports; VS
Code forwards them. Host port bindings live on the non-vscode compose service.
- Hub / orchestrator:
runServicesis just the dev service — no app
services exist.
- Reconcile mode: if a
devcontainer.jsonalready exists, keep its working
name/service/workspaceFolder; only add the AI tooling extensions and the compose-based wiring if missing. Don't churn a working file.
Template — docker/local/docker-compose.{yaml,yml} (reason, don't copy)
Reasoning template. The AI-CLI persistence volumes, the `dailybot-project-network`, and `DOCKER_DEV_ENV=vscode` → `sleep infinity` are the fixed skeleton; services and ports are reasoned per repo.
The fixed skeleton (every repo)
A devcontainer service ({service}vscode) that:
- builds from
docker/local/{service}/Dockerfile, - mounts the repo at
workspaceFolder, - mounts the five AI-CLI named volumes + read-only ssh/gitconfig,
- sets
DOCKER_DEV_ENV=vscodeandcommand: sleep infinity, - publishes no host ports,
- joins
dailybot-project-network.
# name: optional compose project name (e.g. dailybotplatformlocal)
services:
{service}vscode:
container_name: {project-slug} # e.g. dailybot-hub, dailybot-cli
init: true
build:
context: {. | ../..} # repo-root (../..) for public-OSS / COPY-from-root builds
dockerfile: ./{service}/Dockerfile # or ./docker/local/{service}/Dockerfile when context=../..
working_dir: {workspaceFolder}
command: sleep infinity # FIXED — devcontainer stays up; app does NOT run here
environment:
- DOCKER_DEV_ENV=vscode # FIXED — flips entrypoint behavior
env_file:
- {service}/.env # private repos; public repos use a secret-free example
volumes:
- {../.. | .}:{workspaceFolder}
# --- FIXED: AI-CLI persistence (survives rebuilds) ---
- claude_data:{user-home}/.claude_data
- codex_data:{user-home}/.codex_data
- cursor_data:{user-home}/.cursor_data
- dailybot_data:{user-home}/.dailybot_data
- gh_data:{user-home}/.gh_data
- ${HOME}/.ssh:{user-home}/.ssh_host:ro
- ${HOME}/.gitconfig:{user-home}/.gitconfig:ro
# ports: [] # devcontainer publishes NO host ports
networks:
- dailybot
# --- REASONED: only services the app actually depends on (see presets.md) ---
# postgres / pgvector / redis / mailpit / dynamodb / localstack / ... — add per real deps.
volumes:
claude_data: {}
codex_data: {}
cursor_data: {} # Cursor CLI session/auth
dailybot_data: {} # Dailybot CLI config/auth
gh_data: {}
# + REASONED data volumes for any DB/cache you added (e.g. local_postgres14_data)
networks:
dailybot:
name: dailybot-project-network # FIXED — shared external network
external: trueDecision notes
- Where the volumes mount (`{user-home}`) depends on the dev user:
/root
and/or /home/dev-user. Heavier repos (api-services) mount both root and dev-user paths against the same named volumes so the container works whether the app runs as root or the devcontainer attaches as dev-user. A simple repo mounts only the dev-user paths.
- Two-variant pattern (app + vscode): when the app also runs in Docker, keep
a base {service} service (real command, publishes ports) and a {service}vscode variant (YAML anchor <<: *base) that overrides environment: DOCKER_DEV_ENV=vscode, command: sleep infinity, and ports: []. The hub/cli, which only run the dev container, can collapse to a single vscode service.
- Supporting services: add only what the app uses. Give each a healthcheck
if other services depends_on it. Publish their admin/UI ports on the non-vscode variant only (e.g. mailpit 8025, dynamodb-admin 8010).
- Public-OSS:
build.context: ../..+ a root.dockerignore(see SPEC §5). - Reconcile mode: keep existing service names, ports, and network if they
already work; just ensure the five AI-CLI volumes, the ro ssh/gitconfig mounts, the DOCKER_DEV_ENV=vscode/sleep infinity flags, and the network name are present.
Template — docker/local/{service}/Dockerfile (reason, don't copy)
Reasoning template with Node and Python branches. The base image, user, and dependency install are reasoned per repo; the agent-tooling block (install claude/codex/cursor/gh/dailybot CLIs, source custom_commands.sh, pre-create persistence dirs) is the stable part.
Shared across both branches (the stable tooling block)
Every Dockerfile, regardless of language:
1. Installs base tools: sudo git bash-completion nano ssh curl gnupg ca-certificates build-essential. 2. Creates the dev user (or uses the image's) with UID/GID 1000 + passwordless sudo — unless the base image already ships a suitable non-root user. 3. Installs the agent CLIs: GitHub CLI (gh), Dailybot CLI (curl -sSL https://cli.dailybot.com/install.sh | bash), Codex CLI, and — as the dev user — Claude Code (curl -fsSL https://claude.ai/install.sh | bash) and Cursor CLI (curl -fsSL https://cursor.com/install | bash). 4. ENV EDITOR=nano VISUAL=nano GIT_EDITOR=nano. 5. WORKDIR {workspaceFolder}. 6. Copies entrypoint.sh, strips CRLF, chmod +x. 7. Pre-creates {user-home}/.claude_data .codex_data .cursor_data .gh_data .dailybot_data .ssh owned by the dev user. 8. As the dev user: git config defaults + echo 'source {workspaceFolder}/docker/custom_commands.sh' >> ~/.bashrc, then remove any seeded ~/.claude / ~/.claude.json (the entrypoint re-seeds from volume). 9. ENTRYPOINT ["/entrypoint.sh"].
Reason the package manager from the lockfile that exists. Node: enable
Corepack for pnpm/yarn shims if the repo pins packageManager; otherwise plainnpm. Python: poetry / pip-tools / uv as the repo actually uses.
Node branch
FROM node:{24.x}-trixie-slim # reason exact version from .nvmrc / engines / packageManager
# ... base tools (apt) ...
# node image already ships a `node` user (UID 1000); use it OR create dev-user.
# Corepack for pnpm/yarn if the repo pins packageManager:
RUN corepack enable && corepack --version
# gh + dailybot + codex CLIs (system-wide), then USER node/dev-user for claude/cursor.
WORKDIR {/code/js | /app}
# (no app `npm install` in the dev image if you bind-mount the repo; install at runtime)Decision notes (Node):
- User: reuse the image's
nodeuser, or createdev-userfor parity with
Python repos — pick one and keep remoteUser/volume paths consistent.
- Native modules: keep
build-essentialfor packages that compile. - Static-site / Lighthouse: add chromium + its deps (see
static-site
preset) when the build runs headless Chrome.
Python branch
FROM python:{3.x}-slim-trixie # reason exact version from pyproject / .python-version
# ... base tools (apt) ...
RUN groupadd --gid 1000 dev-user && useradd --uid 1000 ... (sudoers)
# Node 24 too (agent CLIs + any JS tooling), gh, dailybot, codex.
# Install deps from the LOCKFILE in its own cache layer (reproducible):
COPY {requirements/dev.txt | poetry.lock+pyproject.toml} /tmp/
RUN pip install --no-cache-dir -r /tmp/requirements-dev.txt # or poetry install
WORKDIR {/app | /workspace}Decision notes (Python):
- Multi-stage when native deps need a build toolchain at build time only
(api-services builds wheels in a python-build-stage, copies them into a slim python-run-stage). A pure-Python CLI does not need multi-stage.
- Locales: generate
en_US/es_ES/pt_PTif the app formats localized
output (api-services).
- Isolated tools: install aggressive-pin tools (e.g.
python-semantic-release) via pipx --global so they don't downgrade the main env (cli repo).
- Lockfile pinning is mandatory for reproducibility (and doubly so for
public-OSS — SPEC §5).
Template — docker/local/{service}/entrypoint.sh (the near-verbatim piece)
This is the one piece you copy near-verbatim. The AI-CLI persistence
pattern is stable across every Dailybot repo. The only things you adapt are
{user-home}(and whether you set it up for one user or bothroot+
dev-user). Do not re-invent it; do not "improve" the seed logic.Why it exists
AI/agent CLIs (claude, codex, cursor, gh, dailybot) store auth + session state under the home directory. Without persistence, every docker compose build logs the agent out. This entrypoint makes that state live in named volumes, so it seeds on first run and survives rebuilds.
The pattern (per tool)
For each tool's real config location, the entrypoint does — idempotently:
1. Ensure the persistent data dir exists ({user-home}/.{tool}_data, backed by a named volume). 2. If the real path (~/.claude, ~/.codex, ~/.cursor, ~/.config/gh, ~/.config/dailybot, ~/.claude.json, ~/.config/claude-code, ~/.config/cursor) is not already a symlink:
- Seed only if the volume copy is empty (
cpreal → data dir), so existing
persisted auth is never clobbered.
- Remove the real path.
- Symlink it into the persistent data dir.
3. chown the data dirs to the dev user.
SSH keys are handled differently: the host ~/.ssh is mounted read-only at ~/.ssh_host; the entrypoint copies each id_* private key (plus *.pub, config, known_hosts) into a writable ~/.ssh with chmod 600/700 — only if keys aren't already present (so a persistent volume isn't overwritten).
The script ends with exec "$@" so the compose command (sleep infinity for the devcontainer) runs as PID 1's child.
Reference skeleton (copy, adjust {user-home} / users only)
#!/bin/bash
# AI-CLI persistence: seed-on-first-run, preserve-on-rebuild.
# Generic helper: link a real path into a persistent volume dir, seeding once.
# $1 = real path, $2 = persistent target (inside the *_data volume)
link_persist() {
local real="$1" target="$2"
if [ ! -L "$real" ]; then
if [ -e "$real" ]; then
# seed only if the volume target is empty/missing
if [ ! -e "$target" ] || [ -z "$(ls -A "$target" 2>/dev/null)" ]; then
mkdir -p "$(dirname "$target")"; cp -r "$real" "$target"
fi
rm -rf "$real"
else
mkdir -p "$target"
fi
mkdir -p "$(dirname "$real")"
ln -sf "$target" "$real"
fi
}
setup_ai_cli_persistence() {
local H="$1" # {user-home}, e.g. /home/dev-user
mkdir -p "$H/.config"
# Claude Code: .claude.json + .claude dir + .config/claude-code (+ .json.backup)
link_persist "$H/.claude.json" "$H/.claude_data/claude.json"
link_persist "$H/.claude" "$H/.claude_data/claude_dir"
link_persist "$H/.config/claude-code" "$H/.claude_data/config_claude_code"
# Codex
link_persist "$H/.codex" "$H/.codex_data/codex_dir"
# Cursor: CLI dir + auth tokens
link_persist "$H/.cursor" "$H/.cursor_data/cursor_dir"
link_persist "$H/.config/cursor" "$H/.cursor_data/config_cursor"
# GitHub CLI
link_persist "$H/.config/gh" "$H/.gh_data/gh_config"
# Dailybot CLI
link_persist "$H/.config/dailybot" "$H/.dailybot_data/config_dailybot"
}
setup_ssh_keys() {
local H="$1"; local SRC="$H/.ssh_host" DST="$H/.ssh"
[ -d "$SRC" ] || return 0
mkdir -p "$DST"
if [ ! -f "$DST/id_rsa" ] && [ ! -f "$DST/id_ed25519" ] && [ ! -f "$DST/id_ecdsa" ]; then
cp "$SRC"/id_* "$DST/" 2>/dev/null || true
cp "$SRC"/*.pub "$DST/" 2>/dev/null || true
cp "$SRC/config" "$DST/config" 2>/dev/null || true
cp "$SRC/known_hosts" "$DST/known_hosts" 2>/dev/null || true
fi
chmod 700 "$DST" 2>/dev/null || true
chmod 600 "$DST"/id_* "$DST/config" 2>/dev/null || true
}
# Adjust to your dev user. Heavier repos run this for BOTH /root and /home/dev-user.
setup_ai_cli_persistence "{user-home}"
setup_ssh_keys "{user-home}"
chown -R {dev-user}:{dev-user} {user-home}/.claude_data {user-home}/.codex_data \
{user-home}/.cursor_data {user-home}/.gh_data {user-home}/.dailybot_data \
{user-home}/.ssh {user-home}/.config 2>/dev/null || true
exec "$@"Decision notes
- The reference repos write this as explicit per-tool functions rather than
the compact link_persist helper above — both are valid; prefer whichever matches the repo's existing style on reconcile. The behavior (seed-once, symlink, preserve, exec "$@") is what MUST be preserved.
- Single vs dual user: the hub/cli run as
dev-useronly → one call. The
api-services container can run as root (app) or dev-user (devcontainer) → call the setup for both home dirs against the same named volumes.
- CRLF: the Dockerfile strips
\rfrom the script beforechmod +x. - Never seed over existing auth: the
[ -z "$(ls -A ...)" ]guard is what
keeps a rebuild from wiping a logged-in session — keep it.
<Agent Title>
Role
<The agent's responsibility and scope.>
Inputs
<What the agent expects to receive.>
Process
1. <Step one.> 2. <Step two.>
Output
<What the agent produces.>
Notes
<Constraints, escalation rules. Keep the model tier abstract — map it to a concrete model ID in repo config, not here.>
<Skill Title>
Goal
<What this skill accomplishes in one or two sentences.>
When to use
<Triggers / situations where this skill applies.>
Steps
1. <Step one.> 2. <Step two.> 3. <Step three.>
Validation
<How to confirm the skill succeeded.>
Notes
<Edge cases, gotchas, references.>
/agent-create — provided by the deepworkplan skill
Thin alias. The flow lives in the installed deepworkplan skill — this fileonly routes to it, so there is a single source of truth and no drift.
What to do
Route this invocation to the author sub-skill of the installed deepworkplan skill and follow its Create an agent flow: read <skill-path>/deepworkplan/author/SKILL.md and execute it, passing along any arguments as the agent name/role. Choose a model tier with justification and keep this repo's .agents/docs/ catalog in sync.
Other agents: invoke the skill's deepworkplan-author sub-skill directly(/deepworkplan-authorin Claude Code,#deepworkplan-authorelsewhere). This
agent-create file is the shorter, conventional alias./dwp-create — provided by the deepworkplan skill
Thin alias. The flow lives in the installed deepworkplan skill — this fileonly routes to it, so there is a single source of truth and no drift.
What to do
Route this invocation to the create sub-skill of the installed deepworkplan skill and follow it: read <skill-path>/deepworkplan/create/SKILL.md and execute its flow. Plan and draft outputs land in this repo's gitignored .dwp/ (.dwp/plans/, .dwp/drafts/) — never the legacy .agent_commands/agent_deep_work_plans/results/ path.
Other agents: invoke the skill's deepworkplan-create sub-skill directly(/deepworkplan-createin Claude Code,#deepworkplan-createelsewhere). This
dwp-create file is the shorter, conventional alias./dwp-execute — provided by the deepworkplan skill
Thin alias. The flow lives in the installed deepworkplan skill — this fileonly routes to it, so there is a single source of truth and no drift.
What to do
Route this invocation to the execute sub-skill of the installed deepworkplan skill and follow it: read <skill-path>/deepworkplan/execute/SKILL.md and execute its flow. Plan and draft outputs land in this repo's gitignored .dwp/ (.dwp/plans/, .dwp/drafts/) — never the legacy .agent_commands/agent_deep_work_plans/results/ path.
Other agents: invoke the skill's deepworkplan-execute sub-skill directly(/deepworkplan-executein Claude Code,#deepworkplan-executeelsewhere). This
dwp-execute file is the shorter, conventional alias.