-
Notifications
You must be signed in to change notification settings - Fork 4
Plugin Rules
Five non-negotiable rules. They apply to every skill and override any conflicting instruction.
Important
These rules live in claude-ops/CLAUDE.md at the plugin root. Claude Code loads them automatically whenever a skill runs, so every skill starts with these constraints in its system context.
claude-ops gives agents real power — they can merge PRs, deploy services, send messages, spend money on ads. That power needs a guardrail layer:
flowchart LR
U[User intent] --> S[Skill]
S --> R[Rule engine]
R -->|Rule 0| PUB[Public-repo safe]
R -->|Rule 1| UI[UI schema valid]
R -->|Rule 2| AUTO[No baton-passing]
R -->|Rule 3| CHOICE[Explicit choices]
R -->|Rule 4| FAST[Background by default]
R -->|Rule 5| CONFIRM[Per-action confirm]
R --> A[Action]
classDef bad fill:#ef4444,color:#fff,stroke:#b91c1c
classDef good fill:#22c55e,color:#fff,stroke:#15803d
classDef neutral fill:#6366f1,color:#fff,stroke:#4338ca
class PUB,UI,AUTO,CHOICE,FAST,CONFIRM good
class U,S,R,A neutral
Warning
This repo is public and open-source. Every file is visible to anyone on the internet. Real names, emails, store URLs, API keys, or paths that reveal a user's identity are a privacy leak — even in example code.
| Category | Bad | Good |
|---|---|---|
| Identity | "owner": "Alice Cooper" |
"owner": "owner" |
alice@acme.com |
user@example.com |
|
| Phone | +15551234567 |
+1234567890 |
| Store URL | acme-store.myshopify.com |
yourstore.myshopify.com |
| Project name | "alias": "acme-app" |
"alias": "my-app" |
| API key | sk_live_abc123... |
<YOUR_TOKEN> or $STRIPE_SECRET_KEY
|
| GitHub slug | acme-inc/acme-app |
your-org/your-repo |
| Path | /Users/alice/Projects/... |
~/Projects/... or $HOME/Projects/...
|
$PREFS_PATH = ~/.claude/plugins/data/ops-ops-marketplace/preferences.json (never committed)
$CLAUDE_PLUGIN_ROOT/scripts/registry.json (gitignored)
Environment variables (never in source)
Doppler / Password manager (never in source)
Tip
Run tests/test-no-secrets.sh before every commit. It grep-checks for common leak patterns (real domains, sk_live_, hardcoded paths) and fails loudly.
The AskUserQuestion tool enforces a hard schema limit of <= 4 items in the options array. Passing more than 4 options returns an InputValidationError and the skill crashes mid-conversation.
flowchart LR
A[N items needed] --> B{N > 4?}
B -->|No| C[Single AskUserQuestion]
B -->|Yes| D[Filter already-configured]
D --> E{Still > 4?}
E -->|No| C
E -->|Yes| F[Batch into groups of <=4]
F --> G[Last option of each batch<br/>except last<br/>= <i>More options...</i>]
classDef ok fill:#22c55e,color:#fff,stroke:#15803d
classDef bad fill:#ef4444,color:#fff,stroke:#b91c1c
class C,G ok
Batch 1 (4 options) Batch 2 (4 options) Batch 3 (3 options)
[Install CLIs] [Configure channels] [Configure ecommerce]
[Background daemon] [Companion plugins] [Configure marketing]
[Configure MCPs] [Save preferences] [Configure voice]
[More options...] ──────► [More options...] ──────► [Configure revenue]
Note
Dynamic lists (projects, vaults, configs) MUST paginate at 4/page. Multi-select follows the same limit — 4 checkboxes max per call.
Warning
Telling the user to "run this in a separate terminal" is lazy and breaks the flow. Run commands via the Bash tool — that's what it's for.
| Scenario | Bad | Good |
|---|---|---|
OAuth (gog auth add) |
"Run gog auth add in your terminal" |
Bash("gog auth add", run_in_background: true) |
| Doppler login | "Run doppler login" |
Bash("doppler login", run_in_background: true) |
| Password manager unlock | "Run bw unlock yourself" |
Bash("bw unlock …") direct |
| npm install | "Please run npm i -g ..." |
Bash("npm i -g ...", run_in_background: true) |
| QR-based WhatsApp auth | "Run wacli auth in a terminal" |
This is the one exception — point phone at QR |
The QR code genuinely requires the user's phone camera pointed at the terminal. No amount of backgrounding fixes that. This is the only case where the skill tells the user to act in a separate terminal.
Every other OAuth flow (Doppler, gog, Shopify, Stripe) opens a browser — which happens automatically whether Bash runs it or the user does, so the skill runs it.
Warning
If auto-scan returns empty for a credential, that is precisely when the user needs to be asked. Silently skipping a service because scanning found nothing is a privacy footgun (the user doesn't know they're missing integration X) and a usability footgun (they have to re-run setup to discover it).
When a credential isn't found OR a smoke test fails, the skill MUST present:
<SERVICE_NAME> — no credential found.
[Paste manually] — accept free-text input now
[Deep hunt] — spawn a general agent to exhaustively search
[Skip] — user explicitly declines
Only the explicit [Skip] option allows the flow to continue past the service. No other escape hatch.
| Anti-pattern | Consequence |
|---|---|
| Auto-skip when env var missing | User never learns Shopify integration exists |
| Auto-skip when smoke test fails | Silent half-broken state — /ops:ecom errors out later |
| Fall through on scan-empty | Privacy leak — user may have the key in a vault the scanner didn't probe |
Tip
The "Deep hunt" option spawns a general-purpose agent that exhaustively searches every Doppler project, every Keychain service-name pattern, every shell profile, every .env file under ~/Projects/, and browser sessions — before giving up. This is what makes the wizard feel omniscient.
During /ops:setup and any skill's setup flow, every Bash call uses run_in_background: true unless the result is needed for the very next decision.
- CLI installs (
brew install …,apt install …) - OAuth flows (browser opens automatically)
- npm installs, git clones,
wacli authhelpers - All credential scans (Doppler, Keychain, Chrome history, vault queries)
- Smoke tests
- Autolink scripts
Setup has ~12 independent steps. Each step has ~3 independent probes. Serial execution = 60+ seconds of dead air while the user stares at "Running…". Background execution + parallel probes = <10 seconds total elapsed time.
Note
While a background command runs, the wizard continues to the next independent step — or asks the user the next question. Results are checked when the notification arrives. The conversation never blocks on a command the user isn't actively waiting for.
Caution
This is the strictest rule. NEVER execute — or recommend executing — any destructive action without a specific, per-action AskUserQuestion confirmation. Batch confirmations are allowed ("Delete these 3 idle ALBs?") but silent execution is never allowed.
| Category | Examples |
|---|---|
| Infra deletion | ECS clusters · RDS · ALBs · NAT gateways · S3 buckets · Lambdas |
| Service stop/scale-down | Stopping services · scaling to 0 |
| Domain cancellation | Cancel auto-renewal · release domain |
| Git history rewrite |
git filter-repo · git rebase -i · git push --force
|
| Repo destruction | Archive repo · delete repo |
| CI/CD disabling | Disable workflows · delete pipelines |
| Container purge | ECR · Docker image delete |
| Observability nuke | Delete CloudWatch alarms or log groups |
Any AWS delete-* / stop-* / terminate-*
|
aws ec2 terminate-instances, aws rds delete-db-instance, etc. |
For CTO, CFO, COO, CEO agents that recommend destructive changes:
- Verify status first — check recent commits, active branches, planning directories, registry status before labeling anything "dead" or "archived"
- Distinguish idle vs dead — "0 tasks but active" ≠ "abandoned, no commits for months"
-
Flag with
⚠️ REQUIRES CONFIRMATIONso orchestrators know to ask - Never assume scaled-to-zero = dead — may be between deployments
/ops:yolo, /ops:orchestrate, /ops:go — before executing any destructive recommendation from a C-suite agent:
⚠️ REQUIRES CONFIRMATION — CTO recommends:
Delete ECS cluster "legacy-staging" (scaled to 0 since 2026-02-14)
[Execute] — run aws ecs delete-cluster
[Skip] — leave as-is
[Ask CTO again] — request more context
[Mark allowlist] — add to registry.allowlist.ecs_clusters
Important
Rule 5 is what makes YOLO mode safe. The agents are fully autonomous until they hit a destructive action — then they stop and ask. No exceptions.
| Rule | Short form | Callout type |
|---|---|---|
| 0 | Public repo — no personal data ever | > [!WARNING] |
| 1 |
AskUserQuestion <= 4 options |
> [!NOTE] |
| 2 | Run commands yourself (except wacli auth) |
> [!NOTE] |
| 3 | Never auto-skip — always give explicit choice | > [!WARNING] |
| 4 | Background by default during setup | > [!TIP] |
| 5 | Destructive actions = per-action confirm | > [!CAUTION] |
- Privacy and Security — how the rules protect user data
- Architecture — where the rules get loaded
- CLAUDE.md source
- Changelog — v0.8.0 introduced Rule 0 and formalized Rules 1–5