Documentation
¶
Overview ¶
Package config handles user and project configuration for git-treeline.
Project Config Loading Strategy ¶
Project configuration (.treeline.yml) is branch-specific — each worktree has its own copy matching its checked-out branch. The rule is simple:
**Always load .treeline.yml from the worktree you're operating on.**
Two exceptions:
- gtl new / gtl review — worktree doesn't exist yet, so initial config is read from the main repo. After git worktree add, setup runs from the NEW worktree's config. The --start flag also reloads from the worktree.
- gtl init / gtl prune — global operations with no specific worktree.
## Commands That Load From Worktree
All of these read .treeline.yml from the current worktree directory:
- gtl start / stop / restart — start also syncs env file + editor config
- gtl setup (when run inside an existing worktree)
- gtl refresh — detection uses worktree's port_count, not main repo's
- gtl doctor
- gtl env show / gtl env sync
- gtl editor refresh
- gtl link / unlink
- gtl open, gtl tunnel, gtl db, gtl release
- gtl clone (operates on the cloned repo itself)
## Env Sync Lifecycle
When does .treeline.yml env: get written to the env file (.env.local)?
- gtl start — syncs env file + editor settings before starting the server
- gtl restart — syncs env file + pushes updated env to the supervisor's in-memory env map (update-env socket command), then restarts
- gtl env sync — explicit manual sync for users who don't use gtl start
- gtl setup — full provisioning: copies source template then writes managed keys
Changes to commands.start require killing the supervisor (Ctrl+C) and running gtl start fresh. gtl stop only stops the child process — the supervisor stays alive and gtl start resumes with the original command. gtl restart warns if it detects a mismatch.
## Implementation
Most code uses:
pc := config.LoadProjectConfig(absPath) // absPath = worktree directory
The setup package provides one constructor:
- setup.New(worktreePath, mainRepo, uc) — loads config from worktree. mainRepo is only used for copy_files source and SQLite template paths. The cmd layer handles pre-creation config reads (e.g. gtl new reads mainRepo for project name before the worktree exists).
setup.RegenerateEnvFile does incremental env sync (updateOrAppend on each managed key) without copying the source template. Returns nil gracefully if no allocation exists.
Package config provides user and project configuration management. User config (config.json) defines global allocation policy like port ranges and Redis strategy. Project config (.treeline.yml) defines per-project settings like database templates and setup commands.
Index ¶
- Constants
- Variables
- func DeepMerge(base, override map[string]any) map[string]any
- func Dig(m map[string]any, keys ...string) any
- func IsValidIdentifier(s string) bool
- func SanitizeIdentifier(s string) string
- func WarnUnknownKeys(data map[string]any, knownKeys map[string]bool, configName string)
- type DBSourceConfig
- type ProjectConfig
- func (pc *ProjectConfig) Aliases() map[string]int
- func (pc *ProjectConfig) CopyFiles() []string
- func (pc *ProjectConfig) DatabaseAdapter() string
- func (pc *ProjectConfig) DatabaseConnArgs() []string
- func (pc *ProjectConfig) DatabaseExtensionsRequire() []string
- func (pc *ProjectConfig) DatabaseExtensionsStrip() []string
- func (pc *ProjectConfig) DatabasePatterns() []string
- func (pc *ProjectConfig) DatabaseSSLMode() string
- func (pc *ProjectConfig) DatabaseSourceEnvs() []string
- func (pc *ProjectConfig) DatabaseSourceSpec(env string) (DBSourceConfig, bool)
- func (pc *ProjectConfig) DatabaseSyncOnCreate() bool
- func (pc *ProjectConfig) DatabaseTemplate() string
- func (pc *ProjectConfig) Editor() map[string]string
- func (pc *ProjectConfig) EditorColor() string
- func (pc *ProjectConfig) EditorTheme() string
- func (pc *ProjectConfig) EditorTitle() string
- func (pc *ProjectConfig) EnvFileSource() string
- func (pc *ProjectConfig) EnvFileTarget() string
- func (pc *ProjectConfig) EnvTemplate() map[string]string
- func (pc *ProjectConfig) Exists() bool
- func (pc *ProjectConfig) HasEnvFileConfig() bool
- func (pc *ProjectConfig) Hooks() map[string][]string
- func (pc *ProjectConfig) LoadError() error
- func (pc *ProjectConfig) MergeTarget() string
- func (pc *ProjectConfig) MigrateCommand() string
- func (pc *ProjectConfig) PortsNeeded() int
- func (pc *ProjectConfig) Project() string
- func (pc *ProjectConfig) Provision() ProvisionConfig
- func (pc *ProjectConfig) RelatedRepos() []RelatedRepo
- func (pc *ProjectConfig) SetProject(name string) error
- func (pc *ProjectConfig) SetupCommands() []string
- func (pc *ProjectConfig) StartCommand() string
- func (pc *ProjectConfig) StartHooks() map[string]StartHook
- func (pc *ProjectConfig) Validate() error
- func (pc *ProjectConfig) WorktreeBase() string
- type ProvisionConfig
- type ProvisionDatabase
- type RelatedRepo
- type StartHook
- type UserConfig
- func (uc *UserConfig) DeleteTunnel(name string) string
- func (uc *UserConfig) EditorColor(project, branch string) string
- func (uc *UserConfig) EditorName() string
- func (uc *UserConfig) EditorTheme(project, branch string) string
- func (uc *UserConfig) Exists() bool
- func (uc *UserConfig) Get(dottedKey string) any
- func (uc *UserConfig) HasExplicitRouterDomain() bool
- func (uc *UserConfig) Init() error
- func (uc *UserConfig) MigrateProjectKeys(oldName, newName string) int
- func (uc *UserConfig) PortBase() int
- func (uc *UserConfig) PortIncrement() int
- func (uc *UserConfig) PortReservations() map[string]int
- func (uc *UserConfig) RedisDatabases() int
- func (uc *UserConfig) RedisStrategy() string
- func (uc *UserConfig) RedisURL() string
- func (uc *UserConfig) ReservedPorts() map[int]bool
- func (uc *UserConfig) ResolveWorktreePath(mainRepo, project, branch string) string
- func (uc *UserConfig) ReviewSkipSwitchConfirm() bool
- func (uc *UserConfig) RouterAliases() map[string]int
- func (uc *UserConfig) RouterDomain() string
- func (uc *UserConfig) RouterMode() string
- func (uc *UserConfig) RouterPort() int
- func (uc *UserConfig) RouterWarningsEnabled() bool
- func (uc *UserConfig) SafariWarningsEnabled() bool
- func (uc *UserConfig) Save() error
- func (uc *UserConfig) Set(dottedKey string, value any)
- func (uc *UserConfig) SetEditorName(name string)
- func (uc *UserConfig) SetRouterMode(mode string)
- func (uc *UserConfig) TunnelConfigs() map[string]string
- func (uc *UserConfig) TunnelDefault() string
- func (uc *UserConfig) TunnelDomain(override string) string
- func (uc *UserConfig) TunnelName(override string) string
- func (uc *UserConfig) WorktreePathTemplate() string
Constants ¶
const ( RouterModePrompt = "prompt" RouterModeDisabled = "disabled" RouterModeEnabled = "enabled" )
const DefaultRedisDatabases = 16
DefaultRedisDatabases matches a stock Redis build (databases 16 → indices 0–15). db0 is reserved for the main/template worktree, leaving 1–15 for feature worktrees under the "database" strategy. Raise `databases` in redis.conf and mirror it via `gtl config set redis.databases N` to grow.
const ProjectConfigFile = ".treeline.yml"
Variables ¶
var ProjectDefaults = map[string]any{ "port_count": 1, "env_file": ".env.local", "database": map[string]any{ "adapter": "postgresql", "template": nil, "pattern": "{template}_{worktree}", }, "copy_files": []any{}, "env": map[string]any{}, "hooks": map[string]any{}, "commands": map[string]any{}, "editor": map[string]any{}, "merge_target": "", "worktree_base": "", }
var UserDefaults = map[string]any{ "port": map[string]any{ "base": float64(3002), "increment": float64(2), }, "redis": map[string]any{ "strategy": "prefixed", "url": "redis://localhost:6379", "databases": float64(DefaultRedisDatabases), }, "router": map[string]any{ "port": float64(3001), }, "tunnel": map[string]any{}, }
Functions ¶
func DeepMerge ¶
DeepMerge merges override into base. Override values win for present keys; nested maps are merged recursively; missing keys get defaults from base.
func IsValidIdentifier ¶ added in v0.40.2
IsValidIdentifier reports whether s is a safe project / database identifier.
func SanitizeIdentifier ¶ added in v0.40.2
SanitizeIdentifier converts an arbitrary string into a valid identifier by replacing runs of non-identifier characters with `_`, trimming leading and trailing underscores, and prefixing with `db_` when the result would start with a digit. Returns "app" for inputs that contain no usable characters.
Types ¶
type DBSourceConfig ¶ added in v0.43.8
type DBSourceConfig struct {
Via string // "fly" | "heroku" | "env"
App string // fly/heroku: app name
Var string // fly/heroku: platform env var to read (default DATABASE_URL); env: local env var name
}
DBSourceConfig is one configured remote source under database.sources.<env>.
type ProjectConfig ¶
type ProjectConfig struct {
ProjectRoot string
Data map[string]any
// contains filtered or unexported fields
}
func LoadProjectConfig ¶
func LoadProjectConfig(projectRoot string) *ProjectConfig
func (*ProjectConfig) Aliases ¶
func (pc *ProjectConfig) Aliases() map[string]int
Aliases returns static alias routes from the project config (e.g. {"redis-ui": 8081}). These are team-shared routes for sidecars or services that manage their own ports.
func (*ProjectConfig) CopyFiles ¶
func (pc *ProjectConfig) CopyFiles() []string
func (*ProjectConfig) DatabaseAdapter ¶
func (pc *ProjectConfig) DatabaseAdapter() string
func (*ProjectConfig) DatabaseConnArgs ¶ added in v0.43.6
func (pc *ProjectConfig) DatabaseConnArgs() []string
DatabaseConnArgs builds connection flag arguments for psql/createdb/dropdb from optional database.host, database.port, and database.user config values. Setting host: localhost forces TCP connections, which avoids Postgres.app's Unix socket authorization dialog when gtl is invoked from a native macOS app.
func (*ProjectConfig) DatabaseExtensionsRequire ¶ added in v0.43.8
func (pc *ProjectConfig) DatabaseExtensionsRequire() []string
DatabaseExtensionsRequire returns extensions to pre-create before a restore.
func (*ProjectConfig) DatabaseExtensionsStrip ¶ added in v0.43.8
func (pc *ProjectConfig) DatabaseExtensionsStrip() []string
DatabaseExtensionsStrip returns extensions to comment out of the restore TOC.
func (*ProjectConfig) DatabasePatterns ¶ added in v0.56.0
func (pc *ProjectConfig) DatabasePatterns() []string
DatabasePatterns returns the primary database naming pattern from database.pattern followed by the database.extra patterns, in declaration order. The primary is cloned from database.template; the extras name auxiliary databases that treeline allocates, tracks, and drops but never creates. Validate rejects the malformed entries this getter tolerates.
func (*ProjectConfig) DatabaseSSLMode ¶ added in v0.43.8
func (pc *ProjectConfig) DatabaseSSLMode() string
DatabaseSSLMode returns the explicit sslmode from config, or "" when unset. The dbsource layer applies the "require" default; returning "" here lets an sslmode embedded in a connection URL take effect when config doesn't override.
func (*ProjectConfig) DatabaseSourceEnvs ¶ added in v0.43.8
func (pc *ProjectConfig) DatabaseSourceEnvs() []string
DatabaseSourceEnvs returns the configured source env names, sorted. Used to list available envs in error messages.
func (*ProjectConfig) DatabaseSourceSpec ¶ added in v0.43.8
func (pc *ProjectConfig) DatabaseSourceSpec(env string) (DBSourceConfig, bool)
DatabaseSourceSpec returns the configured source for a named env (e.g. "production"), and whether it exists.
func (*ProjectConfig) DatabaseSyncOnCreate ¶ added in v0.43.10
func (pc *ProjectConfig) DatabaseSyncOnCreate() bool
func (*ProjectConfig) DatabaseTemplate ¶
func (pc *ProjectConfig) DatabaseTemplate() string
func (*ProjectConfig) Editor ¶
func (pc *ProjectConfig) Editor() map[string]string
func (*ProjectConfig) EditorColor ¶
func (pc *ProjectConfig) EditorColor() string
EditorColor returns the editor color setting ("auto", a hex string, or empty).
func (*ProjectConfig) EditorTheme ¶
func (pc *ProjectConfig) EditorTheme() string
EditorTheme returns the editor theme override, or empty if not configured.
func (*ProjectConfig) EditorTitle ¶
func (pc *ProjectConfig) EditorTitle() string
EditorTitle returns the editor title template, or empty if not configured.
func (*ProjectConfig) EnvFileSource ¶
func (pc *ProjectConfig) EnvFileSource() string
func (*ProjectConfig) EnvFileTarget ¶
func (pc *ProjectConfig) EnvFileTarget() string
func (*ProjectConfig) EnvTemplate ¶
func (pc *ProjectConfig) EnvTemplate() map[string]string
func (*ProjectConfig) Exists ¶
func (pc *ProjectConfig) Exists() bool
func (*ProjectConfig) HasEnvFileConfig ¶
func (pc *ProjectConfig) HasEnvFileConfig() bool
HasEnvFileConfig returns true if the config explicitly declares an env_file block.
func (*ProjectConfig) Hooks ¶
func (pc *ProjectConfig) Hooks() map[string][]string
Hooks returns lifecycle hook commands keyed by hook name (pre_setup, post_setup, pre_release, post_release). Returns nil if no hooks are configured.
func (*ProjectConfig) LoadError ¶ added in v0.48.0
func (pc *ProjectConfig) LoadError() error
LoadError reports a failure to read or parse the project config file. It is nil when the config loaded cleanly or was simply absent (defaults applied). Callers about to take a config-derived destructive action should consult it.
func (*ProjectConfig) MergeTarget ¶
func (pc *ProjectConfig) MergeTarget() string
MergeTarget returns the branch that prune --merged checks against.
func (*ProjectConfig) MigrateCommand ¶ added in v0.43.10
func (pc *ProjectConfig) MigrateCommand() string
func (*ProjectConfig) PortsNeeded ¶
func (pc *ProjectConfig) PortsNeeded() int
func (*ProjectConfig) Project ¶
func (pc *ProjectConfig) Project() string
func (*ProjectConfig) Provision ¶ added in v0.46.0
func (pc *ProjectConfig) Provision() ProvisionConfig
Provision returns the parsed provision: section. The returned config's Database.Template falls back to the top-level database.template when the provision block doesn't override it, keeping a single source of truth for the name gtl clones worktree databases from.
func (*ProjectConfig) RelatedRepos ¶ added in v0.44.0
func (pc *ProjectConfig) RelatedRepos() []RelatedRepo
RelatedRepos returns structural sibling repos declared under related_repos. Each entry may be a bare "owner/name" string or a map with repo/type keys:
related_repos:
- acme/web-server
- repo: acme/mobile-app
type: consumes-api
func (*ProjectConfig) SetProject ¶
func (pc *ProjectConfig) SetProject(name string) error
SetProject writes the project name to .treeline.yml. If a project: line exists, it's replaced in place. Otherwise the field is prepended.
func (*ProjectConfig) SetupCommands ¶
func (pc *ProjectConfig) SetupCommands() []string
func (*ProjectConfig) StartCommand ¶
func (pc *ProjectConfig) StartCommand() string
func (*ProjectConfig) StartHooks ¶
func (pc *ProjectConfig) StartHooks() map[string]StartHook
StartHooks returns named start-lifecycle hooks from the hooks: block. Only map-valued entries with pre_start/post_stop/auto keys are returned; array-valued entries (pre_setup, post_setup, etc.) are ignored.
func (*ProjectConfig) Validate ¶ added in v0.40.2
func (pc *ProjectConfig) Validate() error
Validate checks that the loaded config has identifier-safe values for fields that propagate into databases, redis prefixes, and router keys. Returns nil when the config is safe to use, otherwise an error naming the offending field with a suggested replacement.
func (*ProjectConfig) WorktreeBase ¶ added in v0.50.0
func (pc *ProjectConfig) WorktreeBase() string
WorktreeBase returns the default base branch new worktrees are created from when `gtl new` is invoked without an explicit --base. Empty means fall back to the current branch. This is the branch you start work from, distinct from merge_target (the branch you merge back into / prune against).
type ProvisionConfig ¶ added in v0.46.0
type ProvisionConfig struct {
Present bool
Apt []string
Services []string
Database ProvisionDatabase
}
ProvisionConfig is the parsed provision: section — the declared, executable answer to "what must be true on a host before gtl setup can succeed for this repo." Present reports whether the section exists at all (absent = no-op).
type ProvisionDatabase ¶ added in v0.46.0
ProvisionDatabase declares how to bring the template database into existence on a fresh host. Template defaults to the top-level database.template — the same database gtl clones worktree databases from — so provision creates THAT database rather than a parallel one. Source names a database.sources.<env> to hydrate from (preferred); Hydrate is a fallback shell command run in the repo dir to build+fill the template when no source is configured.
type RelatedRepo ¶ added in v0.44.0
RelatedRepo is one structural sibling declared in .treeline.yml. Unlike a runtime edge (an ad-hoc branch-to-branch link stored in the registry), this is a durable, version-controlled topology fact: "every worktree of this repo relates to that repo." Type defaults to "related".
type StartHook ¶
StartHook defines a named hook activated via `gtl start --with <name>` or automatically on every fresh start when Auto is true. PreStart and PostStop each support a single string or an array of strings.
type UserConfig ¶
type UserConfig struct {
Path string
Data map[string]any
// contains filtered or unexported fields
}
func LoadUserConfig ¶
func LoadUserConfig(path string) *UserConfig
func (*UserConfig) DeleteTunnel ¶
func (uc *UserConfig) DeleteTunnel(name string) string
DeleteTunnel removes a named tunnel from config. Returns the new default name (may be empty if no tunnels remain). Does not call Save().
func (*UserConfig) EditorColor ¶
func (uc *UserConfig) EditorColor(project, branch string) string
EditorColor returns a color override for the given project or project/branch.
func (*UserConfig) EditorName ¶
func (uc *UserConfig) EditorName() string
EditorName returns the stored editor name (e.g. "cursor", "vscode"), or empty.
func (*UserConfig) EditorTheme ¶
func (uc *UserConfig) EditorTheme(project, branch string) string
EditorTheme returns a theme override for the given project or project/branch.
func (*UserConfig) Exists ¶
func (uc *UserConfig) Exists() bool
func (*UserConfig) Get ¶
func (uc *UserConfig) Get(dottedKey string) any
func (*UserConfig) HasExplicitRouterDomain ¶
func (uc *UserConfig) HasExplicitRouterDomain() bool
HasExplicitRouterDomain reports whether router.domain is set in config.json.
func (*UserConfig) Init ¶
func (uc *UserConfig) Init() error
func (*UserConfig) MigrateProjectKeys ¶ added in v0.40.2
func (uc *UserConfig) MigrateProjectKeys(oldName, newName string) int
MigrateProjectKeys rewrites every config map key that's exactly oldName or is prefixed with "oldName/" so it uses newName instead. Targets the maps where project names appear as keys: port.reservations, editor.themes, editor.colors. Returns the number of keys rewritten. Caller must Save().
func (*UserConfig) PortBase ¶
func (uc *UserConfig) PortBase() int
func (*UserConfig) PortIncrement ¶
func (uc *UserConfig) PortIncrement() int
func (*UserConfig) PortReservations ¶
func (uc *UserConfig) PortReservations() map[string]int
func (*UserConfig) RedisDatabases ¶ added in v0.43.18
func (uc *UserConfig) RedisDatabases() int
RedisDatabases returns the number of databases the target Redis is configured for (the `databases` directive in redis.conf). It bounds how many worktrees the "database" strategy can isolate: slots 1..N-1. Values below 2 (no room for a feature worktree beyond db0) fall back to the stock default.
func (*UserConfig) RedisStrategy ¶
func (uc *UserConfig) RedisStrategy() string
func (*UserConfig) RedisURL ¶
func (uc *UserConfig) RedisURL() string
func (*UserConfig) ReservedPorts ¶
func (uc *UserConfig) ReservedPorts() map[int]bool
ReservedPorts returns all ports covered by reservations. Each reservation blocks a full increment-sized range so multi-port projects are protected.
func (*UserConfig) ResolveWorktreePath ¶
func (uc *UserConfig) ResolveWorktreePath(mainRepo, project, branch string) string
ResolveWorktreePath applies the worktree path template. Returns "" if no template is configured (caller should fall back to default behavior).
func (*UserConfig) ReviewSkipSwitchConfirm ¶ added in v0.39.4
func (uc *UserConfig) ReviewSkipSwitchConfirm() bool
ReviewSkipSwitchConfirm returns whether `gtl review` should bypass the "Switch to PR #N (branch: ...)?" prompt when invoked from inside another worktree. Default: false. Set review.skip_switch_confirm: true to bypass.
func (*UserConfig) RouterAliases ¶
func (uc *UserConfig) RouterAliases() map[string]int
RouterAliases returns static alias routes from the user config (e.g. {"grafana": 3100}). These are per-machine routes for personal services.
func (*UserConfig) RouterDomain ¶
func (uc *UserConfig) RouterDomain() string
RouterDomain returns the base domain for local routing.
Resolution order:
- Explicit router.domain in config.json → use it
- Config file exists but router.domain absent → "localhost" (pre-prt.dev install)
- No config file at all → "prt.dev" (fresh machine)
This prevents upgrading the CLI binary from silently changing the domain for users who never explicitly set it.
func (*UserConfig) RouterMode ¶
func (uc *UserConfig) RouterMode() string
RouterMode returns the user's intent for the optional HTTPS router. prompt means offer setup during install, disabled means localhost-only, and enabled means install/repair the router when needed.
func (*UserConfig) RouterPort ¶
func (uc *UserConfig) RouterPort() int
RouterPort returns the port the subdomain router listens on. Default 3001. Kept off 3000 so gtl proxy can still forward OAuth/webhook callbacks on :3000.
func (*UserConfig) RouterWarningsEnabled ¶
func (uc *UserConfig) RouterWarningsEnabled() bool
RouterWarningsEnabled returns whether to show reminders about the optional local HTTPS router. Default: true. Set warnings.router: false to disable.
func (*UserConfig) SafariWarningsEnabled ¶
func (uc *UserConfig) SafariWarningsEnabled() bool
SafariWarningsEnabled returns whether to show Safari/hosts sync warnings. Default: true. Set warnings.safari: false to disable.
func (*UserConfig) Save ¶
func (uc *UserConfig) Save() error
func (*UserConfig) Set ¶
func (uc *UserConfig) Set(dottedKey string, value any)
func (*UserConfig) SetEditorName ¶
func (uc *UserConfig) SetEditorName(name string)
SetEditorName stores the editor name in config. Call Save() to persist.
func (*UserConfig) SetRouterMode ¶
func (uc *UserConfig) SetRouterMode(mode string)
SetRouterMode stores the user's router intent. Call Save() to persist.
func (*UserConfig) TunnelConfigs ¶
func (uc *UserConfig) TunnelConfigs() map[string]string
TunnelConfigs returns all configured tunnels as a map of name → domain.
func (*UserConfig) TunnelDefault ¶
func (uc *UserConfig) TunnelDefault() string
TunnelDefault returns the name of the default tunnel config, or "".
func (*UserConfig) TunnelDomain ¶
func (uc *UserConfig) TunnelDomain(override string) string
TunnelDomain returns the domain for a tunnel. If override is non-empty it selects that tunnel config; otherwise the default is used.
func (*UserConfig) TunnelName ¶
func (uc *UserConfig) TunnelName(override string) string
TunnelName resolves a tunnel name: returns override if non-empty, else the configured default. Used by cmd/tunnel and cmd/share to support --tunnel.
func (*UserConfig) WorktreePathTemplate ¶
func (uc *UserConfig) WorktreePathTemplate() string
WorktreePathTemplate returns the configured worktree path template, or "". The template supports {project} and {branch} interpolation and is resolved relative to the main repo root. Example: ".worktrees/{branch}".