Agent skill

Ghttp

by onsi in onsi/gomega

The ghttp test HTTP server for testing HTTP clients — NewServer/NewTLSServer, AppendHandlers, the Verify assertions (VerifyRequest/VerifyHeader/VerifyHeaderKV/VerifyJSON/VerifyForm/VerifyBasicAuth/Ve…

MITAuto-check passedDevelopment

Install Ghttp

skills CLI
$ npx skills add onsi/gomega --skill ghttp -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install onsi/gomega ghttp --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/onsi/gomega.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/gomega/skills/ghttp .claude/skills/ghttp && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
ghttp
GitHub stars
2.4k
Token cost
~2.2k tokens
SKILL.md length
558 words
Files
1
Skills in repo
12
Repo updated
First seen
Licence
MIT

At a glance

The ghttp test HTTP server for testing HTTP clients — NewServer/NewTLSServer, AppendHandlers, the Verify assertions (VerifyRequest/VerifyHeader/VerifyHeaderKV/VerifyJSON/VerifyForm/VerifyBasicAuth/Ve…

  • Testing code that makes outbound HTTP requests
  • SKILL.md covers Lifecycle, The handler model, Verifying the incoming request and Combining handlers for one…, plus 7 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Ghttp is an agent skill from onsi/gomega. The ghttp test HTTP server for testing HTTP clients — NewServer/NewTLSServer, AppendHandlers, the Verify assertions (VerifyRequest/VerifyHeader/VerifyHeaderKV/VerifyJSON/VerifyForm/VerifyBasicAuth/VerifyContentType/VerifyBody), RespondWith/RespondWithJSONEncoded(Ptr), CombineHandlers, RouteToHandler for unordered MUXed routes, AllowUnhandledRequests, RoundTripper, and TLS. Use when testing code that makes outbound HTTP requests.

Its SKILL.md is about 2.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development. The repository describes itself as: Ginkgo's Preferred Matcher Library. The licence is MIT.

When your agent uses it

  • Testing code that makes outbound HTTP requests

Example prompts

  • “/ghttp”

What it can do on your machine

Read from SKILL.md and the folder at commit 37fa900. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are go).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • onsi.github.io

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Ghttp loads about 2.2k tokens when it runs. Until then it costs about 110 tokens; SKILL.md has 558 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~110
When it runs · the whole SKILL.md, loaded when a task matches
~2.2k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from onsi/gomega at commit 37fa900, republished under its MIT licence (© onsi). 558 words, ~2,176 tokens.

Download SKILL.mdSave it as .claude/skills/ghttp/SKILL.md (or your agent's skills folder).
name
ghttp
description
The ghttp test HTTP server for testing HTTP clients — NewServer/NewTLSServer, AppendHandlers, the Verify* assertions (VerifyRequest/VerifyHeader/VerifyHeaderKV/VerifyJSON/VerifyForm/VerifyBasicAuth/VerifyContentType/VerifyBody), RespondWith/RespondWithJSONEncoded(Ptr), CombineHandlers, RouteToHandler for unordered MUXed routes, AllowUnhandledRequests, RoundTripper, and TLS. Use when testing code that makes outbound HTTP requests.

ghttp: testing HTTP clients

ghttp spins up a real test HTTP server so you can exercise code that makes outbound HTTP requests (clients, SDKs, anything calling net/http). You register handlers that assert on the incoming request and return a canned response; the server records every request it receives. It wraps net/http/httptest.

go
import (
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/ghttp"
	"net/http"
)

This skill assumes a dot-import of gomega. Docs: https://onsi.github.io/gomega/#ghttp-testing-http-clients. See gomega:matchers for the matchers used in assertions and gomega:async if the client is non-blocking.

Lifecycle

go
server := ghttp.NewServer()          // or ghttp.NewTLSServer()
defer server.Close()                 // ALWAYS defer Close

client := myapi.NewClient(server.URL())   // URL is random per run — inject it

The server URL is auto-generated and varies between runs, so you must inject server.URL() into the code under test rather than hard-coding it. With Ginkgo, server = ghttp.NewServer() in BeforeEach and server.Close() in AfterEach.

The handler model

server.AppendHandlers(handlers...) registers an ordered list of handlers, one per expected request. The first request is matched against the first handler, the second against the second, and so on. A handler is just an http.HandlerFunc.

go
server.AppendHandlers(
	ghttp.VerifyRequest("GET", "/sprockets"),
)

Gotchas (the core mental model):

  • AppendHandlers is strictly ordered. Requests must arrive in exactly the registered order.
  • Each handler handles exactly one request. To run several checks against a single request, combine them with ghttp.CombineHandlers (below).
  • The request count is asserted by default. If the client sends more requests than there are handlers (or hits an unregistered route), the test fails. Guard the trivial false-positive (client made no request) with Expect(server.ReceivedRequests()).To(HaveLen(1)).

Verifying the incoming request

These return handlers that fail the test if the request doesn't match:

go
ghttp.VerifyRequest("GET", "/sprockets")                       // method + path
ghttp.VerifyRequest("GET", "/sprockets", "category=encabulators") // + RawQuery
ghttp.VerifyHeader(http.Header{"X-API-Version": []string{"1.0"}})
ghttp.VerifyHeaderKV("X-API-Version", "1.0")                   // convenience for one key
ghttp.VerifyContentType("application/json")
ghttp.VerifyBasicAuth("gopher", "tacoshell")
ghttp.VerifyBody([]byte("raw body"))
ghttp.VerifyJSON(`{"name":"foo"}`)                             // semantic JSON compare
ghttp.VerifyJSONRepresenting(Sprocket{Name: "foo"})           // marshal obj, then compare
ghttp.VerifyForm(url.Values{"q": []string{"x"}})              // parsed form values
ghttp.VerifyFormKV("q", "x")                                  // convenience for one key

The path argument to VerifyRequest accepts a string or a *regexp.Regexp. You can write your own verify handler — pass any http.HandlerFunc that makes assertions against the *http.Request.

Combining handlers for one request

ghttp.CombineHandlers(...) wraps several handlers into one handler so they all run against a single request. Pass that one wrapper to AppendHandlers. This is how you assert on a request and respond:

go
server.AppendHandlers(
	ghttp.CombineHandlers(
		ghttp.VerifyRequest("GET", "/sprockets", "category=encabulators"),
		ghttp.VerifyBasicAuth(username, password),
		ghttp.VerifyHeaderKV("X-API-Version", "1.0"),
		ghttp.RespondWithJSONEncoded(http.StatusOK, sprockets),
	),
)

Providing responses

go
ghttp.RespondWith(http.StatusOK, `[{"name":"foo"}]`)          // status + body (+ optional http.Header)
ghttp.RespondWith(http.StatusOK, body, http.Header{"X-Foo": []string{"bar"}})
ghttp.RespondWithJSONEncoded(http.StatusOK, anyObject)        // JSON-encodes the object for you
ghttp.RespondWithJSONEncodedPtr(&statusCode, &object)         // reads through pointers at request time
ghttp.RespondWithPtr(&statusCode, &body)

End-to-end example

go
var server *ghttp.Server
var client *sprockets.Client

BeforeEach(func() {
	server = ghttp.NewServer()
	client = sprockets.NewClient(server.URL())
})
AfterEach(func() { server.Close() })

It("fetches sprockets", func() {
	returned := []Sprocket{{Name: "entropic decoupler", Color: "red"}}
	server.AppendHandlers(
		ghttp.CombineHandlers(
			ghttp.VerifyRequest("GET", "/sprockets", "category=encabulators"),
			ghttp.VerifyHeaderKV("X-API-Version", "1.0"),
			ghttp.RespondWithJSONEncoded(http.StatusOK, returned),
		),
	)

	sprockets, err := client.FetchSprockets("encabulators")
	Expect(err).NotTo(HaveOccurred())
	Expect(sprockets).To(Equal(returned))
	Expect(server.ReceivedRequests()).To(HaveLen(1))
})

Testing different response scenarios

To exercise 200/401/404 against the same handler setup, capture a status (and/or body) variable in a closure via the *Ptr responders and mutate it per sub-context. The pointer is dereferenced when the request arrives:

go
var statusCode int
var returned []Sprocket

BeforeEach(func() {
	server.AppendHandlers(ghttp.CombineHandlers(
		ghttp.VerifyRequest("GET", "/sprockets"),
		ghttp.RespondWithJSONEncodedPtr(&statusCode, &returned),
	))
})

Context("when unauthorized", func() {
	BeforeEach(func() { statusCode = http.StatusUnauthorized })
	It("errors", func() {
		_, err := client.FetchSprockets("")
		Expect(err).To(MatchError(SprocketsErrorUnauthorized))
	})
})
Show full SKILL.md (220 more words)Show less

Handling multiple requests

Pass multiple handlers to AppendHandlers for clients that make several requests (e.g. pagination). They're consumed in order:

go
server.AppendHandlers(
	ghttp.CombineHandlers(
		ghttp.VerifyRequest("GET", "/sprockets", "category=encabulators"),
		ghttp.RespondWithJSONEncoded(http.StatusOK, firstPage),
	),
	ghttp.CombineHandlers(
		ghttp.VerifyRequest("GET", "/sprockets", "category=encabulators&pagination-token=next"),
		ghttp.RespondWithJSONEncoded(http.StatusOK, secondPage),
	),
)

Because the server fails when requests exceed handlers, this also asserts the client stops after the last page.

Mutating registered handlers by index
go
server.SetHandler(0, newHandler)            // replace handler at index
h := server.GetHandler(0)                   // read it back
server.WrapHandler(0, extraVerifyHandler)   // run an extra handler around the existing one

MUXing unordered routes

AppendHandlers is for ordered assertions. When requests can arrive in any order or any number of times, use server.RouteToHandler(method, path, handler) instead. The path is a string or a *regexp.Regexp.

go
server.RouteToHandler("POST", "/login", ghttp.CombineHandlers(
	ghttp.VerifyRequest("POST", "/login", "user=bob&password=password"),
	ghttp.RespondWith(http.StatusOK, "your-auth-token"),
))

Routing precedence: on each request the server first checks RouteToHandler routes; if none match it pops the next AppendHandlers handler; if that stack is empty it consults the unhandled-request policy below. You can mix both: ordered assertions via AppendHandlers for the requests you care about, MUXed routes for incidental traffic (auth, health checks) that interleaves.

Allowing unhandled requests

By default an unhandled request fails the test. To return a fixed status instead:

go
server.SetAllowUnhandledRequests(true)
server.SetUnhandledRequestStatusCode(http.StatusOK) // default would be 500

Unhandled requests are still recorded in server.ReceivedRequests(), so you can assert on them after the fact.

Escape hatches

  • server.HTTPTestServer is the underlying *httptest.Server — use it for custom listeners (via ghttp.NewUnstartedServer() + server.Start()), TLS config, or anything ghttp doesn't wrap.
  • server.RoundTripper(rt) returns an http.RoundTripper that redirects requests to the test server. Use it when you must hand a configured *http.Client to the code under test rather than a URL. Pass nil to use http.DefaultTransport:
go
httpClient := &http.Client{Transport: server.RoundTripper(nil)}

© onsi, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in plugins/gomega/skills/ghttp of onsi/gomega.

Open the folder on GitHubat commit 37fa900

Compare with similar skills

Ghttp next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Ghttp compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Ghttp this skillonsi/gomega2.4k—~2.2kAutomated safety check: PassMIT
Vercel Composition Patternssupabase/supabase111k59 repos~726Automated safety check: PassMIT
Finishing a Development Branchobra/superpowers296k5 repos~1.9kAutomated safety check: PassMIT
Typescript Advanced Typesrolling-scopes/rsschool-app10k25 repos~4.2kAutomated safety check: PassMPL-2.0
PR Babysitteropeninterpreter/openinterpreter69k3 repos~4.2kAutomated safety check: PassApache-2.0
Code Review ChecklistshareAI-lab/learn-claude-code78k5 repos~1.1kAutomated safety check: PassMIT

Similar skills

  • Official

    React composition patterns that scale. An agent skill from supabase/supabase.

    111k GitHub starsUsed in 59 repos~726 tokens
    DevelopmentAuto-check passed
  • Walks the last step of a branch: confirm tests pass, detect the git environment, ask how to integrate, carry out your choice and clean up the worktree.

    296k GitHub starsUsed in 5 repos~1.9k tokens
    DevelopmentAuto-check passed
  • Typescript Advanced Types

    rolling-scopes/rsschool-app

    Master TypeScript's advanced type system including generics, conditional types, mapped types, template literals, and utility types for building type-safe applications.

    10k GitHub starsUsed in 25 repos~4.2k tokens
    DevelopmentAuto-check passed
  • PR Babysitter

    openinterpreter/openinterpreter

    Watches an open GitHub pull request until it merges, handling review comments, diagnosing CI failures and retrying flaky checks along the way.

    69k GitHub starsUsed in 3 repos~4.2k tokens
    DevelopmentAuto-check passed
  • Code Review Checklist

    shareAI-lab/learn-claude-code

    Reviews code against a five-part checklist covering security, correctness, performance, maintainability and testing, and reports findings in a fixed format.

    78k GitHub starsUsed in 5 repos~1.1k tokens
    DevelopmentAuto-check passed
  • Greploop

    onyx-dot-app/onyx

    Iteratively improves a PR (GitHub), MR (GitLab), or shelved changelist (Perforce) until Greptile gives it a 5/5 confidence score with zero unresolved comments.

    32k GitHub starsUsed in 4 repos~3.3k tokens
    DevelopmentAuto-check passed

More from onsi/gomega

All 12 skills in this repo
  • Assertions

    onsi/gomega

    Write correct synchronous Gomega assertions — Expect/Ω notation, the To/NotTo/ToNot/Should/ShouldNot equivalences, the multi-return error idiom, Succeed vs HaveOccurred, the .Error() chaining form…

    2.4k GitHub stars~2.1k tokensUpdated 13 days ago
    Auto-check passed
  • Async

    onsi/gomega

    Polling assertions in Gomega — Eventually (poll until it passes) and Consistently (must keep passing), the func(g Gomega) callback idiom, WithTimeout/WithPolling/Within/ProbeEvery, WithContext and…

    2.4k GitHub stars~2.2k tokensUpdated 13 days ago
    Auto-check passed
  • Build compound Gomega assertions by combining matchers — And/SatisfyAll (all pass), Or/SatisfyAny (any pass), Not (negate), WithTransform to map the actual before matching, Satisfy for an ad-hoc…

    2.4k GitHub stars~1.5k tokensUpdated 13 days ago
    Auto-check passed
  • Custom Matchers

    onsi/gomega

    Writing your own Gomega matchers — the GomegaMatcher interface (Match/FailureMessage/NegatedFailureMessage), gcustom.MakeMatcher with message templates and template data, the format package helpers…

    2.4k GitHub stars~2.4k tokensUpdated 13 days ago
    Auto-check passed
  • Gbytes

    onsi/gomega

    Testing streaming io buffers with gbytes — gbytes.NewBuffer() (an io.Writer also returned by gexec sessions), the Say(regexp) matcher that forward-scans from a moving read cursor, the canonical…

    2.4k GitHub stars~1.5k tokensUpdated 13 days ago
    Auto-check passed
  • Gexec

    onsi/gomega

    Testing external processes with gexec — compile binaries with Build/BuildWithEnvironment/BuildIn and CleanupBuildArtifacts, start them with Start returning a Session, await exit with the Exit…

    2.4k GitHub stars~1.3k tokensUpdated 13 days ago
    Auto-check passed

Categories

Questions about Ghttp

What does Ghttp do?

The ghttp test HTTP server for testing HTTP clients — NewServer/NewTLSServer, AppendHandlers, the Verify assertions (VerifyRequest/VerifyHeader/VerifyHeaderKV/VerifyJSON/VerifyForm/VerifyBasicAuth/Ve…. Ghttp is an agent skill from onsi/gomega. The ghttp test HTTP server for testing HTTP clients — NewServer/NewTLSServer, AppendHandlers, the Verify assertions (VerifyRequest/VerifyHeader/VerifyHeaderKV/VerifyJSON/VerifyForm/VerifyBasicAuth/VerifyContentType/VerifyBody), RespondWith/RespondWithJSONEncoded(Ptr), CombineHandlers, RouteToHandler for unordered MUXed routes, AllowUnhandledRequests, RoundTripper, and TLS.

When should I use Ghttp?

Ghttp fits situations like: testing code that makes outbound HTTP requests.

How do I install Ghttp in Claude Code?

Run `npx skills add onsi/gomega --skill ghttp -a claude-code`. Or copy the skill folder (plugins/gomega/skills/ghttp in onsi/gomega) into .claude/skills/ghttp in your project. Claude Code loads it when a task matches its description.

How do I install Ghttp in Codex?

Run `npx skills add onsi/gomega --skill ghttp -a codex`. Or copy the skill folder (plugins/gomega/skills/ghttp in onsi/gomega) into .agents/skills/ghttp in your project. Codex loads it when a task matches its description.

Can I use Ghttp in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add onsi/gomega --skill ghttp -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ghttp, .gemini/skills/ghttp, .github/skills/ghttp and .opencode/skills/ghttp in your project.

What does Ghttp need to run?

SKILL.md names no scripts, command-line tools or credentials: Ghttp is instructions for the agent only.

Does Ghttp access the network?

SKILL.md names 1 domain. As links in the text: onsi.github.io. This is read from the text; nothing was executed.

Is Ghttp safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Ghttp use?

Ghttp is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Ghttp use?

About 2.2k tokens (SKILL.md is roughly 8.7k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Ghttp?

Skills that share tags, products or a category with Ghttp: Vercel Composition Patterns (supabase/supabase, 111k stars), Finishing a Development Branch (obra/superpowers, 296k stars), Typescript Advanced Types (rolling-scopes/rsschool-app, 10k stars) and PR Babysitter (openinterpreter/openinterpreter, 69k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Ghttp?

onsi (a GitHub user) maintains it in onsi/gomega, which has 2,357 GitHub stars. The repository holds 12 skills in this directory. The repository was last updated on September 24, 2026.

Source: onsi/gomega on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.