Documentation
¶
Overview ¶
Package cli provides shared CLI infrastructure for writ and lore commands.
Index ¶
- Constants
- Variables
- func AddOutputFlags(cmd *cobra.Command, opts *SinkOptions)
- func AddSilentFlag(cmd *cobra.Command)
- func BashCompletionPath() string
- func BindFlags(cmd *cobra.Command, toolName string, useSharedConfig bool) error
- func BuildPipeline(opts SinkOptions, w io.Writer) (*result.Pipeline, error)
- func CacheHome() string
- func CollectFiles(base, dir string) []string
- func ConfigHome() string
- func CopyDir(src, dst string) error
- func DataHome() string
- func DevloreCacheHome() string
- func DevloreConfigHome() string
- func DevloreDataHome() string
- func DevloreStateHome() string
- func DisplayManPage(cmd *cobra.Command, header *doc.GenManHeader) error
- func Error(format string, args ...any)
- func ExitCode(err error) int
- func ExitWith(code int, err error) error
- func Failure(format string, args ...any) error
- func FishCompletionPath() string
- func GraphsDir() string
- func IndexPath() string
- func InitViper(cfg ViperConfig) error
- func LatestTracePath(graphChecksum string) string
- func LoadLatestTrace(graphChecksum string) (*op.Trace, error)
- func LoadTrace(path string) (*op.Trace, error)
- func ManPath() string
- func NewConfigCmd(info ConfigInfo) *cobra.Command
- func NewHelpCmd(rootCmd *cobra.Command, header ManHeader) *cobra.Command
- func NewManCmd(rootCmd *cobra.Command, header ManHeader) *cobra.Command
- func NewRootCmd(cfg RootConfig) *cobra.Command
- func NewSelfCmd(rootCmd *cobra.Command, info SelfInstallInfo) *cobra.Command
- func NewVersionCmd(info VersionInfo) *cobra.Command
- func Note(format string, args ...any)
- func Print(format string, args ...any)
- func SetUI(n *status.Narrator)
- func SharedConfigPath() string
- func StateHome() string
- func Success(format string, args ...any)
- func TracesDir() string
- func UI() *status.Narrator
- func Warn(format string, args ...any)
- func WritLayersDir() string
- func WritReposDir() string
- func WriteGraph(graph *op.Graph) (string, error)
- func WriteTrace(trace *op.Trace) (string, error)
- func ZshCompletionPath() string
- type ConfigInfo
- type IndexEntry
- type ManHeader
- type RootConfig
- type SelfInstallInfo
- type SinkOptions
- type VersionInfo
- type ViperConfig
Constants ¶
const ( IndexEventGraph = "graph" IndexEventTrace = "trace" )
IndexEventGraph marks an IndexEntry recording a graph write; IndexEventTrace marks one recording a trace write.
const ( ExitOK = 0 // Success ExitError = 1 // Generic error ExitUsage = 64 // Bad CLI syntax ExitDataErr = 65 // Invalid manifest/config ExitNoInput = 66 // File not found ExitSoftware = 70 // Internal error (bug) ExitCantCreate = 73 // Can't create file/symlink ExitIOErr = 74 // Read/write failure ExitNoPerm = 77 // Permission denied )
Exit codes follow BSD sysexits.h conventions for portable process status.
Variables ¶
var ErrManNotAvailable = errors.New("man command not available")
ErrManNotAvailable indicates the man command is not available on this system.
Functions ¶
func AddOutputFlags ¶
func AddOutputFlags(cmd *cobra.Command, opts *SinkOptions)
AddOutputFlags binds --format, --template, --filter, and --jq to opts. Call once during command setup, then call BuildPipeline from the cobra RunE to compose the result.Pipeline.
func AddSilentFlag ¶
AddSilentFlag adds the --silent flag to a root command. The flag value is read by bootstrap (cobra PersistentPreRun) which forks construction of the narrator: silent → sink.Discard, otherwise → sink.Stderr.
func BashCompletionPath ¶
func BashCompletionPath() string
BashCompletionPath returns the bash completion directory. XDG_DATA_HOME/bash-completion/completions
func BindFlags ¶
BindFlags binds all persistent flags from a command to Viper. Do this after defining flags and before Execute().
Flags are bound with the tool's section prefix when using shared config:
- --repo flag → viper key "writ.repo" (with UseSharedConfig)
- --repo flag → viper key "repo" (without UseSharedConfig)
func BuildPipeline ¶
BuildPipeline composes a result.Pipeline from the populated SinkOptions writing through w. Filters compose in --filter-then--jq order; the formatter is selected by result.FormatterByName. The writer is wrapped in a sink.Sink via sink.New internally.
Returns an error when the formatter name is unknown, the template body fails to parse, the field expressions fail to parse, or the jq expression fails to compile.
func CollectFiles ¶
CollectFiles returns all file paths under dir, relative to base.
func DevloreCacheHome ¶
func DevloreCacheHome() string
DevloreCacheHome returns the unified devlore cache directory. XDG_CACHE_HOME/devlore
func DevloreConfigHome ¶
func DevloreConfigHome() string
DevloreConfigHome returns the unified devlore config directory. XDG_CONFIG_HOME/devlore
func DevloreDataHome ¶
func DevloreDataHome() string
DevloreDataHome returns the unified devlore data directory. XDG_DATA_HOME/devlore
func DevloreStateHome ¶
func DevloreStateHome() string
DevloreStateHome returns the unified devlore state directory. XDG_STATE_HOME/devlore
func DisplayManPage ¶
func DisplayManPage(cmd *cobra.Command, header *doc.GenManHeader) error
DisplayManPage generates a man page and displays it with the system pager. Returns ErrManNotAvailable if man is not available on this system.
func Error ¶
Error prints an error message via the installed narrator. Unlike Failure, this does not return an error — use for non-fatal errors.
func ExitCode ¶
ExitCode extracts the exit code from an error. Returns the wrapped code if present, or ExitError (1) for plain errors.
func Failure ¶
Failure prints an error message via the installed narrator and returns the wrapped error. Use when the operation cannot continue.
func FishCompletionPath ¶
func FishCompletionPath() string
FishCompletionPath returns the fish completion directory. XDG_CONFIG_HOME/fish/completions
func GraphsDir ¶
func GraphsDir() string
GraphsDir returns the directory holding persisted graphs.
Returns:
- `string`: the absolute graphs directory under the devlore state home.
func IndexPath ¶
func IndexPath() string
IndexPath returns the run index's path at the store root.
Returns:
- `string`: the absolute path of `index.ndjson` under the devlore state home.
func InitViper ¶
func InitViper(cfg ViperConfig) error
InitViper initializes Viper with standard devlore conventions. Do this in PersistentPreRunE of the root command.
Precedence (lowest to highest):
- Config file defaults
- Config file values
- Environment variables (TOOL_KEY_NAME)
- Command-line flags
Environment variable mapping:
- WRIT_REPO → writ.repo (with UseSharedConfig)
- WRIT_VARS_USER_NAME → writ.vars.user_name
- Dots become underscores, keys are case-insensitive
func LatestTracePath ¶
LatestTracePath returns the path to the `latest.yaml` symlink for the graph identified by `graphChecksum`.
Parameters:
- `graphChecksum`: the graph's checksum (== op.Trace.GraphChecksum).
Returns:
- `string`: the absolute path to the graph's latest-trace symlink (which may not exist yet).
func LoadLatestTrace ¶
LoadLatestTrace loads the most recent trace for the graph identified by `graphChecksum`.
Parameters:
- `graphChecksum`: the graph's checksum (== op.Trace.GraphChecksum).
Returns:
- *op.Trace: the most recent trace for that graph.
- `error`: non-nil if no trace exists for the graph or it cannot be read.
func LoadTrace ¶
LoadTrace loads a single trace from `path`, verifying its tier-1 checksum.
Every trace read funnels through here into op.LoadTrace — the checksum trust boundary. A trace with a missing or mismatched checksum is refused (docs/architecture/5-graph-trace-integrity.md).
Parameters:
- `path`: the trace file to read.
Returns:
- *op.Trace: the deserialized, integrity-verified trace.
- `error`: non-nil if the file cannot be read, decoded, or verified.
func ManPath ¶
func ManPath() string
ManPath returns the user man page directory: XDG_DATA_HOME/man/man1
func NewConfigCmd ¶
func NewConfigCmd(info ConfigInfo) *cobra.Command
NewConfigCmd creates the config command with git-style subcommands.
Dot-paths match the config file structure exactly. No implicit prefixing. "writ.repos.0.path" in the CLI reads writ.repos[0].path in the file. "secrets.mode" reads secrets.mode. WYSIWYG.
Usage:
tool config get <key>... # Get values tool config set <key>=<value>... # Set values tool config unset <key>... # Remove keys tool config list # List all settings tool config edit # Open in $EDITOR tool config validate # Validate against schema tool config schema # Output JSON schema tool config path # Show config file location
func NewHelpCmd ¶
NewHelpCmd creates a help command that prefers man pages when available. This follows git's model: if man pages are installed, display them via pager; otherwise fall back to console text output.
func NewManCmd ¶
NewManCmd creates the man command for displaying/installing man pages. Usage:
tool man # display man page with pager tool man --install # install to ~/.local/share/man/man1/ tool man deploy # display man page for subcommand
func NewRootCmd ¶
func NewRootCmd(cfg RootConfig) *cobra.Command
NewRootCmd creates a root cobra command with all shared flags, metadata commands, and Viper configuration. The caller adds tool-specific flags and subcommands to the returned command.
Parameters:
- cfg: root command configuration (name, descriptions, version info)
Returns:
- *cobra.Command: configured root command with shared flags and metadata commands
func NewSelfCmd ¶
func NewSelfCmd(rootCmd *cobra.Command, info SelfInstallInfo) *cobra.Command
NewSelfCmd creates the "self" command group with install, upgrade, and uninstall subcommands.
func NewVersionCmd ¶
func NewVersionCmd(info VersionInfo) *cobra.Command
NewVersionCmd creates the version command.
func SetUI ¶
SetUI installs the package-global narrator used by the cli facade functions (Note, Warn, Error, Failure, Success, Print).
Subsequent calls replace the installed narrator.
func SharedConfigPath ¶
func SharedConfigPath() string
SharedConfigPath returns the path to the shared devlore config file.
func TracesDir ¶
func TracesDir() string
TracesDir returns the directory holding persisted execution traces.
Traces are grouped into a per-graph subdirectory keyed by graph checksum; see the package store overview.
Returns:
- `string`: the absolute traces directory under the devlore state home.
func WritLayersDir ¶
func WritLayersDir() string
WritLayersDir returns the writ layers directory. XDG_DATA_HOME/devlore/writ/layers
func WritReposDir ¶
func WritReposDir() string
WritReposDir returns the writ-owned repository home — the default clone destination for `writ repo add <layer> <repository-url>`. XDG_DATA_HOME/devlore/writ/repos
func WriteGraph ¶
WriteGraph persists `graph` under GraphsDir, keyed by its checksum, and returns the file path.
Idempotent: a graph with the same checksum is written once. Subsequent calls observe the existing file and return its path without rewriting — distinct runs of the same plan share one persisted graph. A first write also appends an IndexEventGraph line to the run index, carrying the origin's tool and scope so index readers can filter without opening the document.
Parameters:
- `graph`: the assembled, immutable graph to persist. Must not be nil.
Returns:
- `string`: the absolute path the graph is stored at.
- `error`: non-nil if the directory cannot be created or the graph or its index line cannot be written.
func WriteTrace ¶
WriteTrace persists `trace` under TracesDir in its graph's subdirectory, updates the per-graph `latest.yaml` symlink to point at it, and appends an IndexEventTrace line to the run index.
Each run writes a distinct timestamped file, so a graph accumulates many traces. The subdirectory is keyed by op.Trace.GraphChecksum; `latest.yaml` is the convenience entry point for drift detection, reconciliation, and pause/restart.
Parameters:
- `trace`: the captured executor trace to persist. Must not be nil and must carry a GraphChecksum.
Returns:
- `string`: the absolute path the trace is stored at.
- `error`: non-nil if the directory cannot be created or the trace/symlink cannot be written.
func ZshCompletionPath ¶
func ZshCompletionPath() string
ZshCompletionPath returns the zsh completion directory. XDG_DATA_HOME/zsh/site-functions
Types ¶
type ConfigInfo ¶
type ConfigInfo struct {
Name string // Tool name (e.g., "lore", "writ")
Schema []byte // Embedded JSON schema
DefaultConfig []byte // Default configuration content
}
ConfigInfo contains configuration metadata for a tool.
type IndexEntry ¶
type IndexEntry struct {
// At is the UTC moment the store write happened.
At time.Time `json:"at"`
// Event is [IndexEventGraph] or [IndexEventTrace].
Event string `json:"event"`
// Tool is the producing program's name from the graph's origin; graph events only.
Tool string `json:"tool,omitempty"`
// Scope is the planning scope from the graph's origin; graph events only.
Scope string `json:"scope,omitempty"`
// GraphChecksum is the graph's canonical "sha256:<hex>" identity — the join key between events.
GraphChecksum string `json:"graph_checksum"`
// TraceFile is the trace's filename within its per-graph traces subdirectory; trace events only.
TraceFile string `json:"trace_file,omitempty"`
}
IndexEntry is one line of the run index.
A graph event carries `Tool` and `Scope` (from the graph's origin) so readers can filter without opening the document; a trace event carries `TraceFile` and joins to its graph event through the shared `GraphChecksum`.
func ReadIndex ¶
func ReadIndex() ([]IndexEntry, error)
ReadIndex reads the run index, tolerating a torn final line.
Lines that fail to parse are skipped — a crash mid-append must not fail every later read. A missing index file is an error (callers distinguish it via os.IsNotExist): per the deploy-family design, `writ status` treats a missing index as a hard error rather than degrading silently.
Returns:
- `[]IndexEntry`: the parsed entries in append order.
- `error`: non-nil when the index cannot be opened, including when it does not exist.
type RootConfig ¶
type RootConfig struct {
Name string // Command name ("lore" or "writ")
Short string // One-line description
Long string // Multi-line description
DefaultConfig []byte // Schema default config (e.g., schema.LoreDefaultConfig)
Version string // Semantic version, set via ldflags
Commit string // Git commit hash, set via ldflags
BuildDate string // Build timestamp, set via ldflags
}
RootConfig configures a root CLI command for lore or writ.
type SelfInstallInfo ¶
type SelfInstallInfo struct {
Name string // Tool name (e.g., "lore", "writ", "star")
Version string // Semantic version (e.g., "0.4.0"), set via ldflags
ManHeader ManHeader // Man page header metadata
ConfigInfo *ConfigInfo // Config schema and defaults (nil to skip config init)
PostInstallHooks []func(string) []string // Hooks run after install; return installed file paths (relative to prefix)
PostUninstallHooks []func(string) error // Hooks run after uninstall
}
SelfInstallInfo contains metadata needed for self-installation.
type SinkOptions ¶
SinkOptions captures the populated values from AddOutputFlags. The struct is the input to BuildPipeline, which composes a result.Pipeline from the flag values.
type VersionInfo ¶
type VersionInfo struct {
Version string // Semantic version (e.g., "0.1.0")
Commit string // Git commit hash
BuildDate string // Build timestamp
}
VersionInfo contains version metadata set at build time.
type ViperConfig ¶
type ViperConfig struct {
// Name is the tool name (e.g., "lore", "writ")
Name string
// EnvPrefix is the environment variable prefix (e.g., "LORE", "WRIT")
// If empty, defaults to uppercase Name
EnvPrefix string
// ConfigName is the config file name without extension (default: "config")
ConfigName string
// ConfigType is the config file type (default: "yaml")
ConfigType string
// When true, config is read from the tool's section (e.g., config.writ.repo)
UseSharedConfig bool
}
ViperConfig holds configuration for Viper initialization.