keel

package module
v0.9.2 Latest Latest
Warning

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

Go to latest
Published: Sep 5, 2026 License: Apache-2.0 Imports: 2 Imported by: 0

README

keel

Shared Go foundation for process execution and logging, consumed by downstream Go services. One public module, one tag, one version:

go get github.com/david-aggeler/keel

Purpose

For whatever reason, LLMs in 2026 are still struggling in some areas, and I'm using these base libraries in my other projects. keel covers the infrastructure concerns every one of those projects needs and that agents keep getting subtly wrong: logging, CLI structure, and subprocess handling. The code here is close to 100% AI generated.

Logging

An opinionated implementation: one logger, several sinks, all sharing the same redaction path and severity vocabulary.

  • Console: plain text
  • Console: sparse AI — minimal progress noise, but a precise log pointer on error
  • Console: full JSON records
  • File: plain text and JSONL
  • OpenTelemetry: optional OTLP export target via log/otel — importing it is what opts you into the OpenTelemetry SDK dependency; the core stays dependency-free

Plain-text console:

21:00:53 INFO  process start event_type=process_start program=sh command_line=sh -c "…" working_dir=/projects/keel
21:00:53 ERROR  process output event_type=process_output stream=stderr data=child stderr line
21:00:53 INFO  process end event_type=process_end exit_code=0 elapsed_ms=0

Sparse-AI console — compact records, and errors carry an exact file+line pointer into the run's .jsonl log:

{"level":"INFO","event":"process_start","message":"process start","fields":{"program":"sh","service":"keel-demo"}}
{"level":"ERROR","event":"log","message":"keel-demo failed","fields":{"err":{"exit_code":4,"log_file":".logs/20260712T190059Z.jsonl","start_line":13,"hint":"inspect .logs/20260712T190059Z.jsonl from line 13"}}}
CLI

CLIs are currently one of the strongest interfaces for LLMs to work with, so a structured way to declare commands, flags, and generated help text is essential. Consumers describe their CLI as a tree of command specs; dispatch, flag validation, and rendered help all come from that single model.

Plain-text help (keel-demo --help):

keel-demo runs the log and exec showcase.

Usage:
  keel-demo [--mode human|ai|json]
  keel-demo help [command]

Global flags:
  --mode human|ai|json
      Console mode. (default human)

Commands:
  workflow  Parent command with nested help.

The same help in JSON mode (keel-demo --mode json --help) arrives as a single machine-readable record:

{"ts":"2026-07-12T21:01:06+02:00","level":"INFO","msg":"keel-demo help","service":"keel-demo","event_type":"help","command":"keel-demo","help":"keel-demo runs the log and exec showcase.\n\nUsage:\n  keel-demo [--mode human|ai|json]\n…","mode":"json"}
Process Management

Ties closely with logging: every subprocess launch gets uniform START/END lifecycle records, proper stdout/stderr handling, and log-line filtering designed to stay token-efficient for LLM consumers.

Requirements

Dev-process records (requirements, change requests, epics) live outside the repo.

License

Apache-2.0 — see LICENSE.

Packages

Package Import path What it is
log github.com/david-aggeler/keel/log Structured logging: JSON + human-readable console handlers sharing one redaction path and severity vocabulary, build identity, metrics, recent-log ring, operational errors.
cli github.com/david-aggeler/keel/cli Shared command tree, generated help, and usage-error contract for first-party developer CLIs: one CommandSpec model drives dispatch, flag validation, and rendered help.
log/otel github.com/david-aggeler/keel/log/otel Optional OpenTelemetry log exporter bridge (OTLP). Quarantined sibling: only importing it pulls in the OpenTelemetry SDK; core log stays dependency-free.
exec github.com/david-aggeler/keel/exec ProcessStart — the single seam for launching subprocesses with uniform lifecycle observability: START (full untruncated command line + cwd), DURING (streamed output), END (exit code + duration), sensitive-arg redaction.
exec/claude github.com/david-aggeler/keel/exec/claude Adapter for headless claude -p invocations (streaming output).
exec/codex github.com/david-aggeler/keel/exec/codex Adapter for headless codex exec --json invocations: prompt in, streaming JSONL events out, determinate result/error contract, stub-tested.
worktree github.com/david-aggeler/keel/worktree Git worktree lifecycle: bring-up that refuses a checkout it does not own, tear-down gated on inspectable working-tree state rather than merge status (with every blocking path or commit named), read-only state and branch-comparison reports, and separate safe-delete branch removal.

Layering: logexec ← {exec/claude, exec/codex, worktree}; cli stands alone. No external dependencies in the core compile graph — log/otel is the one deliberate exception — and no internal replace directives.

Keel Test Bridge (VSIX)

vsix/ holds the Keel Test Bridge, a VS Code extension that surfaces keel's devtool test protocol in the VS Code Testing UI. It activates only when a workspace contains .vscode/test-bridge.json and is versioned in lockstep with the Go module — one tag covers both. Each release attaches the built .vsix as a GitHub release asset.

Usage

Condensed from the runnable example_test.go files in each package — see those for the full, tested versions.

Logging
import logging "github.com/david-aggeler/keel/log"

logger, err := logging.New(logging.Config{Service: "demo", Console: logging.ConsoleJSON})
if err != nil {
    // handle
}
logger.Info("service starting", "port", 8080)

// With returns a derived logger that stamps the given attributes on
// every subsequent record.
reqLog := logger.With("request_id", "r-42")
reqLog.Info("handling request")
Process execution
import procexec "github.com/david-aggeler/keel/exec"

proc, err := procexec.ProcessStart(context.Background(), procexec.Request{
    Program: "echo",
    Args:    []string{"hello from keel/exec"},
    Logger:  logger, // START/END lifecycle records land here
})
if err != nil {
    // handle
}
res, err := proc.Wait() // ProcessStart returns immediately; Wait blocks
fmt.Print(res.Stdout)
CLI
import "github.com/david-aggeler/keel/cli"

root := &cli.CommandSpec{
    Name: "keel-demo",
    Config: cli.Config{
        Program: "keel-demo",
        Usage:   "keel-demo <command> [args]",
        GlobalFlags: []cli.FlagSpec{
            {Name: "mode", Value: "human|ai|json", Default: "human", Short: "Console protocol."},
        },
    },
    Subcommands: []*cli.CommandSpec{{
        Name:  "echo",
        Use:   "echo <text>",
        Short: "Print text.",
        Handler: func(_ context.Context, args []string) error {
            fmt.Println(strings.Join(args, " "))
            return nil
        },
    }},
}

cfg, words, _ := cli.ParseGlobalConfig(os.Args[1:]) // shared global flags first
_ = cfg
err := root.Dispatch(context.Background(), words)   // walks the tree, runs the handler

Documentation

Overview

Package keel exposes the module-level version-of-record.

Index

Constants

This section is empty.

Variables

View Source
var BuildNumber string

BuildNumber carries the monotonic build number — the commit count since the repository's first commit — stamped at build time with -ldflags "-X github.com/david-aggeler/keel.BuildNumber=<n>". Package keel never executes git; an unstamped build leaves it empty.

Functions

func Semver

func Semver() string

DHF-REQ: keel/requirement-110

func Version

func Version() string

Version returns the dotted MAJOR.MINOR.PATCH.BUILD form when a build number was stamped, and the bare VERSION semver otherwise. A stamp that is not a plain digit string is ignored so the surface stays 4-part numeric.

DHF-REQ: keel/requirement-110 (keel/ac-688, keel/ac-689)

Types

This section is empty.

Directories

Path Synopsis
Package cli provides keel's shared command tree, generated help, and usage-error contract for first-party developer CLIs.
Package cli provides keel's shared command tree, generated help, and usage-error contract for first-party developer CLIs.
cmd
keel-demo command
Command keel-demo is a first-party demonstration binary for visually comparing keel/log and keel/exec renderings across console modes.
Command keel-demo is a first-party demonstration binary for visually comparing keel/log and keel/exec renderings across console modes.
keel-demo-dev command
Command keel-demo-dev is a reference consumer devtool for the VS Code test bridge contract.
Command keel-demo-dev is a reference consumer devtool for the VS Code test bridge contract.
keel-dev command
Command keel-dev is keel's single first-party CLI: the deterministic verification gate (`ci`) and the scripted release loop (`release`).
Command keel-dev is keel's single first-party CLI: the deterministic verification gate (`ci`) and the scripted release loop (`release`).
Package exec is keel's subprocess facility: one place to launch external commands so that every child process is logged uniformly and its output is scrubbed of secrets.
Package exec is keel's subprocess facility: one place to launch external commands so that every child process is logged uniformly and its output is scrubbed of secrets.
claude
Package claude wraps headless `claude -p` invocations: prompt in, final text plus token/cost/turn metrics out.
Package claude wraps headless `claude -p` invocations: prompt in, final text plus token/cost/turn metrics out.
codex
Package codex wraps headless `codex exec --json` invocations: prompt in, a streaming JSONL event log out.
Package codex wraps headless `codex exec --json` invocations: prompt in, a streaming JSONL event log out.
log
Package log is keel's structured-logging foundation: a thin layer over the standard library's log/slog that every keel consumer shares.
Package log is keel's structured-logging foundation: a thin layer over the standard library's log/slog that every keel consumer shares.
logtest
Package logtest provides keel/log's optional test capture handler.
Package logtest provides keel/log's optional test capture handler.
otel
Package otel provides keel/log's optional OpenTelemetry log exporter bridge.
Package otel provides keel/log's optional OpenTelemetry log exporter bridge.
recent
Package recent provides an optional in-memory recent-log tail handler.
Package recent provides an optional in-memory recent-log tail handler.
Package testbridge provides the reusable devtool side of keel's VS Code test bridge contract.
Package testbridge provides the reusable devtool side of keel's VS Code test bridge contract.
Package vscode holds the consumer-neutral core of the VS Code test-runner bridge: the run-event/lock/location/artifact wire types and the WorkspaceProfile port through which a consumer dev tool injects its repo-specific behavior.
Package vscode holds the consumer-neutral core of the VS Code test-runner bridge: the run-event/lock/location/artifact wire types and the WorkspaceProfile port through which a consumer dev tool injects its repo-specific behavior.
Package worktree is keel's git worktree lifecycle facility: one neutral mechanism for bringing worktrees up and tearing them down, with no product, tool, or agent vocabulary anywhere in its surface.
Package worktree is keel's git worktree lifecycle facility: one neutral mechanism for bringing worktrees up and tearing them down, with no product, tool, or agent vocabulary anywhere in its surface.
replicate
Package replicate resolves the keel.worktree.replicate configuration subtree into neutral worktree replication items.
Package replicate resolves the keel.worktree.replicate configuration subtree into neutral worktree replication items.

Jump to

Keyboard shortcuts

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