Small, focused helpers for command line programs and tests. The library provides testable abstractions for environment handling, time, file system operations, logging, hashing, and common user paths.
Recent changes moved dependency wiring to an explicit Runtime model. Context
values are no longer used for runtime dependencies like
clock/logger/stream/hasher.
- Testable environment via
TestEnvwithout mutating OS process env. - Explicit
Runtimedependency container (Env,FS, clock, logger, stream, hasher). - Defaulting helpers:
clock.OrDefault,mylog.OrDefault,toolkit.OrDefaultStream, andtoolkit.OrDefaultHasher. - User-path helpers for config/data/state/cache plus repository-aware app paths.
Sandboxtest harness with jailed filesystem, test clock, logger, and env.ProcessandPipelinehelpers for testing CLI-style I/O flows.
Envinterface withOsEnvandTestEnvimplementations.FileSysteminterface withOsFSimplementation.Runtimeas the main dependency hub (NewRuntime,NewTestRuntime,NewOsRuntime).Streammodel for stdin/stdout/stderr with TTY/piped metadata.- Path/file helpers (
ResolvePath,AbsPath,AtomicWriteFile,Glob, etc.).
AppPathsstruct for repository and platform-scoped app roots.NewAppPaths(rt, root, appname)for explicit root wiring.NewGitAppPaths(ctx, rt, appname)for git-root discovery with fallback scanning.
NewLoggerfor text/JSON slog logger setup.NewTestLogger+TestHandlerfor log assertions in tests.ParseLevel,FindEntries, andRequireEntrytest helpers.Default/OrDefaultlogger helpers.
Clockinterface withOsClockandTestClock.Default/OrDefaultclock helpers.
NewSandboxfor end-to-end test setup.WithEnv,WithEnvMap,WithWd,WithClock,WithFixtureoptions.ProcessandPipelinefor isolated execution and piped stage testing.
go get github.com/jlrickert/cli-toolkitrt, _ := toolkit.NewTestRuntime("/tmp/jail", "/home/alice", "alice")
_ = rt.Set("FOO", "bar")
out := toolkit.ExpandEnv(rt, "$FOO/baz")
// out == "bar/baz" on unix-like platformstc := clock.NewTestClock(time.Date(2020, 1, 1, 12, 0, 0, 0, time.UTC))
c := clock.OrDefault(tc)
now := c.Now()
tc.Advance(2 * time.Hour)
later := c.Now()
_ = now
_ = laterrt, _ := toolkit.NewTestRuntime("/tmp/jail", "/home/alice", "alice")
err := rt.AtomicWriteFile("some/file.txt", []byte("data"), 0o644)
if err != nil {
// handle
}lg, th := mylog.NewTestLogger(t, mylog.ParseLevel("debug"))
rt, _ := toolkit.NewTestRuntime(
"/tmp/jail",
"/home/alice",
"alice",
toolkit.WithRuntimeLogger(lg),
)
rt.Logger().Debug("example message")
_ = th // assert captured entries in testspaths, err := appctx.NewAppPaths(rt, "/path/to/repo", "myapp")
if err != nil {
// handle
}
cfgRoot := paths.ConfigRoot
// cfgRoot == <user-config-dir>/myappsb := sandbox.NewSandbox(
t,
nil,
sandbox.WithClock(time.Now()),
sandbox.WithEnv("DEBUG", "true"),
)
sb.MustWriteFile("config.txt", []byte("data"), 0o644)
// Use sb.Runtime() and sb in testsContext-based runtime dependency helpers were removed in favor of explicit runtime wiring:
clock.WithClock/clock.ClockFromContext-> usetoolkit.Runtime.Clock()orclock.OrDefault.mylog.WithLogger/mylog.LoggerFromContext-> usetoolkit.Runtime.Logger()ormylog.OrDefault.toolkit.WithHasher/toolkit.HasherFromContext-> usetoolkit.Runtime.Hasher()ortoolkit.OrDefaultHasher.toolkit.WithStream/toolkit.StreamFromContext-> usetoolkit.Runtime.Stream()ortoolkit.OrDefaultStream.
Run all tests with:
go test ./...Many helpers provide test-friendly variants and fixtures. sandbox.NewSandbox
wires TestEnv, TestClock, test logger, hasher, and jailed filesystem.
Contributions and issues are welcome. Please open an issue or pull request with a short description and tests for new behavior.
toolkit/- core helpers (env, filesystem, runtime, streams, paths)apppaths/- app path and git-root helpers (package nameappctx)mylog/- structured logging utilitiesclock/- time abstractionssandbox/- comprehensive test setup
- The library aims to stay small and easy to audit.
- Tests avoid touching real OS state via
TestEnv,TestClock, and jailed paths. - Runtime dependencies are passed explicitly via
toolkit.Runtime.
See the repository root for license information.