Documentation
¶
Overview ¶
ABOUTME: Manages the /retro bundled skill — install and uninstall. ABOUTME: The skill file lives at <provider>/skills/retro/SKILL.md and enables the /retro slash command.
Index ¶
- Constants
- Variables
- func AtomicUpdateSettings(updateFn func(*ClaudeSettings) error) error
- func AtomicUpdateSettingsAt(settingsPath string, updateFn func(*ClaudeSettings) error) error
- func BundledSkillNames() []string
- func EnsureDefaultRedaction() (bool, error)
- func GetBinaryPath() (string, error)
- func GetClaudeStateDir() (string, error)
- func GetSettingsPath() (string, error)
- func HasBindings(provider string) (bool, error)
- func InstallBundledSkill(stateDir, providerName, name string) error
- func InstallRetroSkill() error
- func IsBundledSkillInstalled(stateDir, name string) bool
- func IsLinkFromGitHubDisabled() bool
- func IsRetroSkillInstalled() bool
- func ParseLogLevel(level string) (logger.Level, error)
- func ReconcileBundledSkills(stateDir, providerName string) error
- func SaveUploadConfig(config *UploadConfig) error
- func SetBindingCredentials(b Binding, backendURL, apiKey string) error
- func SkillPath(stateDir, name string) string
- func UninstallBundledSkill(stateDir, name string) error
- func UninstallBundledSkills(stateDir string) error
- func UninstallRetroSkill() error
- type Binding
- type BindingCreds
- type ClaudeSettings
- type RedactionConfig
- type RedactionPattern
- type UploadConfig
Constants ¶
const ( SkillProviderClaude = "claude-code" SkillProviderCodex = "codex" SkillProviderOpencode = "opencode" SkillProviderCursor = "cursor" )
const ( ToolNameBash = "Bash" ToolNameMCPGitHubCreatePR = "mcp__github__create_pull_request" // ToolNameCursorShell is Cursor's shell tool name (its equivalent of // Bash); both `git commit` and `gh pr create` run through it. ToolNameCursorShell = "Shell" )
Tool names for PreToolUse/PostToolUse hook matching.
const ClaudeStateDirEnv = "CONFAB_CLAUDE_DIR"
ClaudeStateDirEnv is the environment variable to override the default Claude state directory. Mirrored from pkg/provider; the two must match.
const DisableLinkFromGitHubEnv = "CONFAB_DISABLE_LINK_FROM_GITHUB"
DisableLinkFromGitHubEnv is the environment variable to disable GitHub linking. When set to any non-empty value, GitHub linking (commits and PRs) is disabled.
Variables ¶
var ErrHooksTypeMismatch = errors.New("settings.json: 'hooks' field exists but is not a JSON object — please fix manually")
ErrHooksTypeMismatch is returned when the "hooks" field in settings.json exists but is not a JSON object. This prevents silently overwriting user config.
var ErrNoBinding = errors.New("no confab binding for the requested provider/config dir")
ErrNoBinding is returned by GetUploadConfigFor when a non-default binding has no stored credentials. Callers MUST NOT fall back to the default (top-level) config — doing so would silently sync a custom-dir session to the wrong backend (leak-free policy).
Functions ¶
func AtomicUpdateSettings ¶
func AtomicUpdateSettings(updateFn func(*ClaudeSettings) error) error
AtomicUpdateSettings performs a read-modify-write with optimistic locking. It retries up to maxRetries times if the file is modified by another process. The updateFn receives the current settings and should modify them in-place.
Race condition limitation: The mtime check and rename are not truly atomic. There's a small window (<1ms) between os.Stat() and os.Rename() where another process could modify the file. The retry mechanism mitigates but does not eliminate this race. For most use cases (CLI hook installation, infrequent config changes), the retry logic provides sufficient reliability. If truly atomic updates are required, file locking (flock) would be needed.
func AtomicUpdateSettingsAt ¶ added in v0.17.1
func AtomicUpdateSettingsAt(settingsPath string, updateFn func(*ClaudeSettings) error) error
AtomicUpdateSettingsAt is AtomicUpdateSettings against an explicit settingsPath — used to install/uninstall hooks in a non-default config dir (kata hpec). AtomicUpdateSettings is the default-path wrapper.
func BundledSkillNames ¶ added in v0.16.0
func BundledSkillNames() []string
BundledSkillNames returns the shipped skill names in install order.
func EnsureDefaultRedaction ¶
EnsureDefaultRedaction ensures the config has a redaction section with defaults. If redaction config already exists (even if disabled), it's left unchanged. Returns true if defaults were added, false if config already had redaction settings.
func GetBinaryPath ¶
GetBinaryPath returns the absolute path to the confab binary
func GetClaudeStateDir ¶
GetClaudeStateDir returns the Claude state directory path. Defaults to ~/.claude but can be overridden with CONFAB_CLAUDE_DIR.
func GetSettingsPath ¶
GetSettingsPath returns the path to the Claude settings file (defaults to ~/.claude/settings.json, can be overridden with CONFAB_CLAUDE_DIR).
func HasBindings ¶ added in v0.17.1
HasBindings reports whether any non-default bindings exist for the provider. Hook handlers use this as the no-bindings short-circuit: pure single-dir users (no bindings) skip derivation entirely and take the default path.
func InstallBundledSkill ¶ added in v0.16.0
InstallBundledSkill writes one shipped skill to stateDir, backing up a customized existing SKILL.md beside the file before overwriting it. If the backup write fails, the install aborts rather than overwriting user content.
func InstallRetroSkill ¶ added in v0.15.0
func InstallRetroSkill() error
InstallRetroSkill writes the /retro skill file to ~/.claude/skills/retro/SKILL.md. If an existing file differs from the template, it is backed up as SKILL.md.bak.
func IsBundledSkillInstalled ¶ added in v0.16.0
func IsLinkFromGitHubDisabled ¶
func IsLinkFromGitHubDisabled() bool
IsLinkFromGitHubDisabled returns true if GitHub linking is disabled via environment variable.
func IsRetroSkillInstalled ¶ added in v0.15.0
func IsRetroSkillInstalled() bool
IsRetroSkillInstalled returns true if the /retro skill file exists.
func ParseLogLevel ¶
ParseLogLevel parses a log level string and returns the corresponding logger.Level. Empty string defaults to INFO. Unknown values return INFO plus an error.
func ReconcileBundledSkills ¶ added in v0.16.2
ReconcileBundledSkills installs every shipped skill into stateDir and removes any retired skills left over from previous confab versions. It is idempotent: pruning a retired skill that is already absent is a no-op.
func SaveUploadConfig ¶
func SaveUploadConfig(config *UploadConfig) error
SaveUploadConfig writes upload configuration to ~/.confab/config.json
func SetBindingCredentials ¶ added in v0.17.1
SetBindingCredentials writes backendURL/apiKey to the binding's slot: the top-level fields for the default binding, or Bindings[provider][dir] otherwise. Global fields are preserved.
func UninstallBundledSkill ¶ added in v0.16.0
func UninstallBundledSkills ¶ added in v0.16.0
UninstallBundledSkills removes every shipped skill directory from stateDir.
func UninstallRetroSkill ¶ added in v0.15.0
func UninstallRetroSkill() error
UninstallRetroSkill removes the /retro skill directory (~/.claude/skills/retro/).
Types ¶
type Binding ¶ added in v0.17.1
type Binding struct {
Provider string
Dir string // canonical config dir; empty for the default binding
IsDefault bool
}
Binding identifies a (provider, config dir) backend target. The default binding (IsDefault) maps to the top-level config fields for backward compatibility; any other binding maps to Bindings[Provider][Dir].
func ResolveBinding ¶ added in v0.17.1
ResolveBinding builds the Binding for (provider, dir), treating dir as the default when it is empty or canonically equal to defaultDir. defaultDir is passed in (rather than resolved here) because pkg/config sits below pkg/provider and must not import it.
type BindingCreds ¶ added in v0.17.1
BindingCreds holds the backend credentials for one (provider, config dir). Only the credentials vary per binding; redaction/log-level/auto-update are read from the global top-level config.
type ClaudeSettings ¶
type ClaudeSettings struct {
// contains filtered or unexported fields
}
ClaudeSettings wraps the raw settings map to preserve all fields. This is similar to Python's json.load/json.dump pattern. We intentionally avoid typed structs for hooks since the schema is controlled by Claude Code and evolves rapidly.
func NewClaudeSettings ¶ added in v0.16.0
func NewClaudeSettings() *ClaudeSettings
NewClaudeSettings returns an empty ClaudeSettings. Useful for tests and for callers that want to build a settings object before writing.
func ReadSettings ¶
func ReadSettings() (*ClaudeSettings, error)
ReadSettings reads the default Claude settings file, preserving all fields.
func ReadSettingsAt ¶ added in v0.17.1
func ReadSettingsAt(settingsPath string) (*ClaudeSettings, error)
ReadSettingsAt reads the Claude settings file at settingsPath, preserving all fields. This is the explicit-path core used to install/inspect hooks in a non-default config dir (kata hpec); ReadSettings is the default-path wrapper.
func (*ClaudeSettings) GetEventHooks ¶ added in v0.16.0
func (s *ClaudeSettings) GetEventHooks(eventName string) []any
GetEventHooks returns the array of matchers for an event, as []any. This is a read-only operation that does not create the hooks map if it doesn't exist.
func (*ClaudeSettings) GetHooksMap ¶ added in v0.16.0
func (s *ClaudeSettings) GetHooksMap() (map[string]any, error)
GetHooksMap returns the hooks map, creating it if it doesn't exist. Returns an error if the hooks field exists but has the wrong type, to prevent silently overwriting user configuration.
func (*ClaudeSettings) MarshalJSON ¶ added in v0.16.0
func (s *ClaudeSettings) MarshalJSON() ([]byte, error)
MarshalJSON implements json.Marshaler so callers can inspect the serialized shape directly (used by tests).
func (*ClaudeSettings) SetEventHooks ¶ added in v0.16.0
func (s *ClaudeSettings) SetEventHooks(eventName string, matchers []any) error
SetEventHooks sets the array of matchers for an event. If matchers is nil or empty, the event key is removed. If the hooks map becomes empty, it is removed from settings.
type RedactionConfig ¶
type RedactionConfig struct {
Enabled bool `json:"enabled"`
UseDefaultPatterns *bool `json:"use_default_patterns,omitempty"` // defaults to true if nil
Patterns []RedactionPattern `json:"patterns,omitempty"`
}
RedactionConfig holds redaction settings
func (*RedactionConfig) ShouldUseDefaultPatterns ¶
func (c *RedactionConfig) ShouldUseDefaultPatterns() bool
ShouldUseDefaultPatterns returns true if default patterns should be used. Defaults to true if UseDefaultPatterns is nil.
type RedactionPattern ¶
type RedactionPattern struct {
Name string `json:"name"`
Pattern string `json:"pattern,omitempty"`
Type string `json:"type"`
CaptureGroup int `json:"capture_group,omitempty"`
FieldPattern string `json:"field_pattern,omitempty"`
}
RedactionPattern represents a single redaction pattern
func GetDefaultRedactionPatterns ¶
func GetDefaultRedactionPatterns() []RedactionPattern
GetDefaultRedactionPatterns returns the default high-precision redaction patterns
type UploadConfig ¶
type UploadConfig struct {
BackendURL string `json:"backend_url"`
APIKey string `json:"api_key"`
LogLevel string `json:"log_level,omitempty"` // debug, info, warn, error (default: info)
AutoUpdate *bool `json:"auto_update,omitempty"` // nil = enabled (default), false = disabled
Redaction *RedactionConfig `json:"redaction,omitempty"`
// Bindings maps provider -> canonical config dir -> credentials.
Bindings map[string]map[string]BindingCreds `json:"bindings,omitempty"`
}
UploadConfig holds backend upload configuration.
The top-level BackendURL/APIKey are the DEFAULT binding (the provider's default config dir). Per-(provider, config dir) bindings live under Bindings (kata hpec); only backend_url/api_key vary per binding — Redaction, LogLevel and AutoUpdate stay global. Bindings is omitempty so a pure single-dir install's config.json is byte-identical to before this feature.
func EnsureAuthenticated ¶
func EnsureAuthenticated() (*UploadConfig, error)
EnsureAuthenticated reads the config and verifies it has valid credentials Returns the config if authenticated, or an error if not configured
func EnsureAuthenticatedFor ¶ added in v0.17.1
func EnsureAuthenticatedFor(b Binding) (*UploadConfig, error)
EnsureAuthenticatedFor is GetUploadConfigFor plus a credential check, mirroring EnsureAuthenticated for a specific binding.
func GetUploadConfig ¶
func GetUploadConfig() (*UploadConfig, error)
GetUploadConfig reads upload configuration from ~/.confab/config.json.
This returns the DEFAULT/global config (top-level backend_url + api_key). For anything scoped to a specific session or provider config dir, use GetUploadConfigFor(provider.BindingFor(p, configDir)) instead — calling this directly for a custom-config-dir session silently yields the wrong backend (kata hpec).
func GetUploadConfigFor ¶ added in v0.17.1
func GetUploadConfigFor(b Binding) (*UploadConfig, error)
GetUploadConfigFor returns the effective UploadConfig for a binding: global fields (redaction, log level, auto-update) from the top-level config, with BackendURL/APIKey from the binding. For the default binding this is exactly GetUploadConfig(). For a non-default binding with no stored credentials it returns ErrNoBinding (callers must not fall back to the default).
func (*UploadConfig) IsAutoUpdateEnabled ¶ added in v0.10.2
func (c *UploadConfig) IsAutoUpdateEnabled() bool
IsAutoUpdateEnabled returns whether auto-update is enabled. Defaults to true when AutoUpdate is nil (not set in config).
func (*UploadConfig) Validate ¶
func (c *UploadConfig) Validate() error
Validate checks if the upload config is valid