Skip to content
Back to skills

Product Brief

ASecurity

Use when starting a new project, or when an existing project has no PRODUCT.md — before writing code, choosing a stack, or planning features. Also use when the first-run gate reports a missing or unparseable brief, or when a project cannot say in one sentence who it is for.

  • 3 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 1, 2026
ai-agentspythonrustgodockergit

Works with

  • terminal
  • cli

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 1, 2026

npx -y skills add williamblair333/Uncle-J-s-Refinery --skill product-brief --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Product Brief?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Product Brief
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/williamblair333-product-brief/badge)](https://www.skillsdirectory.com/skills/williamblair333-product-brief)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: product-brief
description: Use when starting a new project, or when an existing project has no PRODUCT.md — before writing code, choosing a stack, or planning features. Also use when the first-run gate reports a missing or unparseable brief, or when a project cannot say in one sentence who it is for.
---

# Product Brief

## Overview

Produces `PRODUCT.md`: what the project is for, who uses it, how a stranger gets
their first result, and a machine-readable block that lets the first-run gate
prove the claim. **Core principle: a brief that a machine cannot check is a wish.**

## Output shape

Write `PRODUCT.md` at the project root with these sections, in this order.
Every one is REQUIRED — an absent section is the failure this skill exists to
prevent, not an editorial choice.

1. **Core job** — one sentence: who, doing what, for what outcome. No feature
   list, no technology.
2. **Users** — who they are, what they already have installed, what they already
   know. This decides how much the first-run path may assume.
3. **Success** — observable measures, including a **time-to-first-result
   target** in seconds: install to first useful output for someone who has never
   seen the project.
4. **First-run path** — numbered commands a stranger can paste, from nothing to
   first result. Every command also appears in the README, verbatim; the gate
   fails on drift between the two.
5. **Non-goals** — what this will not do, so it stops being re-proposed.
6. **UI principles** — how the interface behaves: default output, error shape,
   what it asks for before it does anything. A CLI is an interface; terminal
   output is UI.
7. **`verify:` block** — the machine-readable contract, in a fenced ```yaml
   block (see below).

## The verify block

```yaml
verify:
  image: debian:bookworm-slim   # optional; bare base, no preinstalled toolchain
  network: required             # required | none — declare it, never assume it
  install:                      # verbatim from the README
    - apt-get update && apt-get install -y python3
    - pip install .
  run: mytool process ./sample.txt        # the core job, one command
  expect:
    - stdout_contains: "processed 3 records"
    - file: /tmp/mytool/result.json
    - exit_code: 0              # necessary, never sufficient
  time_target_seconds: 300
```

**`expect` needs at least one observable proof** — a file, or output text. A
tool that catches an error, prints something reassuring and exits 0 passes an
exit-code check while doing nothing, which is the failure the gate exists to
catch. The gate refuses a brief whose expectations are exit-code only.

**The proof must come from the program, not from your test.** Writing
`run: mytool process x; echo done` with `expect: stdout_contains: "done"` passes
while the tool fails — the gate refuses a `run:` that echoes its own expected
string. Assert on text the program prints and files it writes. Prefer `| tee
FILE` over `> FILE; echo ok`, so the real output reaches both stdout and the file
and the exit status stays the program's.

**Credentials:** if the core job cannot run without real secrets, the project
needs a documented stub or offline mode, and `run:` uses it. The gate never
receives credentials. Treat a missing stub mode as a product gap.

**`install_note:`** — when the documented install path cannot run inside the
gate (a `docker compose` project, since Docker cannot nest), state why in
`install_note:` and use the equivalent path. Drift then warns instead of
failing, and the reason is printed in every report. Without the note, using
undocumented steps is a failure, as it should be.

**No `verify:` at all is a legitimate outcome.** A project that needs real
credentials, or a whole stack, and has no stub mode cannot be proven from a
clean machine. Say so in the brief and leave the block out. The gate then reports
`no verify: block`, which is the truth. Do not paper over it with a `--help`
call.

## Quick reference

| Section | The question it answers | Failure if missing |
|---|---|---|
| Core job | Why does this exist? | Features get judged by cost, not purpose |
| Users | What may I assume? | First-run path assumes the author's machine |
| Success | How do we know it worked? | "Done" becomes a matter of opinion |
| First-run path | Can a stranger start? | Setup breaks and nobody notices |
| Non-goals | What are we not doing? | Scope returns every planning round |
| UI principles | What does using it feel like? | Tracebacks and prompts become the interface |
| `verify:` | Can a machine check the claim? | The brief is unenforceable |

## Common mistakes

| Mistake | Fix |
|---|---|
| Core job names a technology ("a Rust daemon that…") | Name the user's outcome; the stack is an implementation detail |
| First-run path starts after install ("run the server") | Start from nothing: clone or install, then first result |
| `run:` is a `--help` or `--version` call | That proves the binary exists, not that the job works. Run the real task |
| `expect:` is only `exit_code: 0` | Add a file or output check; the gate rejects the brief otherwise |
| Success has no time target | Give a number in seconds; slow setup is a real defect |
| Brief written after the code | Write it first; the point is to decide before building |

## After writing it

Run the gate: `python3 $STACK_ROOT/features/product-quality/first_run_gate.py .`

A brief that the gate cannot execute is not finished. Then review the plan
against the brief with `product-focus-review`.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.