Claude Fable 5 Side Project: From Requirements to Ship — What Did AI Build?

AI field notes  ·   ·  About 10 min read

Developer shipping a small side project on a laptop — Claude Fable 5 end-to-end AI collaboration from spec to release

Bottom line: we used Claude Fable 5 to build pulsecheck from zero — a CLI that batch-checks a list of URLs/APIs, writes a JSON report, and exits with a non-zero code when anything is down. Perfect for cron or hooking into alerts. This article has two halves: first, what the tool does and how the finished product looks (see the screenshot below); second, a seven-step replay of what Claude Code wrote vs. what you must decide. If you only want the outcome, read through the screenshot; if you want to reproduce it, start at Step 1.

What is pulsecheck for?

In one sentence: it batch-checks whether a set of URLs/APIs are still reachable — no manual browser tabs or one-off curl loops.

Typical setup: drop production endpoints into config.yaml (e.g. /health, /ping), run pulsecheck from cron every five minutes. If an API returns 503 or times out, exit code becomes 1 and your alert script or monitoring hook fires. It is a lightweight probe, not a full observability platform — no dashboards, no SMS. It answers one question: are these URLs alive right now? and outputs JSON.

CLI
Terminal tool
7
Build steps
52
Minutes to v0.1.0

Three real use cases

Forget Go, YAML, and JSON for a moment — this tool solves “how do I know these services are still up?” Three situations where we built it:

  • Scheduled health checks — You have 5–20 endpoints (payment callbacks, public APIs, internal gateways). A shell for url in ...; do curl ... loop is painful to maintain and produces no unified report. pulsecheck reads one config file, outputs structured JSON, and drops into cron.
  • Pre-deploy / on-call manual check — Before a release, run one command: ./pulsecheck -config prod.yaml -o /tmp/pre-deploy.json. Exit code 0 means all green; exit code 1 means stop the deploy.
  • Alert hook probe — When you do not need the Prometheus stack, wire exit code 1 to an existing Webhook or email script. Keep the JSON report for post-mortems.

Out of scope: historical trends, SMS paging, multi-tenant dashboards — that is Datadog or cloud monitoring territory. pulsecheck only answers whether this batch of URLs is reachable right now.

Finished product screenshot

Below is pulsecheck after all seven steps on a Mac terminal: read config, probe URLs, write JSON. One site returned 503, so exit code is 1.

pulsecheck finished product: terminal running ./pulsecheck outputs report.json with api.example.com 200 and status.example.com 503 probe results
Finished run: left side shows ./pulsecheck -config config.example.yaml -o report.json; right side report.json lists each URL’s status code, latency, and health flag (ok).

Three commands to reproduce locally:

./pulsecheck -config config.example.yaml -o report.json
echo $?          # 1 = at least one target unhealthy
cat report.json   # inspect the report

Input / output / stack

Now that the purpose is clear, here is how it works technically: think of it as batch curl + one consolidated report, compiled into a cron-friendly CLI.

Dimension Description Example
Input YAML config listing URLs to check config.example.yaml
Output JSON health report + process exit code report.json; 0 = all green, 1 = failures
Typical usage Cron probes; pre-deploy checks; exit code triggers alerts Every 5 min: */5 * * * * pulsecheck ...
Stack Go 1.22 single binary No GUI, no database

You maintain one YAML file with probe targets; pulsecheck handles probing and aggregation. Example config:

config.example.yaml
targets:
  - https://api.example.com/health
  - https://status.example.com/ping

Finished repo is roughly 400 lines of Go:

pulsecheck/ layout
pulsecheck/
├── cmd/pulsecheck/main.go      # CLI entry: -config -o
├── internal/checker/checker.go # HTTP probe + latency
├── internal/config/config.go   # YAML parser
├── config.example.yaml
├── Makefile · README.md
└── .github/workflows/ci.yml

Part two: what AI wrote in seven steps

By now you know what pulsecheck is and why it exists. From here we enter the build log: using Claude Fable 5 + Claude Code, from an empty folder to a v0.1.0 tag — which files the Agent produced and where a human had to step in.

Division of labor in one line: AI writes code and tests; you define scope, review, and sign the release. All seven steps include copy-paste prompts. Use Fable 5 in Claude Code (no need for Opus here — see our tier comparison).

Prerequisites

  • Go 1.22+ — verify with go version
  • Claude Code CLI — select Claude Fable 5 (enough for daily Agent loops; see model tier comparison)
  • Empty directorymkdir pulsecheck && cd pulsecheck && git init
  • (Optional) GitHub repo — for Step 6 CI; you can finish locally first

Step 1: Repo and requirements

Your job: capture the pain in three sentences as SPEC.md. You can draft by hand or dictate to AI, but you must trim non-goals — otherwise the Agent adds a Web UI and a database.

Prompt for Claude Code (Step 1)
Read the requirements below and generate a SPEC.md draft. Do not add any feature not listed:

- Tool name pulsecheck, Go 1.22 CLI
- Read URL list from YAML config, concurrent HTTP GET
- Write JSON report to path specified by -o
- Fields: url, status_code, latency_ms, ok
- Default timeout 5s; PULSECHECK_TIMEOUT env var overrides
- Exit codes: 0 all green, 1 any failure, 2 config error
- Non-goals: no GUI, no DB, no Docker, no alert push

AI produces: SPEC.md. You verify: no scope creep; acceptance command includes go test ./....

Acceptance: cat SPEC.md — confirm Must-have / Non-goals / Exit codes sections exist.

Step 2: Project scaffold

Your job: tell AI to scaffold only — no business logic. Fable 5 handles almost all of this step.

Prompt for Claude Code (Step 2)
Read SPEC.md and initialize Go module github.com/you/pulsecheck.
Create project skeleton only; business logic returns stubs:
- cmd/pulsecheck/main.go parses -config and -o
- internal/config reads YAML
- internal/checker empty implementation
- Makefile: test, lint, build
- .github/workflows/ci.yml placeholder
Require go build ./... to pass. Do not write real HTTP logic yet.

AI produces: the eight files in the directory tree above. Time: about 6 minutes.

Acceptance:

go build ./...
./pulsecheck -h   # should print usage

Step 3: Probe logic and tests

Your job: insist on tests first, then implementation. This is the most “real project” step — AI runs go test, fixes failures, and loops until green.

Prompt for Claude Code (Step 3)
In internal/checker:
1. Write checker_test.go first — httptest for 200, 500, and timeout cases
2. Implement checker.go: HTTP GET, record status_code and latency_ms
3. Loop go test ./... until all pass
4. Wire main.go: config → checker → write JSON to -o path

AI produces: core probe code. Logic excerpt:

internal/checker/checker.go (AI-generated · excerpt)
func CheckURL(ctx context.Context, client *http.Client, url string) Result {
    start := time.Now()
    req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
    resp, err := client.Do(req)
    if err != nil {
        return Result{URL: url, OK: false, LatencyMs: time.Since(start).Milliseconds()}
    }
    defer resp.Body.Close()
    ok := resp.StatusCode >= 200 && resp.StatusCode < 300
    return Result{
        URL: url, StatusCode: resp.StatusCode,
        LatencyMs: time.Since(start).Milliseconds(), OK: ok,
    }
}

In our run Fable 5 took 3 rounds of go test — round 2 fixed a timeout-not-passed-to-client bug without human edits.

Acceptance:

go test ./... -v   # 12 table-driven tests all green

Step 4: Review pass

Your job: act as Code Reviewer — list issues for AI to fix. Do not edit yourself (that defeats the test of whether AI can iterate on feedback).

Prompt for Claude Code (Step 4 · review send-back)
Apply these review comments; go test ./... must stay green:
1. Rename JSON field latency to latency_ms per SPEC
2. Use worker pool for multiple URLs — default max 10 concurrent
3. stdout prints only JSON report path hint; warn logs go to stderr

AI produces: worker pool, field rename, log routing. Human judgment: whether these three items are actually worth changing — AI cannot decide that for you.

Acceptance: go test ./... still green; manually hit one or two URLs and confirm JSON field names.

Step 5: Config and README

Your job: have AI write ops-ready docs and sample config.

Prompt for Claude Code (Step 5)
Generate config.example.yaml and README.md:
- Install: go install or go build
- Usage examples and exit code table (0/1/2)
- Cron example: run every 5 minutes and append logs
- Do not invent subcommands that do not exist

AI produces:

config.example.yaml
targets:
  - https://api.example.com/health
  - https://status.example.com/ping

Acceptance: swap example URLs for ones you can reach, then run the three commands from the finished product screenshot section — confirm report.json has all required fields.

Step 6: GitHub Actions CI

Your job: push to GitHub, let AI finish CI and self-fix on failure.

Prompt for Claude Code (Step 6)
Complete .github/workflows/ci.yml:
- go test -race ./...
- golangci-lint run
- use go 1.22
If lint fails, read the log, fix, and recommit.

First lint run flagged an unused import — Fable 5 read the CI log and removed it. On a 16 GB Mac, -race can trigger swap; offload to a GitHub Runner or Cloud Mac node — same reasoning as Claude Code execution environment choices.

Acceptance: CI green on GitHub.

Step 7: Accept and tag release

Your job: this step must be manual — smoke test and tag. AI can draft CHANGELOG; signing the release is yours.

go test ./...
make build
./pulsecheck -config config.example.yaml -o /tmp/report.json
cat /tmp/report.json | jq .
git add -A && git commit -m "feat: pulsecheck v0.1.0"
git tag -a v0.1.0 -m "first release: YAML-driven HTTP health probe"
git push && git push --tags

At this point pulsecheck is shipped: a cron-ready, monitor-hookable CLI built in about 52 minutes.

What to add after v0.1

Deliberately out of v0.1: Slack alerts, Prometheus exporter, Docker image. Open new issues and let Fable 5 iterate — close the loop first, expand later.

Step-by-step: AI vs human

Looking back after the build, division of labor across seven steps:

Step AI (Fable 5) Human required
1 Requirements Expand spoken notes into SPEC structure Trim non-goals, set exit codes
2 Scaffold 8 files, go build passes Confirm Go version and module name
3 Implementation Tests + checker + main wiring Verify tests cover the spec
4 Review Fix per checklist Write the review list
5 Docs README + config sample Copy-paste and run through
6 CI Workflow + lint fixes Define what “green” means
7 Release CHANGELOG draft Smoke test, tag, push

Roughly 78% of code output was AI-written; scope trimming, review judgment, and release sign-off stay human regardless of model tier.

How to choose your path

If you are… Recommended approach Why
First full side project with AI Follow these seven steps + acceptance commands Faster than debating “how good is AI?” abstractly
Building an ops/internal CLI like pulsecheck Go + Fable 5 Agent loop Tests self-run; table-driven acceptance fits
Shipping external SaaS with user data AI drafts + Opus security review Release liability cannot sit entirely on the Agent
Adding to an existing repo Skip step 2; start from an Issue in Agent Scaffold already exists
16 GB Mac + long CI runs Agent locally; race/build on Cloud Mac Avoid swap masquerading as “model slowness”
Need a boss demo within a week Lock spec non-goals before opening Agent Prevents scope creep that blocks ship date

Recommended stacks (composable)

  • Solo developer — Fable 5 for steps 2–6; Cursor Tab for pre-release tweaks; Opus only for external-service review.
  • Small team — Repo template with seven-step checklist; copy pulsecheck flow for new tools; Agent on production Claude Code workflow.
  • Save tokens — Spec polish and CHANGELOG via Gemini Flash; coding loop stays Fable 5; routing per OpenRouter pricing structure.

When layering MCP: MCP pulls Issue/monitoring context; Fable 5 edits the repo; step 7 release sign-off should stay manual.

Common mistakes

  • Mistake 1: no concrete project before chatting — AI gives generic advice; start with a one-line goal like pulsecheck.
  • Mistake 2: business logic in step 2 — mixing scaffold and implementation makes testing harder later.
  • Mistake 3: skipping step 4 review — JSON field names and stdout pollution slip into “done.”
  • Mistake 4: tagging without step 7 smoke test — no smoke test is not a release.
  • Mistake 5: race + Agent on 16 GB RAM — slowdown is memory, not the model; move CI to Runner / Cloud Mac.

FAQ

What problem does pulsecheck solve?

“Are this batch of URLs reachable right now?” — without hand-written shell curl loops or a heavy monitoring platform. Good for personal projects, small teams, or pre-deploy checks.

How is it different from UptimeRobot or Prometheus?

pulsecheck is a lightweight CLI you run on your own machine — config in your hands, no SaaS dependency. UptimeRobot and Prometheus are full monitoring stacks with more features and cost. This article builds the former: enough, and you own the code.

Can I clone a repo instead?

This is a field report + reproducible tutorial. Follow the seven prompts in your own directory for an equivalent build — line-by-line diff parity is not the goal.

Which step did AI handle the most?

Step 3 (tests + implementation) and step 2 (scaffold) were almost entirely Fable 5; steps 1 and 7 needed the most human time.

How is this different from Cursor Tab completion?

Tab excels at single-file edits; a full project needs Claude Code multi-file + test runs. See Copilot vs Cursor field test.

Summary

Product: pulsecheck — read URLs from YAML, batch-check availability, write report.json (see screenshot above). Process: Claude Fable 5 across seven steps from empty folder to v0.1.0 tag; AI wrote most Go code and tests, humans owned scope, review, and release. To evaluate whether AI can ship a small project, the screenshot and I/O table are enough; to build your own, copy the Step 1 prompt and go.

ZavCloud · Cloud Mac

Run pulsecheck CI on Cloud Mac

Dedicated Mac mini M4: Claude Code writes code, GitHub Actions runs test -race on the same macOS node — Step 6 without 16 GB RAM swap.

View plans and pricing
Cloud Mac Dedicated Mac mini