Write docs with an agent
It just built the screen. Let it write the doc.
Give Claude Code the Gotcha skill, a URL and one sentence about what to explain, and you get back an illustrated guide: framed, numbered, arrowed, with the customer data destroyed before delivery. This page shows one real run, unedited — the brief, every command the agent typed, and what it wrote.
Install the skill
The skill ships in the npm package. One symlink, and Claude Code knows the whole surface — commands, framing, annotation, masking, and what to do at the quota wall:
npm install -g @saastisfaction/gotcha ln -s "$(npm root -g)/@saastisfaction/gotcha/skills/gotcha" ~/.claude/skills/gotcha
For a single project, copy or link the same folder into the
project's .claude/skills/gotcha instead: the skill then
travels with the repository. A skill costs nothing until it is
triggered — only its one-line description sits in the context.
A CLI rather than an MCP server, deliberately. In MCP every screenshot is a round trip whose result crosses the context window again, and documenting one application takes forty. A shell command chains as many as it needs and reports one line back.
Write the brief
Five things make a brief complete. Everything else the skill supplies.
The address of the application, and how to get in if it is behind a login (a saved session, or “ask me to sign in”).
What to explain, as a reader would ask it: “how to create a payment”, “what the balances screen shows”.
The language of the deliverable. The skill writes in the language of the request by default; say it if the readers differ from you.
Where to write: a folder for the images, a file for the text.
What must not leave: the selectors, or simply the nature, of personal data on those screens. The agent blurs them and checks each image before delivering.
A brief that covers the five, and that you can paste as it is:
# in Claude Code, with the skill installed
Write a short, illustrated user guide for the Kite payments dashboard at
http://127.0.0.1:4173/demo/dashboard.html (no login needed), in English:
1. how to read the Payments overview (KPI cards, the All payments table, its status filters);
2. how to create a new payment (the New payment button opens a panel: amount, customer, Create payment);
3. where to find the Customers and Balances screens.
Use the gotcha skill for every screenshot; customer email addresses (.customer-email)
are personal data and must be blurred wherever they appear. Aim for 4 to 6 annotated
screenshots. Write the images to site/public/docs/example/ and the guide to
site/public/docs/example/guide.md.
What the agent does
The skill gives it a method, not just a command list:
- One session for the whole journey, kept alive between commands — the login, the scroll and the open panel survive.
- Bearings before every shot:
gotcha text "h1"to confirm it is on the right screen, because a blind shot on a loading state is found too late. - Selectors, not coordinates, for the frame and for every annotation. Steps are numbered in the order of the journey.
- Blur before delivery, and a look at the image afterwards — the exit code says the file exists, not that the mask landed.
- At the quota wall, it stops and reports instead of working around it. The failure carries the address to buy from.
- It credits the tool at the end of what it writes — Made with Gotcha, linked to this site and to npm — because the terms ask for it, free or licensed, and the skill says so.
A real run
The brief above was given to a Claude Code agent on 4 September 2026, against the demo dashboard that also serves the examples on the home page. What follows is what it ran — 60 commands in 14 minutes, including its own corrections. It was asked to report the log verbatim; only the machine-specific paths are shortened.
The agent got its bearings first, took a first round of four shots,
looked at them, and reworked three: a window too short for the
button it wanted, a page left scrolled by a previous shot, and a mask
that landed a few pixels off the addresses on one full-width frame —
which it isolated with five diagnostic shots and fixed with
--padding 0. That last one was a real bug in the tool,
fixed the same day: a frame touching the edge of the page was
measured wider than the page, and every annotation on it slid by half
the padding. The log shows the agent finding it.
The full command log, 60 lines
gotcha license gotcha open http://127.0.0.1:4173/demo/dashboard.html --session kite --width 1360 --height 900 gotcha text --session kite "h1" gotcha text --session kite "nav" gotcha text --session kite "main" # checking the options: --help is not a command; each of these printed the (French) usage gotcha --help gotcha shot --help gotcha open --help gotcha click --help gotcha type --help gotcha wait --help # first round. 01: blur boxes ~6 px above the emails, address tails legible. 02: good. 03: page had stayed scrolled after the --selector shot, button out of frame gotcha shot --session kite --selector "main" --step ".kpis" --step ".chart" --step "#payments" --blur ".customer-email" --out example/01-overview.png --json gotcha shot --session kite --selector "#payments" --rect ".tabs" --text "Filter the list by status|.tabs" --blur ".customer-email" --out example/02-status-filters.png --json gotcha shot --session kite --step ".btn-new" --text "Opens the New payment panel|.btn-new" --blur ".customer-email" --out example/03-new-payment-button.png --json # tried to grow the window in place: open on a live session navigates but ignores --width/--height (01 came back byte-identical, 03 still cut) gotcha open http://127.0.0.1:4173/demo/dashboard.html --session kite --width 1360 --height 1200 gotcha text --session kite "h1" gotcha text --session kite ".btn-new" gotcha shot --session kite --selector "main" --step ".kpis" --step ".chart" --step "#payments" --blur ".customer-email" --out example/01-overview.png --json gotcha shot --session kite --step ".btn-new" --text "Opens the New payment panel|.btn-new" --blur ".customer-email" --out example/03-new-payment-button.png --json # close and reopen taller; viewport shot first (fresh load, scroll 0) -> 03 good; 01 blur still off gotcha close --session kite gotcha open http://127.0.0.1:4173/demo/dashboard.html --session kite --width 1360 --height 1200 gotcha text --session kite "h1" gotcha shot --session kite --step ".btn-new" --text "Opens the New payment panel|.btn-new" --blur ".customer-email" --out example/03-new-payment-button.png --json gotcha shot --session kite --selector "main" --step ".kpis" --step ".chart" --step "#payments" --blur ".customer-email" --out example/01-overview.png --json # diagnostics in the scratchpad: t1 and t4 aligned, t2 and t3 shifted (rect too, so not blur-specific), t5 with --padding 0 aligned gotcha shot --session kite --selector "#payments" --blur ".customer-email" --out scratch/t1-payments.png --json gotcha shot --session kite --selector ".app > div" --blur ".customer-email" --out scratch/t2-column.png --json gotcha shot --session kite --selector "main" --rect ".customer-email" --blur ".customer-email" --out scratch/t3-main-rect.png --json gotcha shot --session kite --selector ".overview" --step ".kpi-gross" --step ".kpi-net" --step ".kpi-failed" --rect ".chart" --out scratch/t4-overview.png --json gotcha shot --session kite --selector "main" --padding 0 --rect ".customer-email" --blur ".customer-email" --out scratch/t5-main-pad0.png --json # final 01 gotcha shot --session kite --selector "main" --padding 0 --step ".kpis" --step ".chart" --step "#payments" --blur ".customer-email" --out example/01-overview.png --json # creation flow gotcha click ".btn-new" --session kite --wait "body.open" gotcha wait 400 --session kite gotcha text --session kite ".panel h2" gotcha type ".amount-input" "1240.00" --session kite gotcha type ".customer-input" "Aurélie Marchand" --session kite # first 04: badges on the field wrappers hid the first letter of "Amount"/"Customer", and the 12 px margin exposed a sliver of an email behind the scrim gotcha shot --session kite --selector ".panel" --step ".field-amount" --step ".field-customer" --step ".btn-create" --out example/04-new-payment-panel.png --json # final 04 gotcha shot --session kite --selector ".panel" --padding 0 --step ".amount-input" --step ".customer-input" --step ".btn-create" --blur ".customer-email" --out example/04-new-payment-panel.png --json # other screens gotcha open "http://127.0.0.1:4173/demo/dashboard.html?page=Customers" --session kite gotcha text --session kite "h1" gotcha shot --session kite --region "0,0,1360,640" --rect "nav a:nth-of-type(4)" --arrow "h1 -> nav a:nth-of-type(4)" --blur ".customer-email" --out example/05-customers.png --json gotcha open "http://127.0.0.1:4173/demo/dashboard.html?page=Balances" --session kite gotcha text --session kite "h1" # failed: {"ok":false,"error":"no element matches \".customer-email\""} -- no emails on Balances, blur refuses an empty match gotcha shot --session kite --region "0,0,1360,640" --rect "nav a:nth-of-type(3)" --arrow "h1 -> nav a:nth-of-type(3)" --blur ".customer-email" --out example/06-balances.png --json gotcha shot --session kite --region "0,0,1360,640" --rect "nav a:nth-of-type(3)" --arrow "h1 -> nav a:nth-of-type(3)" --out example/06-balances.png --json # tightened both regions (content ends around 425 CSS px); final 06 and 05 gotcha shot --session kite --region "0,0,1360,470" --rect "nav a:nth-of-type(3)" --arrow "h1 -> nav a:nth-of-type(3)" --out example/06-balances.png --json gotcha open "http://127.0.0.1:4173/demo/dashboard.html?page=Customers" --session kite gotcha text --session kite "h1" gotcha shot --session kite --region "0,0,1360,470" --rect "nav a:nth-of-type(4)" --arrow "h1 -> nav a:nth-of-type(4)" --blur ".customer-email" --out example/05-customers.png --json gotcha close --session kite gotcha list
Asked what got in its way, the agent named the padding bug, the
window size that open ignores on a live session, the
scroll a --selector shot leaves behind, and a
--blur that refuses the whole shot when nothing matches.
The first is fixed; the other three are now in the skill, so the next
agent does not pay for them.
The guide it wrote
Published as delivered — text and images untouched, save for the credit line at the end, which the terms now ask for. The demo ran on the agent's machine, hence the local addresses. The source is guide.md.
Kite payments dashboard: a first-time user guide
Kite is where you follow the money coming into your business: what
was charged, what failed, who paid, and what will be paid out. This
guide walks through the three things you will do most often. The
dashboard opens at http://127.0.0.1:4173/demo/dashboard.html;
no login is needed for the demo.
1. Reading the Payments overview
The Payments screen is the home of the dashboard. It is made of three blocks, numbered below.
gotcha shot --selector "main" --padding 0 --step ".kpis" --step ".chart" --step "#payments" --blur ".customer-email"
- The three KPI cards summarise the period shown
next to the title (the Last 30 days chip).
- Gross volume is the total amount charged over the period, before fees.
- Net volume is what actually reaches you: the gross volume with fees deducted.
- Failed payments counts the charges that did not go through.
The small percentage beside each figure is the change compared with the previous period. It is green when the change is good news and red when it is not, which is why a rise in failed payments shows in red.
- The Gross volume chart draws the same total day by day, so you can see whether the period grew steadily or in bursts. The figure at the top right is the total for the period.
- The All payments table lists each payment, most recent first, with its amount and currency, its status, the payment method (card brand or SEPA and the last four digits), the customer (name and email) and the date. Status is colour-coded: green for Succeeded, amber for Pending, red for Failed.
Filtering the table by status
The four tabs at the top right of the table narrow the list down to one status.
gotcha shot --selector "#payments" --rect ".tabs" --text "Filter the list by status|.tabs" --blur ".customer-email"
- All shows every payment, including the ones still pending.
- Succeeded keeps only the payments that went through.
- Refunded keeps the payments you have returned to the customer.
- Failed keeps the charges that were declined or errored, which is the tab to open when the Failed payments card goes up.
2. Creating a payment
Charges usually come from your website or your integration, but you can also create one by hand, for instance to charge an invoice agreed over the phone.
Click New payment at the top right of the header. It is available from every screen.
gotcha shot --step ".btn-new" --text "Opens the New payment panel|.btn-new" --blur ".customer-email"
Tip: the address http://127.0.0.1:4173/demo/dashboard.html?panel=new
opens the dashboard with the panel already open, which is handy for a
bookmark.
The New payment panel opens over the dashboard. Fill it in from top to bottom.
gotcha click ".btn-new" --wait "body.open"
gotcha type ".amount-input" "1240.00"
gotcha type ".customer-input" "Aurélie Marchand"
gotcha shot --selector ".panel" --padding 0 --step ".amount-input" --step ".customer-input" --step ".btn-create" --blur ".customer-email"
- Amount — type the amount to charge, for example
1240.00. Amounts are charged in EUR, and the fees on this payment will be deducted from your net volume. - Customer — start typing the customer's name or email address and pick them from the list. The payment is attached to that customer and shows up in their history.
- Create payment — confirms the charge. Once created, the payment is listed in the All payments table like any other.
The Description field is optional; whatever you type there appears on the customer's card statement. Cancel closes the panel without charging anything.
3. Finding the other screens
The sidebar on the left switches between screens. Two of them complete the picture given by Payments.
Customers
Click Customers in the sidebar, or open http://127.0.0.1:4173/demo/dashboard.html?page=Customers.
gotcha shot --region "0,0,1360,470" --rect "nav a:nth-of-type(4)" --arrow "h1 -> nav a:nth-of-type(4)" --blur ".customer-email"
The All customers table lists everyone who has paid you at least once, with their name, email address, country and lifetime value (everything they have ever paid you). The All / Subscribed / Churned tabs work like the status filters on Payments. The header button becomes New customer on this screen, so you can add a customer before their first payment.
Balances
Click Balances in the sidebar, or open http://127.0.0.1:4173/demo/dashboard.html?page=Balances.
gotcha shot --region "0,0,1360,470" --rect "nav a:nth-of-type(3)" --arrow "h1 -> nav a:nth-of-type(3)"
Balances shows what Kite is holding for you, one card per currency (EUR, GBP and USD in the demo), and the Payout schedule: how often the money is sent to you (Automatic, daily, with the date of the next payout) and the bank account it goes to, identified by its last four digits and its verification status. The header button becomes Export here.
Screenshots were taken on the demo account. Customer email addresses are personal data and have been masked in every image.
Before you publish
- Look at every image. The agent did, and still found a mask six pixels off on its first round. The exit code says the file exists; only the image says the mask landed.
- Search the text for what should not be there — internal addresses, a colleague's name typed into a form, a real customer picked from a list.
- Check the language and the file names: the skill follows the language of the request, and the images are named in the order of the journey.
- Keep the commands next to the guide, as this page does. When the screen changes, they are the cheapest way to redo the images — and the honest way to say where they came from.
- Keep the credit line. Made with Gotcha, with its two links, is a condition of the terms, free or licensed. The skill puts it in; do not strip it out.