clireview

package
v0.9.3 Latest Latest
Warning

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

Go to latest
Published: May 27, 2026 License: GPL-3.0 Imports: 10 Imported by: 0

Documentation

Overview

Package clireview is the shared implementation of CLI-tool-backed review providers. The concrete providers (claude-cli, gemini-cli, codex-cli) live in their own packages under internal/provider/ — they only declare a Spec and call clireview.New to get a working Backend that implements provider.Provider plus the provider.PlainTextEmitter marker.

Why a shared package: the three CLIs differ only in their binary name and how they accept a one-shot prompt on the command line. Everything else — registering with the provider registry, running the subprocess, surfacing PATH-not-found and exit-non-zero as translatable errors, returning a provider.Response with the raw CLI output as Content — is identical.

CLI providers deliberately have NO API key, NO model selection (the host CLI manages that), and NO per-call cost estimate (the host CLI bills against the user's existing subscription). The review pipeline branches on provider.PlainTextEmitter to skip the JSON contract path, retry-once, and the cards/markdown renderer.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Backend

type Backend struct {
	// contains filtered or unexported fields
}

Backend is a provider.Provider + provider.PlainTextEmitter built around a single Spec. Construct via New; callers don't need to touch the struct directly.

versionOnce + versionMemo cache the result of the host CLI's version query for the lifetime of the process. DefaultModel is on every cache-key computation, so paying the subprocess cost more than once per process startup would be wasteful — and the version can't change underneath us mid-run anyway.

func New

func New(spec Spec) *Backend

New returns a Backend ready to register with the provider registry. Validation of the Spec is deferred to actual use (Review, TestConnection) so a missing binary doesn't crash init().

func (*Backend) ContextWindow

func (b *Backend) ContextWindow(string) int

ContextWindow is informational for CLI providers — we don't gate the request on it because the host CLI handles its own context management. We return a generous default so the dry-run footer doesn't read "0".

func (*Backend) DefaultModel

func (b *Backend) DefaultModel() string

DefaultModel returns a stable identifier for the cache key. CLI tools don't expose model selection to us, so we tag entries with the binary name + detected version. Across CLI upgrades the version changes and cached entries cleanly invalidate.

func (*Backend) EmitsPlainText

func (b *Backend) EmitsPlainText()

EmitsPlainText implements provider.PlainTextEmitter — the marker interface review.go uses to branch into the CLI-output path.

func (*Backend) EstimateTokens

func (b *Backend) EstimateTokens(s string) int

EstimateTokens uses the shared chars/4 heuristic. CLI tools usually don't expose tokenizers we can call from outside their process, so the approximation has to do for the cost preflight and context-window gate.

func (*Backend) Name

func (b *Backend) Name() string

func (*Backend) Pricing

func (b *Backend) Pricing(string) provider.Pricing

Pricing is zero for CLI providers — the user pays through their host-CLI subscription (Claude Pro, Gemini Advanced, ChatGPT Plus, …), not per-token to us. The cost preflight short-circuits on zero pricing, and the verbose footer shows "—" instead of a token count.

func (*Backend) Review

func (b *Backend) Review(ctx context.Context, req provider.Request) (provider.Response, error)

Review invokes the host CLI with the combined system + user prompt, captures stdout, and returns it verbatim as the Response Content. Token usage is zeroed (the CLI doesn't expose it) and Model is set to the resolved DefaultModel so the cache key invalidates on CLI upgrades.

The review pipeline checks provider.PlainTextEmitter before calling, so this is only invoked when the caller is committed to the CLI path — no JSON parsing follows.

func (*Backend) TestConnection

func (b *Backend) TestConnection(ctx context.Context) error

TestConnection verifies the binary is on PATH and runs its version command (when defined). A failed lookup or non-zero exit from the version command surface as the catalog-translatable errors at the CLI layer.

type Spec

type Spec struct {
	// Name is the provider name as it appears in the registry,
	// `commitbrief providers list`, and the `--provider` flag —
	// e.g. "claude-cli", "gemini-cli". The user-facing `--cli`
	// shorthand maps "claude" → "claude-cli" by appending "-cli".
	Name string

	// Binary is the executable name expected on PATH, e.g. "claude",
	// "gemini", "codex". `exec.LookPath` resolves it.
	Binary string

	// PromptArgs returns the argv slice (excluding the binary itself)
	// for a one-shot, non-interactive invocation that prints the
	// model's response to stdout and exits. Implementations should
	// disable colors and tool use where possible so the output stays
	// machine-friendly.
	//
	// When [UseStdin] is true the prompt argument is the empty string
	// and PromptArgs returns *only* the flag/positional combo that
	// makes the host CLI read its prompt from stdin (e.g. claude's
	// `-p -`). The Backend then pipes the combined prompt into the
	// subprocess's stdin instead of embedding it in argv.
	PromptArgs func(prompt string) []string

	// UseStdin selects the stdin transport for the prompt. UC-24 in
	// PATCH_ROADMAP: large prompts (mid-size diffs + rules) exceed the
	// platform ARG_MAX limit when embedded in argv, surfacing as
	// `argument list too long` on Linux/macOS at ~128KB. Piping the
	// prompt via stdin sidesteps the limit entirely.
	//
	// Adapter authors: only set this true when you've confirmed the
	// host CLI reliably reads from stdin in one-shot mode.
	UseStdin bool

	// VersionArgs prints the CLI version and exits. Used by
	// TestConnection to confirm the binary works and by the cache
	// key to invalidate cached entries across CLI upgrades. Optional;
	// if nil, version is "" and cache keys can't differentiate
	// across upgrades.
	VersionArgs []string

	// Timeout caps a single CLI invocation. CLIs sometimes hang on
	// rate limits or network issues; we'd rather surface a clear
	// error than block the user indefinitely. Zero means no timeout.
	Timeout time.Duration
}

Spec describes one CLI backend. Each concrete provider package fills this in once and passes it to New.

Jump to

Keyboard shortcuts

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