agentleFS
PlayQodeXPlayQodeX/claude-code-blockers/.claude/skills/blockers/SKILL.md

blockers

Skill1 starsChanged 7 months agoMITView on GitHub

Track external blockers that need user input (API keys, scope decisions, vendor selections, CPA reviews) outside the chat. Use when the user runs /blockers, /blockers <id-or-name>, /blockers resolved, /blockers add, or /blockers check. Also surface this skill proactively when a workstream is parked because of a missing key, a deferred architecture decision, or any "needs founder input" condition — offer to register it as a blocker.

  • Reads credentials

1 other project uses a version of this.

Adopted by

Most recently taken up by

  • Other versions1 project uses a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 1

    1. veraetogrex-portfolio/solo-sdd★ 0same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

The file

Show its rules and text

We split this skill into the rules it gives an agent

15 rules. About 0 are common, 5 are distinctive, and 10 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈5

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 10

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Every blocker carries these fields:

    line 28
  2. Very specific:

    Default action. Print the table view of every unresolved blocker, sorted by urgency (P0 first), then by daysOpen desc within each urgency …

    line 69
  3. Very specific:

    After the table: N unresolved (P0: x, P1: y, P2: z, P3: w) · M resolved-detected · K resolved.

    line 81
  4. Very specific:

    After any state change, append a one-line entry to the ## Resolution log section at the bottom of blockers.md with timestamp + actor (user) …

    line 95
  5. Very specific:

    After confirmation, append a new YAML block to blockers.md under the ## Blockers section.

    line 120
  6. Distinctive:

    Read the named env file.

    line 125
  7. Distinctive:

    Check whether each listed env var is present and non-empty.

    line 126
  8. Very specific:

    If all vars present → flip status to resolved-detected (or stay there).

    line 127
  9. Very specific:

    If any vars missing → keep status as unresolved.

    line 128
  10. Very specific:

    Never write secrets anywhere: Not to blockers.md, not to a log file, not to the chat output.

    line 138
  11. Very specific:

    When refused, tell the user: "drop that into <app>/<env-file> directly, then run /blockers check."

    line 143
  12. Very specific:

    Cross-app aware display: Always show the app field in the table view AND the focused-card view.

    line 147
  13. Very specific:

    Prefix collision rule: if two apps share a prefix, /blockers add refuses and asks the user to disambiguate.

    line 284
  14. Distinctive:

    When the assistant hits a wall that the user could resolve but the assistant cannot — a missing API key, a deferred architecture decision …

    line 290
  15. Distinctive:

    Do NOT auto-register. The user opts in.

    line 294

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

/blockers — workspace blocker registry

A workspace-scoped registry for things the assistant cannot resolve on its own — API keys, vendor selections, architectural decisions, regulatory engagements, anything that needs information from outside the chat.

The user invokes this with /blockers [subcommand]. The skill is the file at .claude/skills/blockers/ plus a hand-curated registry at the workspace root.


Files this skill reads and writes

PathPurposeEditable by skill?
<workspace-root>/blockers.mdThe registry. Hand-seeded once; the skill flips status fields and updates daysOpen on every read.Yes — status, resolvedAt, and daysOpen only. Never overwrites the body.
<workspace-root>/blockers.config.yamlWorkspace setup (apps, env file paths, app prefixes). Created once at install.Read-only after install.
<app>/.env, <app>/.env.local, <app>/.env.exampleSource of truth for resolved env-var blockers.Read-only. The skill never writes secrets to any file.

Path resolution. The skill always operates at the workspace root (the directory that contains blockers.md). If blockers.md is missing, the skill prompts the user to copy .claude/skills/blockers/template-blockers.md to the workspace root and .claude/skills/blockers/template-config.yaml to blockers.config.yaml.


Blocker fields

Every blocker carries these fields:

FieldRequired?TypePurpose
idyesstringNumerical app-prefixed identifier, e.g. LD-0001 (Ledger blocker #1). Auto-allocated by /blockers add per-app.
nameyesstring (slug)Human-readable slug, e.g. stripe-sandbox-keys. Used in URLs, log lines, and dependsOn references.
titleyesstringOne-line description shown in cards.
appyesstringApp key from blockers.config.yaml.
typeyesenumenv-var | architecture-decision | scope-decision | external-engagement | provider-port
urgencyyesenumP0 | P1 | P2 | P3 (see below)
statusyesenumunresolved | resolved-detected | resolved-confirmed | superseded | wontfix
dateyesISO dateDate the blocker was added/identified (YYYY-MM-DD). Set once at registration; never edited.
daysOpenderivedintegerDays from date to today (computed live by the skill on every render; not persisted as the source of truth — date is). For resolved-confirmed blockers, days from date to resolvedAt.
workstreamsyesstring[]Workstream IDs gated by this blocker.
envVarsyes for env-varstring[]Env var names to drop into the configured env file. Never values.
sourceoptionalstringPointer to the plan/doc that scoped this blocker.
unblocksyesstringFree-text. What work proceeds once resolved.
neededyesstringFree-text. What the user has to do/find/decide.
notesoptionalstringFree-text.
dependsOnoptionalstring[]Names (not numerical ids) of other blockers that must resolve first.
resolvedAtoptionalISO datetimeSet on transition to resolved-confirmed.

Urgency scale (P0 highest)

  • P0 — Critical. Production blocked, money on the line, or cannot ship anything until resolved.
  • P1 — High. Blocks a workstream that's active or near-term (current quarter).
  • P2 — Medium. Blocks a planned workstream (next quarter or two).
  • P3 — Low. Blocks future / nice-to-have work; safe to defer indefinitely.

Numerical id format

<PREFIX>-<NNNN> where <PREFIX> is the 2-letter (uppercase) prefix declared per-app in blockers.config.yaml, and <NNNN> is a zero-padded 4-digit sequence number unique within that prefix. Example: LD-0001, LD-0002, AU-0001, AM-0001.

Allocation: /blockers add auto-assigns the next available number for the chosen app. The user never types the numerical id when adding; it's deterministic.


Subcommands

/blockers (no args)

Default action. Print the table view of every unresolved blocker, sorted by urgency (P0 first), then by daysOpen desc within each urgency band (older = higher).

ID         NAME                            APP        URGENCY  TYPE                 DAYS  WORKSTREAMS BLOCKED
LD-0006    advisor-portal-architecture     ledger     P1       architecture-dec.    14    W4.4.3
AU-0001    stripe-sandbox-keys             auth       P1       env-var              14    W2.2.4
LD-0007    cpa-review-engagement           ledger     P1       external-engagement  14    W1.3
AU-0005    vip-tier-thresholds-final       auth       P1       scope-decision       14    W0.5
LD-0004    plaid-production-keys           ledger     P2       env-var              14    W1.2.7
...

After the table: N unresolved (P0: x, P1: y, P2: z, P3: w) · M resolved-detected · K resolved. End with: Run /blockers <id-or-name> to focus one, or /blockers resolved to see the resolved log.

Both LD-0006 and advisor-portal-architecture resolve to the same blocker — the skill accepts either form for <id-or-name> arguments.

/blockers <id-or-name>

Focus one blocker. Display the full card (see "Display format"). Then interactively resolve based on type:

  • env-var: confirm the env vars listed are now in the named env file. Run /blockers check against this single id (grep the env file for each var name). If all present → mark resolved-detected + ask user to confirm. If any missing → tell the user exactly which file + which var name to add. NEVER prompt the user to paste the secret value into the chat. NEVER write the secret to any file.
  • architecture-decision / scope-decision: prompt the user inline for the decision. The answer IS the resolution and gets persisted to the registry.
  • external-engagement: record the engagement status (e.g. "engaged with KPMG UK 2026-04-30, expected memo 2026-06-15"). Resolution timeline lives in the notes, not in the status field — these blockers stay unresolved until the deliverable lands.
  • provider-port: record where the provider keys live (env var name + file path) + that the port itself is mechanical work the next session can pick up.

After any state change, append a one-line entry to the ## Resolution log section at the bottom of blockers.md with timestamp + actor (user) + id + name + new status + brief reason.

/blockers resolved

Show the resolved log — the bottom section of blockers.md. Read-only; no prompts. Useful for sanity-checking what was unblocked when. Each row shows daysOpen at the time of resolution (not live).

/blockers add

Interactive add-a-new-blocker flow. Prompt for each field in order:

  1. name (required, slug — typically <short-name> or W<workstream>-<short-name>)
  2. title (required)
  3. app (required — must match a key in blockers.config.yaml; the skill auto-derives the numerical id from the app's prefix + next available sequence number)
  4. type (required — one of: env-var, architecture-decision, scope-decision, external-engagement, provider-port)
  5. urgency (required — P0 / P1 / P2 / P3)
  6. workstreams (comma-separated workstream IDs that this blocker gates)
  7. For env-var: list of env var names (one per line, blank to finish)
  8. For architecture-decision / scope-decision: the decision being asked for
  9. For external-engagement: engagement type + counterparty (e.g. "CPA review, UK Big Four")
  10. needed (free text — what the user has to do/find/decide)
  11. unblocks (free text — what work proceeds once this resolves)
  12. notes (optional)

Auto-set: id (next available <prefix>-<NNNN> for the named app), date (today), status (unresolved).

After confirmation, append a new YAML block to blockers.md under the ## Blockers section.

/blockers check

Pure scan, no prompts. For every env-var blocker:

  1. Read the named env file.
  2. Check whether each listed env var is present and non-empty.
  3. If all vars present → flip status to resolved-detected (or stay there).
  4. If any vars missing → keep status as unresolved.

Print a delta report: 2 blockers transitioned to resolved-detected, 0 stayed unresolved, 1 blocker has missing env file (auth/.env not found).

Never reports the values of env vars — only their presence. Output goes to the chat; treat it as a one-off audit.


Hard rules

  1. Never write secrets anywhere. Not to blockers.md, not to a log file, not to the chat output. Refuse if the user pastes a secret. Specifically refuse strings matching:
    • sk_test_*, sk_live_*, pk_test_*, pk_live_* (Stripe)
    • AKIA*, ASIA* (AWS)
    • Strings >40 chars of mixed-case alphanumerics + base64 chars
    • Anything the user labels as "secret", "key", "token", "password" inline When refused, tell the user: "drop that into <app>/<env-file> directly, then run /blockers check."
  2. Auto-detected resolution is provisional. resolved-detected is the auto state; only the user's explicit confirmation flips it to resolved-confirmed. A stray env var should never silently mark a blocker done.
  3. Never delete a blocker from blockers.md. Resolution is a status flip + log append, not a deletion. The audit trail is load-bearing.
  4. Numerical ids are immutable + monotonic. Once LD-0007 is allocated, that number is permanently associated with that blocker even if it's later marked wontfix or superseded. New blockers get the next available number, never a recycled one. The 4-digit padding gives 9 999 blockers per app — overflow is not a concern at human scale.
  5. Cross-app aware display. Always show the app field in the table view AND the focused-card view. A blocker that affects multiple apps lists each one separated by + (e.g. auth + admin).
  6. Lifecycle integration: when a blocker resolves to resolved-confirmed, scan blockers.md for any other blockers whose dependsOn field references the resolved blocker's name, and list them as "now potentially unblocked." Then offer to open the next round of work that the unblocked workstream(s) cover. Do NOT touch wealth-migration.md or any other plan file from this skill — surfacing the next step is enough; the user runs the actual work through normal session flow.

Status values

  • unresolved — initial state.
  • resolved-detected — automated detection (env-var scan) flipped this. Awaiting user confirmation.
  • resolved-confirmed — user confirmed the blocker is resolved. Logged in the resolution log.
  • superseded — the requirement changed. Body of the entry should explain how.
  • wontfix — the workstream this gates is being deprioritised or deprecated. Body should explain.

State transitions:

  • unresolved → resolved-detected (auto, env-var only)
  • unresolved → resolved-confirmed (user, any type)
  • resolved-detected → resolved-confirmed (user)
  • resolved-detected → unresolved (user, if the auto-detection was wrong)
  • any → superseded or wontfix (user)

Display format

Table row (list view)

ID         NAME                            APP        URGENCY  TYPE                 DAYS  WORKSTREAMS BLOCKED

Fixed-width columns. Truncate workstreams if more than 3 fit (W2.2.4, W3.3.4, W3.3.5 +1 more). Truncate type to first 18 chars + . if needed.

Focused card (single blocker)

[<id>] <name> — <title>
  App(s):              <app> (or app1 + app2)
  Urgency:             <P0|P1|P2|P3>
  Type:                <type>
  Status:              <status>
  Date added:          <YYYY-MM-DD> (<daysOpen> days ago)
  Workstreams blocked: <comma-separated>
  Source:              <plan or doc reference>

  Needed:
    <free text — what the user has to do>

  Resolution target:
    [env-var]  Drop these vars in <app>/<envFile>:
      - VAR_NAME_ONE
      - VAR_NAME_TWO
    [architecture-decision]  Answer the question inline.
    [external-engagement]  Track engagement status in notes.
    [provider-port]  Drop keys then a future session does the port work.

  Unblocks once resolved:
    <free text — what work proceeds>

  Notes:
    <optional free text>

  Resolution log:
    <if any history exists, last 3 entries>

Registry file format (blockers.md)

Markdown with YAML blocks. The skill reads YAML between ```yaml fences and renders the surrounding markdown verbatim. Top of file holds the ## Configuration section (a pointer to blockers.config.yaml for human reference); ## Blockers holds one block per blocker; ## Resolution log is append-only at the bottom.

A blocker entry:

## [LD-0001] truelayer-sandbox-keys — TrueLayer sandbox API keys

```yaml
id: LD-0001
name: truelayer-sandbox-keys
title: TrueLayer sandbox API keys
app: ledger
type: env-var
urgency: P2
status: unresolved
date: 2026-04-28
workstreams: [W1.2.4]
envVars:
  - TRUELAYER_CLIENT_ID
  - TRUELAYER_CLIENT_SECRET
  - TRUELAYER_REDIRECT_URI
source: ledger/docs/plans/wealth-migration.md § W1.2.4
unblocks: |
  W1.2.4 -- TrueLayer bank-feed provider port (UK + EU coverage via PSD2 Open Banking).
needed: |
  Sign up at https://console.truelayer.com (free sandbox tier), copy client_id and client_secret into ledger/.env.
notes: |
  Highest-leverage second provider after Plaid -- covers UK + 11 EU countries with one API.
```

Body text below the YAML block is free-form notes editable by the user. The skill never overwrites it; only the YAML's status, resolvedAt, and daysOpen fields.


Workspace config file format (blockers.config.yaml)

# Apps in this workspace. Each entry maps an app key to its repo path
# (relative to workspace root), its env file (relative to workspace
# root), and a 2-letter uppercase prefix used for numerical blocker
# ids. The skill uses these to:
#   - validate that a blocker's `app:` field is known
#   - locate the env file when running /blockers check on env-var blockers
#   - allocate numerical ids (<prefix>-NNNN) per-app
#   - render the env-var resolution target in the focused card

apps:
  - key: ledger
    prefix: LD          # 2-letter uppercase; must be unique across apps
    path: ./ledger
    envFile: ./ledger/.env
  - key: admin
    prefix: AM
    path: ./admin
    envFile: ./admin/.env.local
  - key: auth
    prefix: AU
    path: ./auth
    envFile: ./auth/.env
  # ... add one entry per app/repo in your workspace

# Optional: where the registry file lives. Defaults to ./blockers.md.
registry: ./blockers.md

For single-repo projects, apps may have one entry with key: app, prefix: AP, path: .; the skill works the same way.

Prefix collision rule: if two apps share a prefix, /blockers add refuses and asks the user to disambiguate.


When to invoke this skill proactively

When the assistant hits a wall that the user could resolve but the assistant cannot — a missing API key, a deferred architecture decision flagged in a plan file, a "needs founder input" comment, an external regulatory dependency — offer:

"This is parked on <X>. Want me to register it as a blocker so /blockers tracks it?"

Do NOT auto-register. The user opts in. Auto-registration would clutter the registry with speculative blockers.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.