Documentation
¶
Overview ¶
Package frictionax provides CLI friction detection, correction, and telemetry for any command-line tool.
It detects CLI usage errors (typos, unknown commands, unknown flags) and provides helpful corrections with optional auto-execution for high-confidence matches. Designed to work with any CLI framework via pluggable adapters.
Core Concepts ¶
- FrictionEvent: Captures a CLI usage failure for analytics
- Suggestion: Represents a correction suggestion with confidence score
- Handler: Processes CLI errors and generates suggestions
- Catalog: Stores learned command/token mappings for high-confidence corrections
Suggestion Chain Priority ¶
When handling a CLI error, suggestions are tried in this order:
- Full command remap from catalog (highest confidence)
- Token-level catalog lookup
- Levenshtein distance fallback (for typos)
Auto-Execute ¶
High-confidence catalog matches with AutoExecute=true can be automatically executed without user confirmation. This enables "desire path" support where common patterns are seamlessly corrected.
Actor Detection ¶
The system distinguishes between human and agent actors to:
- Format output appropriately (text vs JSON)
- Track analytics by actor type
- Adjust behavior based on actor patterns
Actor detection is pluggable via the ActorDetector interface. The default EnvActorDetector checks CI environment variables, but consumers can inject their own detection logic (e.g., checking for specific agent frameworks).
Redaction ¶
Input redaction is pluggable via the Redactor interface. Consumers provide their own redaction logic for secrets and sensitive data. A NoOpRedactor is included for cases where redaction is not needed.
Privacy Guarantees ¶
- Secrets are redacted via the pluggable Redactor interface
- File paths are bucketed to categories, not captured
- Error messages are truncated and sanitized
- No user identity or repository names captured
Auto-Execute Philosophy ¶
Not every correction is auto-executed. Only curated catalog entries with:
- auto_execute: true flag set
- Confidence >= 0.85 threshold
- Safe, non-destructive operations
Levenshtein suggestions are NEVER auto-executed (they're typo guesses, not expressions of intent).
Teaching Pattern ¶
When a command is corrected, the correction is emitted in stdout (not stderr) so agents see it in their context and learn for subsequent calls.
Desire Paths ¶
A "desire path" is a reasonable expectation that doesn't match current behavior. When many users/agents make the same "mistake," that's a signal the CLI should work that way. This package surfaces these patterns through analytics.
Created by SageOx (https://sageox.ai).
Index ¶
- type Actor
- type ActorDetector
- type BuildConfig
- type BuildResult
- type CLIAdapter
- type CatalogData
- type CommandMapping
- type FailureKind
- type FileSource
- type Friction
- type FrictionEvent
- type FrictionResponse
- type HTTPSource
- type Option
- func WithActorDetector(d ActorDetector) Option
- func WithAuth(fn func() string) Option
- func WithCachePath(path string) Option
- func WithCatalog(cliName string) Option
- func WithIsEnabled(fn func() bool) Option
- func WithLogger(l *slog.Logger) Option
- func WithRedactor(r Redactor) Option
- func WithRequestDecorator(fn func(*http.Request)) Option
- func WithTelemetry(endpoint, version string) Option
- type ParsedError
- type PatternDetail
- type PatternSource
- type PatternsResponse
- type Redactor
- type Result
- type SkippedPattern
- type Stats
- type SubmitRequest
- type Suggestion
- type SuggestionType
- type TokenMapping
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ActorDetector ¶
ActorDetector detects whether the current context is a human, AI agent, or CI.
type BuildConfig ¶
type BuildConfig struct {
MinHumanCount int
MinAgentCount int
MinTotalCount int
SkipKinds []string
DiffOnly bool
}
BuildConfig controls the catalog build process.
func DefaultBuildConfig ¶
func DefaultBuildConfig() BuildConfig
DefaultBuildConfig returns sensible defaults for catalog building.
type BuildResult ¶
type BuildResult struct {
Catalog CatalogData `json:"catalog"`
NewEntries []CommandMapping `json:"new_entries"`
Skipped []SkippedPattern `json:"skipped"`
}
BuildResult contains the output of a catalog build.
func Build ¶
func Build(patterns []PatternDetail, existing CatalogData, cfg BuildConfig) (*BuildResult, error)
Build creates catalog entries from pattern data, deduplicating against an existing catalog. It filters patterns by thresholds, skips configured kinds, and produces CommandMapping entries with empty Target fields (targets are determined by LLM reasoning in the skill layer).
type CLIAdapter ¶
type CLIAdapter interface {
// CommandNames returns all available command names.
CommandNames() []string
// FlagNames returns all available flag names for a command.
// If command is empty, returns global flags.
FlagNames(command string) []string
// ParseError extracts structured info from a CLI error.
// Returns nil if the error is not a parseable CLI error.
ParseError(err error) *ParsedError
}
CLIAdapter abstracts CLI framework details for error parsing. Implement this for your CLI framework (Cobra, urfave/cli, Kong, etc.).
type CatalogData ¶
type CatalogData struct {
Version string `json:"version"`
Commands []CommandMapping `json:"commands"`
Tokens []TokenMapping `json:"tokens"`
}
CatalogData contains all learned mappings for serialization. This is the wire format for catalog updates from the server.
type CommandMapping ¶
type CommandMapping struct {
Pattern string `json:"pattern"`
Target string `json:"target"`
HasRegex bool `json:"has_regex"`
AutoExecute bool `json:"auto_execute"`
Count int `json:"count"`
Confidence float64 `json:"confidence"`
Description string `json:"description"`
// contains filtered or unexported fields
}
CommandMapping represents a full command remap from learned patterns.
func (*CommandMapping) ApplyMapping ¶
func (m *CommandMapping) ApplyMapping(input string) (string, bool)
ApplyMapping applies the mapping to input, returning corrected command. For regex patterns, captures are substituted into target ($1, $2, etc). Returns the corrected command and true if matched, empty string and false otherwise.
type FailureKind ¶
type FailureKind string
FailureKind categorizes CLI usage failures for analytics and suggestion routing.
const ( // FailureUnknownCommand indicates an unknown command was entered. FailureUnknownCommand FailureKind = "unknown-command" // FailureUnknownFlag indicates an unknown flag was provided. FailureUnknownFlag FailureKind = "unknown-flag" // FailureMissingRequired indicates a required argument or flag is missing. FailureMissingRequired FailureKind = "missing-required" // FailureInvalidArg indicates an argument has an invalid value. FailureInvalidArg FailureKind = "invalid-arg" // FailureParseError indicates a general CLI parsing failure. FailureParseError FailureKind = "parse-error" )
type FileSource ¶
type FileSource struct {
// contains filtered or unexported fields
}
FileSource reads patterns from a JSON file or stdin.
func NewFileSource ¶
func NewFileSource(path string) *FileSource
NewFileSource creates a PatternSource that reads from a JSON file. Use "-" to read from stdin.
func (*FileSource) FetchPatterns ¶
func (s *FileSource) FetchPatterns(ctx context.Context, minCount int, limit int) ([]PatternDetail, error)
FetchPatterns reads patterns from the file, applying minCount and limit filters.
type Friction ¶
type Friction struct {
// contains filtered or unexported fields
}
Friction is the single entry point for CLI friction detection, correction, and telemetry. Create one with New() and configure via options.
Basic usage (suggestions only, no telemetry):
f := frictionax.New(adapter) result := f.Handle(args, err)
Full usage (suggestions + telemetry):
f := frictionax.New(adapter,
frictionax.WithCatalog("mycli"),
frictionax.WithTelemetry("https://api.example.com", "0.5.0"),
frictionax.WithAuth(func() string { return token }),
)
defer f.Close()
result := f.Handle(args, err)
func New ¶
func New(adapter CLIAdapter, opts ...Option) *Friction
New creates a Friction instance with the given adapter and options. The adapter is required and provides CLI framework integration.
Call Close() when done to flush any buffered telemetry events.
func (*Friction) Close ¶
func (f *Friction) Close()
Close stops background telemetry processing and flushes buffered events. Safe to call multiple times. No-op if telemetry is not configured.
func (*Friction) Handle ¶
Handle processes CLI args and error, returning a Result with suggestion and execution decision. Returns nil if the error cannot be parsed.
func (*Friction) Record ¶
func (f *Friction) Record(event FrictionEvent)
Record adds a friction event directly to the telemetry buffer. This is useful for recording events that aren't CLI parse errors. No-op if telemetry is not configured.
func (*Friction) Stats ¶
Stats returns current telemetry statistics. Returns zero-value Stats if telemetry is not configured.
func (*Friction) UpdateCatalog ¶
func (f *Friction) UpdateCatalog(data CatalogData) error
UpdateCatalog replaces the catalog data with the provided data. No-op if the catalog is not configured.
type FrictionEvent ¶
type FrictionEvent struct {
Timestamp string `json:"ts"`
Kind FailureKind `json:"kind"`
Command string `json:"command,omitempty"`
Subcommand string `json:"subcommand,omitempty"`
Actor string `json:"actor"`
AgentType string `json:"agent_type,omitempty"`
PathBucket string `json:"path_bucket"`
Input string `json:"input"`
ErrorMsg string `json:"error_msg"`
Suggestion string `json:"suggestion,omitempty"`
}
FrictionEvent captures a CLI usage failure for analytics. Events are privacy-preserving: inputs are redacted, errors are truncated.
Field limits:
- Input: max 500 characters
- ErrorMsg: max 200 characters
Use Truncate() to enforce these limits before submission.
func (*FrictionEvent) MarshalJSON ¶
func (f *FrictionEvent) MarshalJSON() ([]byte, error)
MarshalJSON returns JSON bytes ready for transmission.
func (*FrictionEvent) Truncate ¶
func (f *FrictionEvent) Truncate()
Truncate enforces field length limits on the event. Call this before submission to ensure compliance with API limits.
type FrictionResponse ¶
type FrictionResponse struct {
Accepted int `json:"accepted"`
Catalog *CatalogData `json:"catalog,omitempty"`
}
FrictionResponse represents the API response from friction event submission.
type HTTPSource ¶
type HTTPSource struct {
// contains filtered or unexported fields
}
HTTPSource fetches patterns from a frictionax-server HTTP endpoint.
func NewHTTPSource ¶
func NewHTTPSource(baseURL string) *HTTPSource
NewHTTPSource creates a PatternSource that fetches from the given frictionax-server URL. The server must expose GET /api/v1/friction/patterns.
func (*HTTPSource) FetchPatterns ¶
func (s *HTTPSource) FetchPatterns(ctx context.Context, minCount int, limit int) ([]PatternDetail, error)
FetchPatterns fetches patterns from the HTTP endpoint.
type Option ¶
type Option func(*frictionConfig)
Option configures the Friction instance.
func WithActorDetector ¶
func WithActorDetector(d ActorDetector) Option
WithActorDetector sets a custom actor detector. If not set, the default environment-based detector is used.
func WithAuth ¶
WithAuth sets the authentication function for telemetry requests. The function is called on each request and should return a bearer token.
func WithCachePath ¶
WithCachePath sets the file path for on-disk catalog caching. If not set, no catalog caching is performed.
func WithCatalog ¶
WithCatalog enables the learned-corrections catalog for the given CLI name. The catalog provides high-confidence corrections from server-side data.
func WithIsEnabled ¶
WithIsEnabled sets a function that controls whether telemetry is active. If the function returns false, events are silently dropped.
func WithLogger ¶
WithLogger sets a structured logger for debug output. If not set, slog.Default() is used.
func WithRedactor ¶
WithRedactor sets a custom redactor for input and error message sanitization. If not set, inputs are passed through unmodified.
func WithRequestDecorator ¶
WithRequestDecorator sets a function called on each outgoing HTTP request. Use this to add custom headers (e.g., User-Agent).
func WithTelemetry ¶
WithTelemetry enables background telemetry reporting. Events are buffered and sent to the endpoint periodically.
type ParsedError ¶
type ParsedError struct {
Kind FailureKind
BadToken string
Command string
Subcommand string
RawMessage string
}
ParsedError contains structured error information extracted from CLI parsing. CLIAdapter implementations parse raw errors into this structure.
type PatternDetail ¶
type PatternDetail struct {
Pattern string `json:"pattern"`
Kind string `json:"kind"`
ErrorMsg string `json:"error_msg,omitempty"`
TotalCount int64 `json:"total_count"`
HumanCount int64 `json:"human_count"`
AgentCount int64 `json:"agent_count"`
AgentTypes int64 `json:"agent_types"`
LatestVersion string `json:"latest_version,omitempty"`
FirstSeen string `json:"first_seen"`
LastSeen string `json:"last_seen"`
}
PatternDetail represents an aggregated friction pattern with actor breakdown. This is the wire format for pattern aggregation APIs.
type PatternSource ¶
type PatternSource interface {
FetchPatterns(ctx context.Context, minCount int, limit int) ([]PatternDetail, error)
}
PatternSource fetches aggregated friction patterns from a data source.
type PatternsResponse ¶
type PatternsResponse struct {
Patterns []PatternDetail `json:"patterns"`
Total int `json:"total"`
}
PatternsResponse wraps pattern details for API responses.
type Result ¶
type Result struct {
// Suggestion contains the correction suggestion (may be nil if no suggestion found).
Suggestion *Suggestion
// Event contains the friction event for analytics submission.
Event *FrictionEvent
// AutoExecute is true if the corrected command should be auto-executed.
// Only true for high-confidence catalog matches.
AutoExecute bool
// CorrectedArgs contains the args to re-execute with (if AutoExecute is true).
CorrectedArgs []string
}
Result contains the outcome of friction handling. It includes the suggestion, friction event for analytics, and execution decision.
func (*Result) Emit ¶
Emit outputs the correction/suggestion for the caller to learn from. For agents (jsonMode=true): writes structured JSON to stdout. For humans (jsonMode=false): writes human-friendly text to stderr.
func (*Result) EmitError ¶
EmitError outputs an error with a suggestion for agent learning. For suggest-only cases where the command is not auto-executed.
func (*Result) Format ¶
Format formats the result's suggestion for output. If jsonMode is true, returns a JSON object with type, suggestion, and confidence. Otherwise returns human-friendly text ("Did you mean this?\n <suggestion>"). Returns empty string if no suggestion is present.
func (*Result) WrapOutput ¶
WrapOutput wraps successful command output with correction metadata. This teaches agents what the correct command is for next time.
type SkippedPattern ¶
type SkippedPattern struct {
Pattern string `json:"pattern"`
Kind string `json:"kind"`
Reason string `json:"reason"`
}
SkippedPattern records why a pattern was not added to the catalog.
type Stats ¶
type Stats struct {
Enabled bool `json:"enabled"`
BufferCount int `json:"buffer_count"`
BufferSize int `json:"buffer_size"`
SampleRate float64 `json:"sample_rate"`
RetryAfter any `json:"retry_after"`
CatalogVersion string `json:"catalog_version,omitempty"`
}
Stats holds telemetry statistics for status display.
type SubmitRequest ¶
type SubmitRequest struct {
Version string `json:"v"`
Events []FrictionEvent `json:"events"`
}
SubmitRequest is the request body for friction event submission.
type Suggestion ¶
type Suggestion struct {
Type SuggestionType
Original string
Corrected string
Confidence float64
Description string
}
Suggestion represents a correction suggestion for a CLI error.
type SuggestionType ¶
type SuggestionType string
SuggestionType indicates the source/method used to generate a suggestion.
const ( // SuggestionCommandRemap indicates a full command remap from the catalog. SuggestionCommandRemap SuggestionType = "command-remap" // SuggestionTokenFix indicates a single token correction from the catalog. SuggestionTokenFix SuggestionType = "token-fix" // SuggestionLevenshtein indicates an edit-distance based guess. SuggestionLevenshtein SuggestionType = "levenshtein" )
type TokenMapping ¶
type TokenMapping struct {
Pattern string `json:"pattern"`
Target string `json:"target"`
Kind FailureKind `json:"kind"`
Count int `json:"count"`
Confidence float64 `json:"confidence"`
}
TokenMapping represents a single-token correction from learned patterns.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
adapters
|
|
|
cobra
Package cobra implements a frictionax.CLIAdapter for the spf13/cobra CLI framework.
|
Package cobra implements a frictionax.CLIAdapter for the spf13/cobra CLI framework. |
|
kong
Package kong implements a frictionax.CLIAdapter for the alecthomas/kong CLI framework.
|
Package kong implements a frictionax.CLIAdapter for the alecthomas/kong CLI framework. |
|
urfavecli
Package urfavecli implements a frictionax.CLIAdapter for the urfave/cli/v2 framework.
|
Package urfavecli implements a frictionax.CLIAdapter for the urfave/cli/v2 framework. |
|
cmd
|
|
|
frictionax
command
|
|
|
frictionax-server
command
|
|
|
internal
|
|
|
levenshtein
Package levenshtein provides edit distance calculation between strings.
|
Package levenshtein provides edit distance calculation between strings. |
|
ringbuffer
Package ringbuffer provides a generic thread-safe circular buffer with deduplication.
|
Package ringbuffer provides a generic thread-safe circular buffer with deduplication. |
|
throttle
Package throttle provides a flush rate limiter to prevent thundering herd.
|
Package throttle provides a flush rate limiter to prevent thundering herd. |
|
redactors
|
|
|
secrets
Package secrets implements a frictionax.Redactor with built-in secret detection patterns.
|
Package secrets implements a frictionax.Redactor with built-in secret detection patterns. |
