Help us shape the future of Go! Take the 2026 Go Developer Survey

config

package
v0.56.0 Latest Latest
Warning

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

Go to latest
Published: Aug 24, 2026 License: MIT Imports: 10 Imported by: 0

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

View Source
const (
	RouterModePrompt   = "prompt"
	RouterModeDisabled = "disabled"
	RouterModeEnabled  = "enabled"
)
View Source
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.

View Source
const ProjectConfigFile = ".treeline.yml"

Variables

View Source
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": "",
}
View Source
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

func DeepMerge(base, override map[string]any) map[string]any

DeepMerge merges override into base. Override values win for present keys; nested maps are merged recursively; missing keys get defaults from base.

func Dig

func Dig(m map[string]any, keys ...string) any

Dig traverses nested maps by keys, returning nil if any step fails.

func IsValidIdentifier added in v0.40.2

func IsValidIdentifier(s string) bool

IsValidIdentifier reports whether s is a safe project / database identifier.

func SanitizeIdentifier added in v0.40.2

func SanitizeIdentifier(s string) string

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.

func WarnUnknownKeys

func WarnUnknownKeys(data map[string]any, knownKeys map[string]bool, configName string)

WarnUnknownKeys checks data for top-level keys not present in knownKeys and prints warnings to stderr. configName identifies the file in messages (e.g. "config.json", ".treeline.yml").

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

type ProvisionDatabase struct {
	Template string
	Source   string
	Hydrate  string
}

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

type RelatedRepo struct {
	Repo string
	Type string
}

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

type StartHook struct {
	Auto     bool
	PreStart []string
	PostStop []string
}

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:

  1. Explicit router.domain in config.json → use it
  2. Config file exists but router.domain absent → "localhost" (pre-prt.dev install)
  3. 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}".

Jump to

Keyboard shortcuts

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