Skip to content

Make hammer agent-friendly: zero-config URL mode, JSON stdout, SLO exit codes#6

Merged
chenchaoyi merged 1 commit into
masterfrom
claude/bold-wright-u43svu
Jun 18, 2026
Merged

Make hammer agent-friendly: zero-config URL mode, JSON stdout, SLO exit codes#6
chenchaoyi merged 1 commit into
masterfrom
claude/bold-wright-u43svu

Conversation

@chenchaoyi

Copy link
Copy Markdown
Owner

Reshape hammer so any agent (or CI job) can run a meaningful load test in one command, parse the result without scraping human text, and branch on a stable exit code — while staying a single, dependency-free binary and keeping the existing profile format fully backward-compatible.

What's new

1. Zero-config one-shot mode — no profile file needed:

hammer -url https://api/users -method POST -header 'Authorization: Bearer t' -body '{"x":1}' -content-type REST

Templating ({{ uuid }}, {{ randInt N }}) still works in -url / -body.

2. Machine-readable stdout-output json emits the whole report to stdout; all logs stay on stderr, so stdout is always clean to pipe into jq.

3. SLO assertions + meaningful exit codes-max-error-rate, -max-p50/p95/p99 produce a checks block and drive the exit code:

Code Meaning
0 completed, all checks passed (or none set)
1 SLO threshold violated
2 usage / argument error
3 setup error (bad profile, etc.)

So hammer -url … -max-p99 500ms -max-error-rate 0 || alert just works.

4. Profile from stdin… | hammer -profile - for generated traffic mixes, no temp file.

5. Quieter for automation-quiet silences the live monitor; the /stats HTTP endpoint is now opt-in (was :9001 by default) so runs never bind a surprise port in CI/sandboxes.

6. Richer report — added error_rate, achieved_rps, and checks to the JSON, plus a self-documenting -h banner with examples and exit codes.

Implementation notes

  • profile/: factored per-call init into Profile.add, then added LoadFromReader (stdin) and SingleCall (URL mode) on top of it — shared validation/templating path.
  • hammer.go: split main into run() int so exit codes are explicit and deferred cleanup still runs; report() now writes to an io.Writer and appends check results.
  • Added tests for SingleCall/LoadFromReader, header parsing, error-rate, threshold evaluation, and the new derived JSON fields. README rewritten with a dedicated For agents section.

Compatibility

Everything is additive except one deliberate, documented default change: -stats-addr now defaults to disabled (was :9001). The profile format, existing flags, and JSON fields are unchanged.

Verification

go build ./..., go vet ./..., and go test -race ./... all pass; every new flow was exercised end-to-end against the local test server (zero-config mode, JSON-to-stdout, stdin profile, POST with headers, and exit codes for pass/fail/usage/setup).

🤖 Generated with Claude Code


Generated by Claude Code

…it codes

Reshape hammer so any agent (or CI job) can run a meaningful load test in
one command, parse the result without scraping human text, and branch on a
stable exit code — while staying a single, dependency-free binary and keeping
the existing profile format fully backward-compatible.

New capabilities:

- Zero-config one-shot mode: -url with -method/-body/-header/-content-type
  builds an in-memory single-call profile (templating still works), so no
  profile file is needed for the common case.
- Profile from stdin: -profile - reads the Call stream from stdin.
- Machine-readable output: -output json prints the full structured report to
  stdout while all logs stay on stderr, so stdout is always clean to pipe.
- SLO assertions + exit codes: -max-error-rate / -max-p50 / -max-p95 / -max-p99
  produce a pass/fail checks block and drive the process exit code
  (0 ok, 1 SLO violated, 2 usage, 3 setup).
- Quieter automation: -quiet silences the live monitor; the /stats HTTP
  endpoint is now opt-in (default disabled) so runs don't bind a surprise port.
- Richer report: error_rate, achieved_rps, and a checks section added to the
  JSON report; help banner documents usage, exit codes, and examples.

Implementation notes:

- profile: factor per-call init into Profile.add; add LoadFromReader (stdin)
  and SingleCall (URL mode) on top of it.
- main: split into run() int so exit codes are explicit and deferred cleanup
  still runs; report() now writes to an io.Writer and appends check results.
- Tests for SingleCall/LoadFromReader, header parsing, error-rate, threshold
  evaluation, and the new derived JSON fields. README rewritten with a
  dedicated "For agents" section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E11t2fuxGyKayRSL3Yu5SE
@chenchaoyi chenchaoyi merged commit 5ee6bb2 into master Jun 18, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants