| type | Knowledge Pack | ||||
|---|---|---|---|---|---|
| title | CoreCLI Framework | ||||
| description | CLI framework for Lethean command-line tools, built on core/go primitives | ||||
| author | Mistral Vibe | ||||
| version | 1.0.0 | ||||
| created | 2026-06-17 14:40:00 UTC | ||||
| tags |
|
Official site: dappco.re/go/cli/
CoreCLI is the CLI runtime for every Core binary. It builds on core/go (dappco.re/go) — the Core standard library — and keeps its core path free of external dependencies.
From the CoreCLI Migration RFC (plans/code/core/cli/RFC.core-go-migration.md):
CoreCLI is the CLI runtime for every Core binary. It builds on core/go (dappco.re/go) — the Core standard library — and keeps its core path free of external dependencies: every external import is unaudited attack surface against the SASE/HIPAA compliance story, so the library carries none beyond a thin terminal layer.
The cli library imports:
core/go— The Core standard librarygolang.org/x/term— TTY detectiongolang.org/x/sys— System utilitiesmattn/go-runewidth— Display-width calculation (self-contained module)
No CLI framework and no styling library on the dependency list.
ANSI styling and stripping are a zero-dependency implementation in pkg/cli/ansi.go. The Frame/TUI system lives in the opt-in pkg/cli/frame sub-module, which has its own go.mod so its dependencies never reach consumers that need only output and command registration.
The core/go Action registry is the single capability map: c.Action("git.log", handler) registers a named, entitlement-gated action with a description and an input schema.
The CLI, the REST API, and the MCP server are projections of this one map.
cli.MountActions projects the registry onto the command tree: every registered action is a command at the path derived from its dotted name (git.log → core git log), invoked through Action.Run so entitlement and enable/disable gating apply identically across surfaces.
core.Entitled is the access-control layer that decides which caller and which surface may invoke which action — one map, gated per subject and per surface.
Help text for projected actions is generated, not hand-authored. A binary supplies a cli.HelpGenerator; cmd/core's generator composes a readable description from the action name with go-i18n's grammar engine (demo.echo → "Echo the demo").
- Repository: github.com/dappcore/cli
- Module:
dappco.re/go/cli - Dependencies: Zero external CLI frameworks (pure core/go + thin term layer)
go get dappco.re/go/cli@latestimport "dappco.re/go/cli"- Primary spec:
plans/code/core/go/cli/RFC.md(catalogue atplans/code/core/go/cli/RFC.catalog.md) - Migration guide:
plans/code/core/cli/RFC.core-go-migration.md - Implementation:
core/cli/ - Agent guide:
core/cli/AGENTS.md - This pack: INDEX.md for the command inventory and per-area docs
Commands register on a core/go *core.Core through core.Command — path-based routing where the directory-style path (config/get) is the command path.
A binary composes its surface explicitly: each command package exposes an AddXCommands(c *core.Core) core.Result registrar, handed to cli.Main through cli.WithCommands.
Important: cmd binaries are package main and not importable, so they wire registrars directly rather than relying on init() self-registration.
core.Command carries a CommandAction func(core.Options) core.Result. Options is the universal input DTO — flags and positional arguments parse into it — and Result is the universal output. Argument validation happens inside the action.
pkg/cli provides:
- Semantic output:
Success,Error,Warn,Info,Debug - Structured output:
Field,List,Table - Prompts:
Prompt,Confirm,Select - Glyph system: Unicode/emoji/ASCII themes
- HLCRF terminal layout: Header, Left, Content, Right, Footer regions for composite TUIs
Display width and truncation account for wide and zero-width runes.
Translatable strings resolve through cli.T, backed by the Core i18n service with a CLI-local fallback.
Command and action descriptions are i18n keys; the grammar engine renders readable text for keys without a catalog entry. go-i18n is grammar- and phonetics-aware, so generated text is article-correct ("an SSH", "a go.mod").
The CLI test suite under tests/cli/ builds the binary from source and asserts behaviour against the compiled artifact — one Taskfile per command surface (config, doctor, pkg, version, …), each exercising the real binary.
Package tests follow the _Good / _Bad / _Ugly convention.
| Method | Purpose | Example |
|---|---|---|
c.Command(path, action) |
Register command | c.Command("git.log", handler) |
cli.Main(c, opts...) |
Start CLI | cli.Main(c, cli.WithCommands(...)) |
cli.WithCommands(reg...) |
Add registrars | cli.WithCommands(AddGitCommands) |
| Function | Purpose | Example |
|---|---|---|
cli.Success(msg) |
Success message | cli.Success("Done") |
cli.Error(err, msg) |
Error message | cli.Error(err, "Failed") |
cli.Warn(msg) |
Warning message | cli.Warn("Caution") |
cli.Info(msg) |
Info message | cli.Info("Starting...") |
cli.Debug(msg) |
Debug message | cli.Debug("State: %v", state) |
| Function | Purpose | Example |
|---|---|---|
cli.Field(key, value) |
Key-value pair | cli.Field("Name", "value") |
cli.List(key, items) |
List of items | cli.List("Tags", []string{...}) |
cli.Table(headers) |
Table output | cli.Table([][]string{...}) |
| Function | Purpose | Example |
|---|---|---|
cli.Prompt(msg) |
Text input | name := cli.Prompt("Name:") |
cli.Confirm(msg) |
Yes/No | ok := cli.Confirm("Sure?") |
cli.Select(msg, opts) |
Choice | choice := cli.Select("Pick:", opts) |
Cobra-based command tree:
// Root command
var rootCmd = &cobra.Command{
Use: "app",
Short: "Application description",
Long: "Detailed application description",
}
// Subcommands
var serveCmd = &cobra.Command{
Use: "serve",
Short: "Start the server",
RunE: serveHandler,
}
func serveHandler(cmd *cobra.Command, args []string) error {
// Semantic output
return core.ResultFromError(serve()).Log().Error()
}Always structured:
{
"status": "success",
"result": {
"message": "Server started",
"address": "localhost:8080"
}
}
{
"status": "error",
"error": {
"code": "PORT_IN_USE",
"message": "Port 8080 already in use"
}
}Natural language support:
# Traditional
app serve --port 8080 --host 0.0.0.0
# Natural language (via agent)
app serve on port 8080 on all interfaces// In your command package
func AddGitCommands(c *core.Core) core.Result {
c.Command("git.log", func(opts core.Options) core.Result {
dir := opts.String("dir")
// Parse additional flags and args from opts
return c.Process().RunIn(ctx, dir, "git", "log")
})
return core.Ok(nil)
}
// In main.go
func main() {
c := core.New()
cli.Main(c,
cli.WithCommands(AddGitCommands),
cli.WithCommands(AddConfigCommands),
)
}// Success output
cli.Success("Operation completed successfully")
// Error output
cli.Error(err, "Failed to complete operation")
// Warning output
cli.Warn("This action may have side effects")
// Structured output
cli.Field("Name", "value")
cli.List("Items", []string{"a", "b", "c"})
cli.Table([][]string{
{"Name", "Status"},
{"Service1", "Running"},
{"Service2", "Stopped"},
})// In your command
desc := cli.T("git.log.desc") // Translated via i18n
// With fallback
msg := cli.T("some.key", "Default message if key not found")// Simple prompt
name := cli.Prompt("Enter your name")
// Confirmation
ok := cli.Confirm("Are you sure?")
// Selection
choice := cli.Select("Choose an option", []string{"Option 1", "Option 2"})// Create a frame with HLCRF layout
frame := cli.NewFrame()
frame.Header().Write("My Application")
frame.Content().Write("Main content here")
frame.Footer().Write("Press q to quit")
frame.Render()- Read the RFC:
plans/code/core/cli/RFC.md - Check migration guide:
RFC.core-go-migration.md(plans/code/core/cli/RFC.core-go-migration.md) - Explore code:
ls core/cli/
- Clone the repo:
git clone github.com/dappcore/cli - Add to your app: Import
dappco.re/go/cli - Create commands: Use
corecli.Command()wrapper - Semantic output: Always use
core.Result
- Command-line tools — CLI applications
- Multi-repo dispatch — Commands that span multiple repositories
- Semantic output — Structured, machine-readable output
- Internationalised CLIs — Multi-language support
- TUI applications — Terminal-based user interfaces
- Provider routing — Commands that need to route to different providers
- GUI applications — Use CoreGUI for desktop apps
- Web applications — Use CoreTS for frontend
- Simple scripts — Use plain Go for one-off scripts
- Zero external dependencies — CoreCLI has no CLI framework dependencies
- Path-based routing — Command paths derive from action names (
git.log→core git log) - Universal types — Commands use
core.Optionsfor input andcore.Resultfor output - Generated help — Help text is generated from action names via go-i18n
- One capability map — CLI, REST API, and MCP server all project from the same action registry
- Explicit registration — Commands are registered explicitly, not via
init() - Semantic output — Use
cli.Success,cli.Error, etc. for consistent output - Internationalised — All user-facing text should use
cli.T() - Test with Taskfiles — CLI tests build the binary and test the compiled artifact
- Follow Good/Bad/Ugly — Package tests follow the triplet pattern
- CoreCLI Migration RFC (
plans/code/core/cli/RFC.core-go-migration.md) — Primary specification - Official site — Official documentation
- go-i18n RFC (
plans/code/core/go-i18n/RFC.md) — Internationalisation details
- CoreGo — Core Go framework
- CoreGUI — GUI framework
- CoreTS — TypeScript framework
- CorePlay — Play framework
- CorePHP — PHP framework
This knowledge pack is maintained by Mistral Vibe. Updates triggered by:
- Changes to
plans/code/core/cli/ - Changes to
core/cli/repository - New CLI patterns
- Cobra updates
Knowledge Pack v1.0.0 Created: 2026-06-17T14:40:00Z Author: Mistral Vibe Source: Lethean CoreCLI Framework