cupel

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 3, 2026 License: MIT

README

cupel

cupel turns an English-language specification into Go tests by calling Claude, and writes them into a goforge component. It produces three styles of test for the same spec:

  1. Example tests — concrete, readable cases (plus testable Example funcs).
  2. Parameterized / data-driven tests — table-driven t.Run cases.
  3. Property-based tests — invariants checked with the standard-library testing/quick.

The output is not a loose file: cupel enforces the goforge architecture on it. The model reply is de-fenced, parsed, required to declare the external <iface>_test package, gofmt-formatted, written into components/<name>/ alongside a valid interface/internal/component.yaml scaffold, and then validated by running goforge check.

A cupel is the porous vessel an assayer uses to refine raw metal — here it refines raw prose into tests.

Built with goforge

cupel is itself a goforge workspace, so its own structure obeys the same worker-type discipline it enforces on its output:

brick kind worker type
spec component deterministic/pure — parse & validate the spec
prompt component deterministic/pure — build the Claude messages
architecture component deterministic/pure — validate/format output, render the brick
claude component non_deterministic/[input_effect, output_effect] — Anthropic Messages API backend
claudecode component non_deterministic/[input_effect, output_effect] — local Claude Code CLI backend
gen component non_deterministic/[input_effect, output_effect] — orchestrate & write files
cli base the effect boundary (effective: non_deterministic/[input_effect, output_effect])

goforge classify shows the cli base is declared pure but effectively effectful — effects propagate up from claude/gen through the dependency closure, exactly as goforge intends.

Install

go install goforge.dev/cupel/projects/cupel@latest   # the cupel CLI
go install goforge.dev/goforge@latest                 # needed for the check step

Use

Run from inside any goforge workspace. name: is the target component.

# api backend (default) — calls the Anthropic API
export ANTHROPIC_API_KEY=sk-...
cupel name:user spec:"A user has a non-empty name and an email containing '@'.
Two users are equal iff their emails match (case-insensitive)."

# cli backend — drives the local Claude Code `claude` CLI instead (no API key)
cupel name:user backend:cli spec-file:user.md

# from stdin
cat order.md | cupel name:order
Backends
backend: how it generates needs
api (default) Anthropic Messages API over HTTP, system prompt cached ANTHROPIC_API_KEY
cli shells out to claude -p ... --append-system-prompt ... in headless print mode Claude Code installed (claude on PATH, or CUPEL_CLAUDE_BIN)

Both backends feed the identical prompt and the same output enforcement, so the generated tests and the trailing goforge check are the same either way.

Arguments (poly-style key:value / :flag):

arg meaning
name:NAME target goforge component (required)
iface:PKG public package of that component (default NAME)
spec:"TEXT" inline specification
spec-file:PATH read the spec from a file
backend:WHICH api (default) or cli (drive the Claude Code CLI)
model:ID Claude model ($CUPEL_MODEL; api default claude-opus-4-8, cli default its own)
root:DIR workspace root (default: discovered from cwd)
:force overwrite the interface/internal/yaml scaffold
:dry-run render everything, write nothing
:no-check skip the trailing goforge check

cupel writes components/<name>/<name>_test.go (always) and, when the brick does not yet exist, a placeholder interface, internal/core.go, and component.yaml so the result is a complete, check-valid goforge component.

Develop

go test ./...           # unit tests for every brick (offline)
goforge check           # structure, boundary, worker-type, project deps
goforge classify        # declared vs. effective worker types

Directories

Path Synopsis
bases
cli
Package cli is the cupel base: the entry-point layer that wires the spec, claude, and gen components into a runnable command.
Package cli is the cupel base: the entry-point layer that wires the spec, claude, and gen components into a runnable command.
components
architecture
Package architecture is the public interface of the architecture component.
Package architecture is the public interface of the architecture component.
architecture/internal
Package internal holds the architecture component implementation: the logic that enforces the goforge brick layout on generated test output.
Package internal holds the architecture component implementation: the logic that enforces the goforge brick layout on generated test output.
claude
Package claude is the public interface of the claude component: a thin client for the Anthropic Messages API used to turn a prompt into generated tests.
Package claude is the public interface of the claude component: a thin client for the Anthropic Messages API used to turn a prompt into generated tests.
claude/internal
Package internal holds the claude component implementation: the Anthropic Messages API request/response handling.
Package internal holds the claude component implementation: the Anthropic Messages API request/response handling.
claudecode
Package claudecode is the public interface of the claudecode component: a backend that drives the local Claude Code CLI (`claude`) in headless print mode instead of calling the Anthropic API directly.
Package claudecode is the public interface of the claudecode component: a backend that drives the local Claude Code CLI (`claude`) in headless print mode instead of calling the Anthropic API directly.
claudecode/internal
Package internal holds the claudecode component implementation: invoking the Claude Code CLI in headless print mode.
Package internal holds the claudecode component implementation: invoking the Claude Code CLI in headless print mode.
gen
Package gen is the public interface of the gen component: it orchestrates the pipeline spec -> prompt -> claude -> architecture and writes the resulting goforge component to disk.
Package gen is the public interface of the gen component: it orchestrates the pipeline spec -> prompt -> claude -> architecture and writes the resulting goforge component to disk.
gen/internal
Package internal holds the gen component implementation: writing a rendered brick to disk under a workspace root.
Package internal holds the gen component implementation: writing a rendered brick to disk under a workspace root.
prompt
Package prompt is the public interface of the prompt component.
Package prompt is the public interface of the prompt component.
prompt/internal
Package internal holds the prompt component implementation.
Package internal holds the prompt component implementation.
spec
Package spec is the public interface of the spec component.
Package spec is the public interface of the spec component.
spec/internal
Package internal holds the spec component implementation.
Package internal holds the spec component implementation.
Package development wires every brick into one place for IDE and REPL use.
Package development wires every brick into one place for IDE and REPL use.
projects
cupel command
Command cupel generates example, parameterized/data-driven, and property-based Go tests from an English specification by calling Claude, writing them into a goforge component and validating the result against the goforge architecture.
Command cupel generates example, parameterized/data-driven, and property-based Go tests from an English specification by calling Claude, writing them into a goforge component and validating the result against the goforge architecture.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL