config

package
v1.14.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 10, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package config owns the initech.yaml schema. It reads, parses, validates, and exposes the Project type that all other packages consume.

Config discovery order: explicit --config flag, ./initech.yaml in the current directory, then walk upward to find initech.yaml (like .git discovery). The first match wins.

This package does not know about git, scaffold, or roles. It only knows how to turn a YAML file into a validated Go struct.

Index

Constants

View Source
const (
	// AgentTypeClaudeCode is the default agent type. Claude Code supports
	// bracketed paste, so it keeps the existing paste-based injection path.
	AgentTypeClaudeCode = "claude-code"
	// AgentTypeCodex uses typed injection and Enter submit by default.
	AgentTypeCodex = "codex"
	// AgentTypeOpenCode uses the same raw-input defaults and readiness handling
	// as Codex.
	AgentTypeOpenCode = "opencode"
	// AgentTypeGeneric is a non-Claude agent with conservative typed-input defaults.
	AgentTypeGeneric = "generic"
)
View Source
const DefaultMcpBind = "0.0.0.0"

DefaultMcpBind is the default bind address for the MCP server.

View Source
const DefaultPressureThreshold = 85

DefaultPressureThreshold is the RSS percentage above which agents may be auto-suspended. Used when PressureThreshold is zero (unset).

Variables

View Source
var Registry = []FieldMeta{

	{Key: "project", Type: "string", Description: "Project name used for session identification and socket paths"},
	{Key: "root", Type: "string", Description: "Absolute path to the project root directory"},
	{Key: "roles", Type: "[]string", Description: "Agent roles to create workspaces for", Restart: true},
	{Key: "claude_command", Type: "[]string", Default: `["claude"]`, Description: "Base command to launch Claude Code agents"},
	{Key: "claude_args", Type: "[]string", Description: "Default CLI arguments appended to every agent launch"},
	{Key: "peer_name", Type: "string", Description: "This instance's identity for cross-machine addressing (e.g., \"laptop\")"},
	{Key: "mode", Type: "string", Default: "tui", Description: "Run mode: empty string for TUI, \"headless\" for daemon"},
	{Key: "listen", Type: "string", Description: "TCP listen address for headless mode (e.g., \"0.0.0.0:7391\")", Restart: true},
	{Key: "token", Type: "string", Description: "Shared auth token for cross-machine coordination", Secret: true},

	{Key: "web_port", Type: "int", Default: "0 (disabled)", Description: "Web companion server port. 0 or omitted disables it", Restart: true},
	{Key: "webhook_url", Type: "string", Description: "HTTP endpoint for agent event webhook POSTs. Empty disables"},
	{Key: "announce_url", Type: "string", Description: "Agent Radio webhook URL for TTS announcements. Empty disables"},

	{Key: "mcp_port", Type: "int", Default: "9200", Description: "MCP server port. 0 disables", Restart: true},
	{Key: "mcp_token", Type: "string", Description: "Bearer token for MCP server auth. Auto-generated if empty", EnvVar: "INITECH_MCP_TOKEN", Secret: true},
	{Key: "mcp_bind", Type: "string", Default: "0.0.0.0", Description: "MCP server bind address"},

	{Key: "beads.enabled", Type: "bool", Default: "true", Description: "Enable beads issue tracker integration"},
	{Key: "beads.prefix", Type: "string", Description: "Bead ID prefix (e.g., \"ini\" produces ini-abc)"},

	{Key: "resource.auto_suspend", Type: "bool", Default: "false", Description: "Auto-suspend agents under memory pressure"},
	{Key: "resource.pressure_threshold", Type: "int", Default: "85", Description: "RSS percentage (0-100) that triggers auto-suspend"},

	{Key: "slack.app_token", Type: "string", Description: "Slack app-level token (xapp-...) for Socket Mode", EnvVar: "INITECH_SLACK_APP_TOKEN", Secret: true, Restart: true},
	{Key: "slack.bot_token", Type: "string", Description: "Slack bot token (xoxb-...) for Web API calls", EnvVar: "INITECH_SLACK_BOT_TOKEN", Secret: true, Restart: true},
	{Key: "slack.allowed_users", Type: "[]string", Description: "Slack user IDs allowed to dispatch commands. Empty allows all"},
	{Key: "slack.response_mode", Type: "string", Default: "thread", Description: "Reply mode: \"thread\" (default) or \"channel\""},
	{Key: "slack.thread_context", Type: "bool", Default: "true", Description: "Fetch thread history and prepend as context for dispatched messages"},

	{Key: "repos", Type: "[]object", Description: "Code repositories cloned as agent workspace submodules"},
	{Key: "repos[].url", Type: "string", Description: "Git clone URL for agent submodule"},
	{Key: "repos[].name", Type: "string", Description: "Local directory name for the repo submodule"},

	{Key: "remotes.<name>.addr", Type: "string", Description: "Host:port of the remote peer"},
	{Key: "remotes.<name>.token", Type: "string", Description: "Auth token for this remote (overrides project-level token)", Secret: true},

	{Key: "role_overrides.<role>.command", Type: "[]string", Description: "Override the agent launch command entirely"},
	{Key: "role_overrides.<role>.claude_args", Type: "[]string", Description: "Additional CLI arguments for this role's agent"},
	{Key: "role_overrides.<role>.agent_type", Type: "string", Default: "claude-code", Description: "Agent type: \"claude-code\", \"codex\", \"opencode\", or \"generic\""},
	{Key: "role_overrides.<role>.dir", Type: "string", Description: "Custom working directory for this role"},
	{Key: "role_overrides.<role>.auto_approve", Type: "bool", Description: "Auto-approve matching permission prompts for this role"},
	{Key: "role_overrides.<role>.submit_key", Type: "string", Default: "enter", Description: "Submit key: \"enter\" (default) or \"ctrl+enter\""},
	{Key: "role_overrides.<role>.no_bracketed_paste", Type: "bool", Default: "false", Description: "Use raw typed input instead of bracketed paste"},
	{Key: "role_overrides.<role>.tech_stack", Type: "string", Description: "Tech stack hint injected into the role template"},
	{Key: "role_overrides.<role>.build_cmd", Type: "string", Description: "Build command injected into the role template"},
	{Key: "role_overrides.<role>.test_cmd", Type: "string", Description: "Test command injected into the role template"},
	{Key: "role_overrides.<role>.repo_name", Type: "string", Description: "Repo submodule name when multiple repos are configured"},
}

Registry contains metadata for every config field in initech.yaml. Ordering determines list output order. Template keys use angle-bracket placeholders for map-typed fields (e.g., remotes.<name>.addr).

Functions

func DefaultAutoApprove added in v0.25.23

func DefaultAutoApprove(agentType string) bool

DefaultAutoApprove returns the agent-type default for permission prompt auto-approval. Codex and OpenCode default on; all other agent types default off.

func DefaultNoBracketedPaste added in v0.25.21

func DefaultNoBracketedPaste(agentType string) bool

DefaultNoBracketedPaste returns the agent-type default for text injection. Only Claude Code keeps bracketed paste enabled by default.

func DefaultSubmitKey added in v0.25.21

func DefaultSubmitKey(agentType string) string

DefaultSubmitKey returns the submit key implied by the agent type.

func Discover

func Discover(dir string) (string, error)

Discover finds an initech.yaml file by walking upward from dir. Returns the absolute path to the config file, or an error if none is found.

func IsCodexLikeAgentType added in v0.25.22

func IsCodexLikeAgentType(agentType string) bool

IsCodexLikeAgentType reports whether agentType should use the Codex/OpenCode readiness and raw-send flow.

func IsSecret added in v1.12.0

func IsSecret(key string) bool

IsSecret returns true if the field should be masked in output.

func NormalizeAgentType added in v0.25.21

func NormalizeAgentType(agentType string) string

NormalizeAgentType returns the effective agent type, defaulting to claude-code when the config omits it.

func ValidAgentType added in v0.25.21

func ValidAgentType(agentType string) bool

ValidAgentType reports whether agentType is one of the supported config values.

func Validate

func Validate(p *Project) error

Validate checks that the project config is internally consistent. Returns nil if valid, or an error describing the first problem found.

func Write

func Write(path string, p *Project) error

Write serializes a Project to YAML and writes it to the given path.

Types

type BeadsConfig

type BeadsConfig struct {
	Enabled *bool  `yaml:"enabled,omitempty"` // nil = legacy (treat as enabled), false = disabled
	Prefix  string `yaml:"prefix,omitempty"`
}

BeadsConfig holds beads issue tracker settings.

func (BeadsConfig) IsEnabled added in v1.5.0

func (b BeadsConfig) IsEnabled() bool

IsEnabled returns whether beads integration is active. Nil (legacy configs without the field) is treated as enabled for backwards compatibility.

type FieldMeta added in v1.12.0

type FieldMeta struct {
	Key         string // Dot-notation path (e.g., "beads.prefix", "remotes.<name>.addr").
	Type        string // "string", "int", "bool", "[]string", "map".
	Default     string // Human-readable default value.
	Description string // One-line description for list/show output.
	EnvVar      string // Override env var name (e.g., "INITECH_MCP_TOKEN"). Empty if none.
	Secret      bool   // Mask value in show/get output unless --reveal.
	Restart     bool   // True if changing this field requires TUI restart.
}

FieldMeta describes a single config field for the config CLI subcommands. The Registry slice is the single source of truth for field names, types, defaults, and descriptions. All config CLI commands read from this registry rather than hardcoding field knowledge.

func AllFields added in v1.12.0

func AllFields() []FieldMeta

AllFields returns the full registry. Callers should not modify the slice.

func LookupField added in v1.12.0

func LookupField(key string) (FieldMeta, bool)

LookupField finds metadata by key. Exact matches are tried first, then template patterns where angle-bracket segments (<name>, <role>) match any value. Returns the metadata and true if found, or zero value and false.

type Project

type Project struct {
	Name          string                  `yaml:"project"`
	Root          string                  `yaml:"root"`
	Repos         []Repo                  `yaml:"repos,omitempty"`
	Beads         BeadsConfig             `yaml:"beads,omitempty"`
	Resource      ResourceConfig          `yaml:"resource,omitempty"`
	Roles         []string                `yaml:"roles"`
	ClaudeCommand []string                `yaml:"claude_command,omitempty"`
	ClaudeArgs    []string                `yaml:"claude_args,omitempty"`
	RoleOverrides map[string]RoleOverride `yaml:"role_overrides,omitempty"`

	// Web companion server fields.
	WebPort     *int   `yaml:"web_port,omitempty"`     // Web companion port. nil/0 = disabled, >0 = enabled.
	WebhookURL  string `yaml:"webhook_url,omitempty"`  // HTTP endpoint for agent event POSTs. Empty = disabled.
	AnnounceURL string `yaml:"announce_url,omitempty"` // Agent Radio webhook for TTS announcements. Empty = disabled.

	// MCP server fields.
	McpPort  *int   `yaml:"mcp_port,omitempty"`  // MCP server port. Default 9200, nil uses default, 0 disables.
	McpToken string `yaml:"mcp_token,omitempty"` // Bearer token. Auto-generated if empty. INITECH_MCP_TOKEN env var overrides.
	McpBind  string `yaml:"mcp_bind,omitempty"`  // Bind address. Default "0.0.0.0".

	// Slack chat integration fields.
	Slack SlackConfig `yaml:"slack,omitempty"`

	// Cross-machine coordination fields.
	PeerName string            `yaml:"peer_name,omitempty"` // This instance's identity (e.g., "workbench").
	Mode     string            `yaml:"mode,omitempty"`      // "" (default TUI) or "headless" (daemon).
	Listen   string            `yaml:"listen,omitempty"`    // TCP listen addr for headless mode. Defaults to 127.0.0.1 if only port given (e.g., ":7391" becomes "127.0.0.1:7391"). Use "0.0.0.0:port" to bind all interfaces.
	Token    string            `yaml:"token,omitempty"`     // Shared auth token.
	Remotes  map[string]Remote `yaml:"remotes,omitempty"`   // Named remote peers.
}

Project is the top-level config read from initech.yaml.

func Load

func Load(path string) (*Project, error)

Load reads, parses, and validates an initech.yaml file from the given path. It expands ~ in the root field to the user's home directory. If the config contains auth tokens and the file is group/world readable, a warning is printed to stderr.

func (*Project) EffectiveMcpBind added in v1.1.0

func (p *Project) EffectiveMcpBind() string

EffectiveMcpBind returns the MCP bind address, defaulting to "0.0.0.0".

func (*Project) EffectiveMcpPort added in v1.1.0

func (p *Project) EffectiveMcpPort() int

EffectiveMcpPort returns the MCP server port from config. Returns 0 (disabled) when mcp_port is not set, or the explicit value when set.

func (*Project) EffectiveMcpToken added in v1.1.0

func (p *Project) EffectiveMcpToken() string

EffectiveMcpToken returns the MCP bearer token, checking the INITECH_MCP_TOKEN environment variable first, then the config value. Returns empty string if neither is set (caller should auto-generate).

func (*Project) EffectiveSlackAppToken added in v1.10.1

func (p *Project) EffectiveSlackAppToken() string

EffectiveSlackAppToken returns the app token, preferring the env var.

func (*Project) EffectiveSlackBotToken added in v1.10.1

func (p *Project) EffectiveSlackBotToken() string

EffectiveSlackBotToken returns the bot token, preferring the env var.

func (*Project) EffectiveWebPort added in v1.5.10

func (p *Project) EffectiveWebPort() int

EffectiveWebPort returns the web companion port from config. Returns 0 (disabled) when web_port is not set, or the explicit value when set.

type Remote added in v0.23.17

type Remote struct {
	Addr  string `yaml:"addr"`            // host:port of the remote peer.
	Token string `yaml:"token,omitempty"` // Auth token for this remote (overrides project-level token).
}

Remote describes a remote initech peer for cross-machine coordination.

type Repo

type Repo struct {
	URL  string `yaml:"url"`
	Name string `yaml:"name"`
}

Repo is a code repository that agents get as a git submodule.

type ResourceConfig

type ResourceConfig struct {
	AutoSuspend       bool `yaml:"auto_suspend,omitempty"`
	PressureThreshold int  `yaml:"pressure_threshold,omitempty"` // RSS percentage (0-100). Default: 85.
}

ResourceConfig holds resource management settings. When AutoSuspend is true, the TUI runs a memory monitor and can auto-suspend/resume agents under memory pressure. When absent or false, all resource management is dormant.

type RoleOverride

type RoleOverride struct {
	TechStack        string   `yaml:"tech_stack,omitempty"`
	BuildCmd         string   `yaml:"build_cmd,omitempty"`
	TestCmd          string   `yaml:"test_cmd,omitempty"`
	Dir              string   `yaml:"dir,omitempty"`
	RepoName         string   `yaml:"repo_name,omitempty"`
	AgentType        string   `yaml:"agent_type,omitempty"` // "claude-code" (default), "codex", "opencode", or "generic".
	Command          []string `yaml:"command,omitempty"`    // Override the agent command entirely (e.g. ["codex"]).
	ClaudeArgs       []string `yaml:"claude_args,omitempty"`
	AutoApprove      *bool    `yaml:"auto_approve,omitempty"`       // When true, auto-approve matching permission prompts.
	NoBracketedPaste bool     `yaml:"no_bracketed_paste,omitempty"` // When true, use the non-bracketed injection path.
	SubmitKey        string   `yaml:"submit_key,omitempty"`         // "enter" (default) or "ctrl+enter".
}

RoleOverride lets a project customize per-role settings beyond catalog defaults.

type SlackConfig added in v1.10.1

type SlackConfig struct {
	AppToken      string   `yaml:"app_token,omitempty"`      // xapp-... App-level token for Socket Mode.
	BotToken      string   `yaml:"bot_token,omitempty"`      // xoxb-... Bot token for Web API calls.
	AllowedUsers  []string `yaml:"allowed_users,omitempty"`  // Slack user IDs allowed to dispatch. Empty = all.
	ResponseMode  string   `yaml:"response_mode,omitempty"`  // "thread" (default) or "channel".
	ThreadContext *bool    `yaml:"thread_context,omitempty"` // Fetch thread history for dispatch context. nil/true = enabled.
}

SlackConfig holds Slack chat integration settings. When both tokens are set, initech connects via Socket Mode to receive @mention events and dispatch them to agents. Env vars INITECH_SLACK_APP_TOKEN and INITECH_SLACK_BOT_TOKEN override the config file values.

func (*SlackConfig) IsThreadContextEnabled added in v1.10.3

func (s *SlackConfig) IsThreadContextEnabled() bool

IsThreadContextEnabled returns true if thread context fetching is enabled. Defaults to true when not explicitly set.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL