Skip to content

Commit 536b81a

Browse files
docs(ops-mode): add global scope, ops list, and collision guard to README and site
Adds the global ops scope (~/.claude/ops/), /mdd ops list command, collision guard rule, and updated directory structure to both README.md and docs/index.html. Keeps both doc surfaces in sync with the full ops mode feature as implemented in mdd.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 7d8f430 commit 536b81a

2 files changed

Lines changed: 125 additions & 19 deletions

File tree

README.md

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -444,15 +444,29 @@ npm: [mdd-tui](https://www.npmjs.com/package/mdd-tui) · GitHub: [TheDecipherist
444444

445445
> **The flaw MDD had:** Deployment and infrastructure tasks had no documentation home. Running `/mdd dokploy-deploy` defaulted to Build Mode and skipped the documentation phases — because deploying services isn't a feature to build. Ops Mode fixes this.
446446
447-
MDD now treats deployments as first-class citizens. Every deployment target gets a structured runbook in `.mdd/ops/`. Write it once — then `runop` executes it every time, with live health checks, verified steps, and canary-gated multi-region rollout.
447+
MDD now treats deployments as first-class citizens. Every deployment target gets a structured runbook — either project-local or global. Write it once — then `runop` executes it every time, with live health checks, verified steps, and canary-gated multi-region rollout.
448448

449-
### The Three Commands
449+
### Commands
450450

451451
| Command | What it does |
452452
|---|---|
453-
| `/mdd ops <description>` | Create a new deployment runbook — asks about services, regions, images, credentials, webhooks, and deployment strategy |
454-
| `/mdd runop <slug>` | Execute the runbook — pre-flight health check → canary-gated region deploy → post-flight verify |
455-
| `/mdd update-op <slug>` | Edit an existing runbook — re-asks questions with current values pre-filled, shows a diff before writing |
453+
| `/mdd ops <description>` | Create a runbook — **first question is always: global or project?** |
454+
| `/mdd ops list` | List all runbooks — global and project — with last-run health status |
455+
| `/mdd runop <slug>` | Execute a runbook — checks project-local first, then global |
456+
| `/mdd update-op <slug>` | Edit an existing runbook — same lookup order |
457+
458+
### Global vs Project Scope
459+
460+
The **first thing `/mdd ops` asks** is where the runbook should live:
461+
462+
| Scope | Location | Use for |
463+
|---|---|---|
464+
| **Project** | `.mdd/ops/<slug>.md` | This project only (e.g., deploy this specific app to Dokploy) |
465+
| **Global** | `~/.claude/ops/<slug>.md` | Reusable across all projects (e.g., update Cloudflare DNS, renew SSL certs, Docker Hub login) |
466+
467+
> **Global ops cannot access project-local `.env` variables or project paths.** They use `~/.env` globals only — which is exactly right for infrastructure procedures that don't belong to any one project.
468+
469+
**Global is the authoritative namespace.** If a global runbook named `cloudflare-dns` exists, no project can create a local runbook with the same name. This prevents any ambiguity about which runbook `runop` will execute — you always know exactly what runs.
456470

457471
### Write Once, Runs Every Time
458472

@@ -538,12 +552,36 @@ deployment_strategy:
538552
`on_gate_failure: rollback` — canary fails, auto-rollback EU, primary untouched.
539553
`on_gate_failure: skip_region` — skip the failed region and continue to primary (useful when EU is lower priority).
540554

541-
### What Lives in `.mdd/ops/`
555+
### Listing All Runbooks
556+
557+
```bash
558+
/mdd ops list
559+
```
560+
561+
```
562+
📦 Ops Runbooks
563+
564+
Global (~/.claude/ops/)
565+
cloudflare-dns DNS record updates via Cloudflare API last run: 2026-04-10
566+
ssl-renewal Let's Encrypt cert renewal (Certbot) last run: never
567+
568+
Project (.mdd/ops/)
569+
rulecatch-dokploy 10 services → eu-west (canary) + us-east last run: 2026-04-18 ✓ all healthy
570+
swarmk-dokploy 7 services → eu-west (canary) + us-east last run: 2026-04-17 ⚠ api degraded
542571

572+
Run /mdd runop <slug> to execute any runbook.
543573
```
574+
575+
### Where Runbooks Live
576+
577+
```
578+
~/.claude/ops/ ← global runbooks (all projects)
579+
cloudflare-dns.md
580+
ssl-renewal.md
581+
544582
.mdd/
545-
├── docs/ ← feature docs (type: feature | task)
546-
└── ops/ ← deployment runbooks (type: ops)
583+
├── docs/ ← feature docs (type: feature | task)
584+
└── ops/ ← project runbooks (this project only)
547585
├── rulecatch-dokploy.md
548586
├── swarmk-dokploy.md
549587
└── archive/

docs/index.html

Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -672,22 +672,80 @@ <h2>Ops Mode <span style="background: linear-gradient(135deg, #f59e0b, #ef4444);
672672
<strong>What Ops Mode fixes:</strong> MDD's original flaw &mdash; deployment and ops tasks had no documentation home. They fell into Build Mode or were skipped entirely. Ops Mode gives deployments the same document-first discipline as features. Write the runbook once; <code>/mdd runop</code> executes it every time.
673673
</div>
674674

675-
<h3>The Three Commands</h3>
675+
<h3>The Four Commands</h3>
676676
<div class="commands-grid" style="margin-bottom: 2rem;">
677677
<div class="command-card">
678678
<h3><code>/mdd ops &lt;description&gt;</code></h3>
679-
<p class="command-desc">Create a new deployment runbook in <code>.mdd/ops/</code>. Interviews you about services, regions, health checks, rollback criteria, and deployment strategy. Produces a structured YAML-frontmatter runbook that <code>runop</code> can execute.</p>
679+
<p class="command-desc">Create a new deployment runbook. First asks: global (<code>~/.claude/ops/</code>) or project-scoped (<code>.mdd/ops/</code>)? Interviews you about services, regions, health checks, rollback criteria, and deployment strategy. Produces a structured YAML-frontmatter runbook that <code>runop</code> can execute.</p>
680680
</div>
681681
<div class="command-card">
682682
<h3><code>/mdd runop &lt;slug&gt;</code></h3>
683-
<p class="command-desc">Execute a runbook end-to-end: pre-flight health check &rarr; canary-gated region deploy &rarr; post-flight verify. Reads the ops doc as the source of truth. Executes step-by-step with verification at each step. If any gate fails, execution stops &mdash; the next region is never touched.</p>
683+
<p class="command-desc">Execute a runbook end-to-end: pre-flight health check &rarr; canary-gated region deploy &rarr; post-flight verify. Checks project-local first, then global. Reads the ops doc as the source of truth. If any gate fails, execution stops &mdash; the next region is never touched.</p>
684684
</div>
685685
<div class="command-card">
686686
<h3><code>/mdd update-op &lt;slug&gt;</code></h3>
687-
<p class="command-desc">Edit an existing runbook. Updates services, regions, health endpoints, rollback criteria, or deployment strategy. Re-validates the runbook structure after editing so <code>runop</code> always has a consistent doc to execute from.</p>
687+
<p class="command-desc">Edit an existing runbook. Checks project-local first, then global. Updates services, regions, health endpoints, rollback criteria, or deployment strategy. Re-validates the runbook structure after editing.</p>
688+
</div>
689+
<div class="command-card">
690+
<h3><code>/mdd ops list</code></h3>
691+
<p class="command-desc">Show all runbooks &mdash; global and project-scoped &mdash; in a unified view. Displays slug, scope, platform, environments, and status so you can see everything available at a glance.</p>
688692
</div>
689693
</div>
690694

695+
<h3>Global vs Project Scope</h3>
696+
<p><code>/mdd ops</code> asks scope as its very first question. The answer controls where the runbook is stored and how it is shared.</p>
697+
698+
<div style="overflow-x: auto; margin: 1.5rem 0;">
699+
<table style="width: 100%; border-collapse: collapse; font-size: 0.9em;">
700+
<thead>
701+
<tr style="background: var(--bg-secondary);">
702+
<th style="text-align: left; padding: 0.75rem 1rem; border-bottom: 2px solid var(--border);">Scope</th>
703+
<th style="text-align: left; padding: 0.75rem 1rem; border-bottom: 2px solid var(--border);">Location</th>
704+
<th style="text-align: left; padding: 0.75rem 1rem; border-bottom: 2px solid var(--border);">Available</th>
705+
<th style="text-align: left; padding: 0.75rem 1rem; border-bottom: 2px solid var(--border);">Use for</th>
706+
</tr>
707+
</thead>
708+
<tbody>
709+
<tr>
710+
<td style="padding: 0.75rem 1rem; border-bottom: 1px solid var(--border);"><strong>Global</strong></td>
711+
<td style="padding: 0.75rem 1rem; border-bottom: 1px solid var(--border);"><code>~/.claude/ops/&lt;slug&gt;.md</code></td>
712+
<td style="padding: 0.75rem 1rem; border-bottom: 1px solid var(--border);">All projects</td>
713+
<td style="padding: 0.75rem 1rem; border-bottom: 1px solid var(--border);">Docker Hub login, DNS updates, Vercel deploys, reusable infrastructure tasks</td>
714+
</tr>
715+
<tr>
716+
<td style="padding: 0.75rem 1rem;"><strong>Project</strong></td>
717+
<td style="padding: 0.75rem 1rem;"><code>.mdd/ops/&lt;slug&gt;.md</code></td>
718+
<td style="padding: 0.75rem 1rem;">This project only</td>
719+
<td style="padding: 0.75rem 1rem;">Service-specific deploys, project env vars, region-specific image names</td>
720+
</tr>
721+
</tbody>
722+
</table>
723+
</div>
724+
725+
<div class="callout" style="background: rgba(245, 158, 11, 0.08); border-left: 4px solid #f59e0b; padding: 1rem 1.25rem; border-radius: 0.5rem; margin-bottom: 1.5rem;">
726+
<strong>Global scope note:</strong> Global ops cannot read project-local <code>.env</code> variables or project paths. They have access to <code>~/.env</code> globals only. If your runbook needs <code>DOCKER_HUB_TOKEN</code> or other global secrets, store them in <code>~/.env</code> and reference them there.
727+
</div>
728+
729+
<div class="callout" style="background: rgba(239, 68, 68, 0.08); border-left: 4px solid #ef4444; padding: 1rem 1.25rem; border-radius: 0.5rem; margin-bottom: 2rem;">
730+
<strong>Collision guard:</strong> Global namespace is authoritative. If a global op named <code>docker-hub-push</code> already exists, you cannot create a project op with the same slug. This is a hard stop &mdash; no silent shadowing. Rename one of them to avoid ambiguity.
731+
</div>
732+
733+
<h3>Listing All Runbooks</h3>
734+
<p><code>/mdd ops list</code> shows all runbooks across both scopes in a unified view:</p>
735+
<pre><code class="language-text">Ops Runbooks
736+
────────────────────────────────────────────────────────────
737+
738+
Global (~/.claude/ops/)
739+
docker-hub-login docker-hub all projects complete
740+
dns-cloudflare manual all projects draft
741+
742+
Project (.mdd/ops/)
743+
rulecatch-dokploy dokploy staging, prod in_progress
744+
api-rollback manual production draft
745+
746+
4 runbooks total (2 global, 2 project)
747+
Run /mdd runop &lt;slug&gt; to execute any runbook.</code></pre>
748+
691749
<h3>The Runbook Concept</h3>
692750
<p>A runbook is a structured ops document in <code>.mdd/ops/</code> with YAML frontmatter declaring services, regions, deployment order, health check endpoints, and gate behaviour. It is the single source of truth for a deployment. <code>/mdd runop</code> reads it and executes it &mdash; you do not hand-craft the sequence each time.</p>
693751
<p><strong>Write once, runs every time.</strong> Once a runbook exists, every future deployment of that service runs through the same documented sequence, with the same pre-flight checks, the same canary gate, and the same post-flight verification. Nothing falls through the cracks because someone forgot a step.</p>
@@ -768,18 +826,28 @@ <h3>Gate Behaviour</h3>
768826
</div>
769827
</div>
770828

771-
<h3>The <code>.mdd/ops/</code> Directory</h3>
772-
<p>All ops runbooks live in <code>.mdd/ops/</code>, alongside feature docs and audit artifacts:</p>
773-
<pre><code class="language-bash">.mdd/
829+
<h3>Directory Structure</h3>
830+
<p>Project runbooks live in <code>.mdd/ops/</code>. Global runbooks live in <code>~/.claude/ops/</code> alongside your other global Claude config:</p>
831+
<pre><code class="language-bash"># Project-scoped runbooks (this project only)
832+
.mdd/
774833
├── docs/ # Feature documentation
775-
├── ops/ # Deployment runbooks (Ops Mode)
834+
├── ops/ # Project deployment runbooks
776835
│ ├── rulecatch-dokploy.md # Multi-region Dokploy deploy runbook
777836
│ └── api-rollback.md # Emergency rollback runbook
778837
├── initiatives/
779838
├── waves/
780-
└── audits/</code></pre>
781-
782-
<p>Runbooks are gitignored by default alongside the rest of <code>.mdd/</code> &mdash; they contain environment-specific configuration (region URLs, health endpoints, image names) that belongs in your local workspace, not version control.</p>
839+
└── audits/
840+
841+
# Global runbooks (available in every project)
842+
~/.claude/
843+
├── commands/ # Global slash commands
844+
├── skills/ # Global skills
845+
├── ops/ # Global deployment runbooks ← NEW
846+
│ ├── docker-hub-login.md # Reusable Docker Hub auth runbook
847+
│ └── dns-cloudflare.md # DNS update runbook (any project)
848+
└── CLAUDE.md</code></pre>
849+
850+
<p>Project runbooks are gitignored by default alongside the rest of <code>.mdd/</code> &mdash; they contain environment-specific configuration (region URLs, health endpoints, image names) that belongs in your local workspace, not version control. Global runbooks persist in your home directory and are never project-specific.</p>
783851
</section>
784852

785853
<!-- Featured Packages -->

0 commit comments

Comments
 (0)