Documentation
¶
Overview ¶
Package config resolves Coop settings from environment variables and an optional conf file, with XDG-based defaults. Every COOP_* setting follows the same precedence: environment variable, then conf file, then built-in default.
Index ¶
- Constants
- func EnsurePrivateDir(path string) error
- func RegisterAdapterConfig(name string)
- func RootDir() string
- func ShellSplit(s string) []string
- func WithLock(path string, fn func() error) error
- func WriteFileAtomic(path string, data []byte) error
- func WriteFileAtomicMode(path string, data []byte, perm os.FileMode) error
- type Config
- func (c *Config) ACPCarryBytes() int
- func (c *Config) ActiveEffort(agent string) string
- func (c *Config) ActiveModel(agent string) string
- func (c *Config) ActiveProfile(agent string) string
- func (c *Config) AgentDir(agent string) string
- func (c *Config) AgentEffortDefault(agent string) string
- func (c *Config) AgentModelDefault(agent string) string
- func (c *Config) AgentProfileDir(agent, name string) string
- func (c *Config) Clone() *Config
- func (c *Config) Cmd(env, def string) []string
- func (c *Config) DefaultProfileOf(agent string) string
- func (c *Config) DefaultsFile() string
- func (c *Config) EffortFor(agent string) string
- func (c *Config) EnvFile() string
- func (c *Config) Explicit(key string) bool
- func (c *Config) GlobalPresetsDir() string
- func (c *Config) Instructions() string
- func (c *Config) ModelFor(agent string) string
- func (c *Config) Profiles(agent string) []string
- func (c *Config) SetActiveEffort(agent, effort string)
- func (c *Config) SetActiveModel(agent, model string)
- func (c *Config) SetActiveProfile(agent, name string)
- func (c *Config) SetDefaultProfile(agent, name string) error
- func (c *Config) SetEgress(mode string)
- func (c *Config) SetRuntimeLimits(cpus, memory, pids string)
- func (c *Config) SetTargetEffort(agent, effort string)
- func (c *Config) SetTargetModel(agent, model string)
- type Failure
Constants ¶
const (
DefaultProfile = "default"
)
DefaultProfile is the credential profile used when none is selected; profilesSubdir is the folder under an agent dir that holds the named profiles.
Variables ¶
This section is empty.
Functions ¶
func EnsurePrivateDir ¶
EnsurePrivateDir creates or tightens one host-owned directory without following a final link. It deliberately does not walk descendants: a private ancestor protects provider-owned state without changing the provider's own file modes.
func RegisterAdapterConfig ¶
func RegisterAdapterConfig(name string)
RegisterAdapterConfig registers the two coop.conf keys owned by an agent adapter. The agent registry calls it from its existing single registration point, so adding an adapter does not require a second provider list in config.
func ShellSplit ¶
ShellSplit exposes shellSplit so other packages can split a committed command setting (e.g. the .agent/project.yaml gate:) into argv exactly as Load splits COOP_GATE — one splitter, one rule.
func WithLock ¶
WithLock runs fn while holding an exclusive advisory lock (flock) on a sibling <path>.lock, so a load→modify→write of path can't lose a concurrent process's update. Fails CLOSED: when the lock file can't be opened or flocked, fn does NOT run and the caller gets an error naming the lock — these files pick which credential an unattended run uses, so a silently lost update is worse than a refused command (on a healthy system flock on a local file effectively never fails, so this costs nothing in normal operation). Linux/darwin only — coop's only targets.
func WriteFileAtomic ¶
WriteFileAtomic writes data to path via a uniquely-named temp file in the same dir, fsyncs it, then renames it into place and fsyncs the parent dir. The rename is atomic (no truncated file on a crash) and a UNIQUE temp name means concurrent writers don't clobber a shared "<path>.tmp" mid-write; the two fsyncs mean a power loss leaves either the old contents or the new ones — never a live-but-empty file, which for a credential pointer reads back as "unset" and silently changes which account the next run picks.
Types ¶
type Config ¶
type Config struct {
BaseImage string // COOP_BASE_IMAGE — shared base image tag
Workdir string // COOP_WORKDIR — where the repo mounts in the box (empty = its real host path)
HomeInBox string // COOP_HOME_IN_BOX — the box user's home
Shell string // COOP_SHELL — `coop shell`'s shell
ConfigDir string // COOP_CONFIG_DIR — per-agent auth + settings folder
MCPFile string // COOP_MCP_FILE — the one MCP source of truth
MCPInBox string // where MCPFile mounts in the box (Claude's --mcp-config)
RuntimeName string // COOP_RUNTIME — "" means autodetect
RepoOverride string // COOP_REPO — overrides git-toplevel detection
ImageOverride string // COOP_IMAGE — overrides image selection
Homes bool // COOP_HOMES — mount the per-agent home dirs
Network bool // COOP_NETWORK — join the sibling-services network
AutoUp bool // COOP_AUTO_UP — auto-start sibling services (compose up) before a box when a compose file is present
Cache bool // COOP_CACHE — mount the shared dependency cache volume
Caffeinate bool // COOP_CAFFEINATE — hold a system sleep inhibitor (caffeinate on macOS) while a loop runs
NoUpdateCheck bool // COOP_NO_UPDATE_CHECK — opt out of the once-a-day update-available check
StreamTrace bool // COOP_STREAM_TRACE — persist raw and rendered output for streaming loop attempts
ACPWarm bool // COOP_ACP_WARM — keep alternate ACP providers warm (environment only)
// EvalDisableWebTools is internal trial state, also carried to a loop subprocess.
// It disables ordinary native search/fetch, not arbitrary authenticated requests.
EvalDisableWebTools bool
ServicesNet string // COOP_SERVICES_NET — override the services network name
ACPCarryTokens int // COOP_ACP_CARRY_TOKENS — per-session budget (≈tokens, ~4 bytes each) for the conversation carried across an ACP provider switch (default 200000)
TasksFiles []string // COOP_TASKS — explicit task queue(s) override; empty = derive from .agent/project.yaml (subprojects) else .agent/tasks
Gate []string // COOP_GATE — revalidation gate run in the box before a fork merge lands
ExtraRunArgs []string // COOP_RUN_ARGS — extra args passed to the container runtime
// Box resource/privilege caps (docker; skipped on Apple `container`).
Memory string // COOP_MEMORY — memory cap, e.g. "4g" (empty = unset)
CPUs string // COOP_CPUS — cpu cap, e.g. "2" (empty = unset)
Pids string // COOP_PIDS — pids-limit (fork-bomb cap), default 4096; "0"/"unlimited"/"" = off
NoNewPrivileges bool // COOP_NO_NEW_PRIVILEGES — pass --security-opt no-new-privileges (default on)
Egress string // COOP_EGRESS — open, filtered (host-qualified), or none
ConsultTimeout string // COOP_CONSULT_TIMEOUT — per-peer coop-consult timeout in seconds (empty/0 = unlimited)
// ProviderTimeouts is the INTERNAL provider-attempt watchdog override
// ("start=2s,idle=3s,tool=6s"), read only so deterministic fixture tests can shorten the
// fixed deadlines; it is deliberately not a documented user knob.
ProviderTimeouts string // COOP_PROVIDER_TIMEOUTS
Editor string // COOP_EDITOR — editor for `coop fork review --open` (else $VISUAL/$EDITOR or a detected GUI editor)
ReviewCmd string // COOP_REVIEW_CMD — full override for `coop fork review` (run via sh -c; gets $COOP_FORK_PATH/$COOP_FORK_NAME/$COOP_REVIEW_REF)
// BoxHome is ~/.config/coop: the home for conf, mcp.json, and agents/.
BoxHome string
// contains filtered or unexported fields
}
Config is the fully-resolved settings for one invocation. It is computed once in Load and passed down; process-only presentation settings are the narrow exception because the leaf ui package cannot import config.
func Load ¶
Load resolves the configuration from the environment and conf file. A genuinely absent default file is optional; an explicitly selected file or a present invalid file is an operator error.
func (*Config) ACPCarryBytes ¶
ACPCarryBytes is the per-session budget, in bytes, for the conversation carried across an ACP provider switch — COOP_ACP_CARRY_TOKENS at ~4 bytes per token, defaulting here too so a Config built directly (tests) doesn't silently zero the budget.
func (*Config) ActiveEffort ¶
ActiveEffort returns the run's EXPLICIT top-tier effort for agent ("" when none), so a caller that temporarily overrides it (the review pass) can snapshot and restore it.
func (*Config) ActiveModel ¶
ActiveModel returns the run's EXPLICIT top-tier model for agent ("" when none), so a caller that temporarily overrides it (the loop swapping in a step's loop.yaml model for the review pass) can snapshot and restore the prior value.
func (*Config) ActiveProfile ¶
ActiveProfile is the exported reader for activeProfile — the profile a run of agent resolves to right now. Used for display (the run/loop banner names which profile is in play).
func (*Config) AgentDir ¶
AgentDir is the host folder mounted at the box's ~/.<agent>: the active profile's credential + session dir (see AgentProfileDir). Defaults to the "default" profile.
func (*Config) AgentEffortDefault ¶
AgentEffortDefault is the agent-wide default reasoning effort — the effort part of COOP_<AGENT>_MODEL (its shape is model[/effort], e.g. "opus/high"), or "". One var carries both axes, so there is no separate COOP_<AGENT>_EFFORT.
func (*Config) AgentModelDefault ¶
AgentModelDefault is the agent-wide default model — the model part of COOP_<AGENT>_MODEL (model[/effort]), or "". Resolved late (not in Load) because config doesn't know the agent set.
func (*Config) AgentProfileDir ¶
AgentProfileDir is the host folder for one named credential profile of an agent: <ConfigDir>/<agent>/profiles/<name>/. "default" is just the profile named "default" — every login lives under profiles/, so this always resolves there.
func (*Config) Clone ¶
Clone returns a copy that can be mutated without touching the original. A plain `*cfg` is NOT enough: Config carries per-run maps (the explicitly-set keys, and the per-agent profile, model and effort tiers), and a shallow copy shares them — so a caller that "copied the config" to change one run's model would silently change every other holder's too, and a concurrent one would race. Callers that run several configurations side by side (coop eval) rely on this.
func (*Config) Cmd ¶
Cmd resolves a command setting (COOP_<NAME>_CMD) the same way Load resolves every other: environment variable, then conf file, then the built-in default — then splits it into words. It lets an agent adapter own its own default command without config knowing the agent set.
func (*Config) DefaultProfileOf ¶
DefaultProfileOf returns the profile marked default for agent, or the built-in DefaultProfile when none is marked.
func (*Config) DefaultsFile ¶
DefaultsFile marks each agent's default profile (KEY=VALUE, agent=profile): the profile an interactive run uses when none is given on the CLI. Managed by `coop credentials <agent> <credential> default`.
func (*Config) EffortFor ¶
EffortFor resolves the reasoning effort a run of agent should use, most specific first:
- the explicit per-run choice (target /effort),
- the active rotation target's effort,
- the agent-wide COOP_<AGENT>_MODEL's /effort.
Like the model, effort is its own axis — never a property of a credential. "" means no coop-level choice, so the agent CLI's own default applies (see agent.withEffort).
func (*Config) Explicit ¶
Explicit reports whether the user explicitly set key (env var or conf file) — false when the loaded value is just the built-in default. The .agent/project.yaml box: overlay (box.Run) uses it so a committed repo policy fills only the slots the user left unset: an explicit setting always wins, and — since the built-in egress default is the loosest — a repo can only tighten.
func (*Config) GlobalPresetsDir ¶
GlobalPresetsDir is the per-user presets root (~/.config/coop/presets): a second location `coop <preset>` and `coop presets` load from when the repo doesn't define the name (a repo preset wins a collision). COOP_PRESETS_DIR overrides the path — free testability, and it lets a user relocate the folder.
func (*Config) Instructions ¶
Instructions is the optional shared instruction file wired into each agent.
func (*Config) ModelFor ¶
ModelFor resolves the model a run of agent should use, most specific first:
- the explicit per-run choice,
- the active rotation target's model (a loop's `opus@work` — re-set on each rotation),
- the agent-wide COOP_<AGENT>_MODEL.
The model is its own axis — never a property of a credential (a credential is just an account). "" means no coop-level choice — the agent CLI's own default runs (including a model baked into COOP_<AGENT>_CMD, which the adapters never override; see agent.withModel).
func (*Config) Profiles ¶
Profiles lists agent's credential profile names from its profiles/ dir, or nothing when the agent has never been used (or has no profiles/ dir yet).
func (*Config) SetActiveEffort ¶
SetActiveEffort selects the reasoning effort a run of agent uses, overriding every other tier — only an EXPLICIT target /effort lands here. Empty clears it, falling back to the lower tiers.
func (*Config) SetActiveModel ¶
SetActiveModel selects the model a run of agent uses, overriding every other tier — only an explicit one-off choice lands here. Empty clears the selection, falling back to the lower tiers.
func (*Config) SetActiveProfile ¶
SetActiveProfile selects which credential profile of agent AgentDir resolves to — and therefore which one the box mounts and the adapters read. The loop calls this to rotate between subscriptions; an empty name resets to the default.
func (*Config) SetDefaultProfile ¶
SetDefaultProfile marks name as agent's default profile, persisting it to DefaultsFile and updating the in-memory view. The load→modify→write runs under WithLock so concurrent writers (e.g. two `coop credentials default` for different agents) don't lose each other's edit.
func (*Config) SetEgress ¶
SetEgress records the posture the host resolved for this launch (network admission folds the repo's request, the remembered approval and the operator's flags into one decision). Marking it explicit keeps a later project-policy overlay from deciding the mode a second time.
func (*Config) SetRuntimeLimits ¶
SetRuntimeLimits fixes one admitted launch's caps without changing the operator config. Marking them explicit also carries them through a supervised ACP child.
func (*Config) SetTargetEffort ¶
SetTargetEffort selects the active rotation target's effort — applied at loop start and on every rotation, below an explicit target /effort and above every static default. Empty clears it.
func (*Config) SetTargetModel ¶
SetTargetModel selects the active rotation target's model — a loop applies it at start and on every rotation, so an `opus@work` target runs opus until the rotation moves on. It ranks below an explicit one-off target and above every static default. Empty clears it (a bare credential target), so resolution falls through to the agent-wide default.
type Failure ¶
Failure is a settings problem this package could not work around, kept as the PARTS a person needs — where it is, what is wrong, and the one change that fixes it — rather than as a rendered block: config is a leaf library, and the CLI owns the terminal (internal/importdag_test.go). Where is empty when no file carries the problem, Action when there is nothing useful to add.