Documentation
¶
Overview ¶
Package appdir decides where a tool keeps its things: the global home (~/.<app>), the project home (.<app>/ found by walking up), the folders and files inside them, the prod/dev profile split, pointer keys, and moving an old home. It implements the folder parts of the app standard; the full contract is docs/SPEC.md.
New only reads: it stats folders and reads home.jsonc and config pointer keys, and never creates anything. Folders appear on the first Ensure. Every resolved path records the Rule that picked it, so a tool's `paths --json` and `doctor` can say why a path is what it is.
d, err := appdir.New("lore", appdir.WithHome(flagHome), appdir.WithProfile(flagProfile))
if err != nil { return err }
db, err := d.Ensure(appdir.KindDB) // creates .lore/ folders lazily; ErrNoProject outside a project
appdir keeps no package-level mutable state; every outside input (env, home dir, working dir, build info) has a seam option.
Index ¶
- Variables
- func CleanEnv(environ []string, prefix string) []string
- func ForTest(t testing.TB, app string) string
- type ConfigFile
- type ConfigReader
- type DBAccess
- type Dirs
- func (d *Dirs) App() string
- func (d *Dirs) Banner() string
- func (d *Dirs) CheckDB(path string) (DBAccess, error)
- func (d *Dirs) ChildEnv(environ []string) []string
- func (d *Dirs) ConfigFiles() []ConfigFile
- func (d *Dirs) DaemonDiscovery() (string, Profile, error)
- func (d *Dirs) DaemonProfile() Profile
- func (d *Dirs) Ensure(k Kind) (string, error)
- func (d *Dirs) EnsureSocketDir() (Socket, error)
- func (d *Dirs) EnvName(suffix string) string
- func (d *Dirs) EnvPrefix() string
- func (d *Dirs) ForProfile(p Profile) (*Dirs, error)
- func (d *Dirs) GitignoreBlock() string
- func (d *Dirs) Global() Home
- func (d *Dirs) HasProject() bool
- func (d *Dirs) InitHome(path string, s Scope) error
- func (d *Dirs) InitProject(dir string) (string, error)
- func (d *Dirs) IsRelease() bool
- func (d *Dirs) KindEnv(k Kind) string
- func (d *Dirs) Kinds() []KindSpec
- func (d *Dirs) Mode() Mode
- func (d *Dirs) MoveLegacy(ctx context.Context) (MoveResult, error)
- func (d *Dirs) Name(base string) string
- func (d *Dirs) NameWith(base, sep string) string
- func (d *Dirs) Path(k Kind) (string, error)
- func (d *Dirs) PathIn(k Kind, s Scope) (string, error)
- func (d *Dirs) Paths() []Entry
- func (d *Dirs) Profile() Profile
- func (d *Dirs) Project() (Home, error)
- func (d *Dirs) ReleaseReason() string
- func (d *Dirs) RunPath(f RunFile) (string, error)
- func (d *Dirs) Socket() (Socket, error)
- func (d *Dirs) VerifyFile(path string) error
- func (d *Dirs) Warnings() []Warning
- func (d *Dirs) WriteGitignore() (bool, error)
- type Entry
- type EntryType
- type GitRule
- type Home
- type HomeInfo
- type Kind
- type KindOption
- type KindSpec
- type LegacyHome
- type LegacyVerify
- type Lookup
- type Mode
- type MoveResult
- type MoveStatus
- type Option
- func WithAllowRoot(allow bool) Option
- func WithBuildInfo(fn func() (*debug.BuildInfo, bool)) Option
- func WithCacheTag(on bool) Option
- func WithConfigReader(fn ConfigReader) Option
- func WithDaemonProfile(name string) Option
- func WithDevProfile(p Profile) Option
- func WithDirName(name string) Option
- func WithEnv(fn func(string) (string, bool)) Option
- func WithEnvPrefix(prefix string) Option
- func WithGitCommit(patterns ...string) Option
- func WithGitIgnore(patterns ...string) Option
- func WithHome(path string) Option
- func WithHomeDir(fn func() (string, error)) Option
- func WithKind(name Kind, opts ...KindOption) Option
- func WithLayoutVersion(n int) Option
- func WithLegacyHome(l LegacyHome) Option
- func WithLegacyVerify(fn LegacyVerify) Option
- func WithLookup(l Lookup) Option
- func WithMode(m Mode) Option
- func WithPerm(dir, file fs.FileMode) Option
- func WithProfile(name string) Option
- func WithProfiles(names ...Profile) Option
- func WithRelease(release bool) Option
- func WithReleaseProfile(p Profile) Option
- func WithRunFile(f RunFile, name string) Option
- func WithSocketMaxLen(n int) Option
- func WithTempFallback(on bool) Option
- func WithTestGuard(on bool) Option
- func WithWorkDir(dir string) Option
- func WithoutKind(name Kind) Option
- type Profile
- type Rule
- type RunFile
- type Scope
- type Socket
- type Warning
- type WarningCode
Constants ¶
This section is empty.
Variables ¶
var ( ErrInvalidOption = errors.New("invalid option") ErrUnknownProfile = errors.New("unknown profile") ErrUnknownKind = errors.New("unknown kind") ErrNoProject = errors.New("no project home") ErrNoHome = errors.New("no home folder") ErrEnvVar = errors.New("variable not set") ErrPointerAbsolute = errors.New("absolute pointer in a committed file") ErrPointerMissing = errors.New("pointer target does not exist") ErrPointerNotHome = errors.New("pointer target is not a home of this app") ErrLayoutTooNew = errors.New("home layout is newer than this binary") ErrRootOwned = errors.New("running as root in another user's home") ErrSymlinkEscape = errors.New("symlink leads outside the home") ErrUnsafeTemp = errors.New("unsafe temp folder") ErrProdDB = errors.New("dev build refuses the prod database") ErrBusy = errors.New("busy") ErrGitignoreMarkers = errors.New("gitignore markers are broken") ErrNotHome = errors.New("folder belongs to another app") // ErrBadHomeFile: init found a home.jsonc that exists but cannot be read // or parsed. It is the user's file, so init refuses rather than replace // it; the reader's own error is wrapped too (fs.ErrPermission, ...). ErrBadHomeFile = errors.New("home file cannot be read") )
Sentinel errors. They are the only package-level variables in appdir and are never reassigned. Every returned error wraps one of them with the path, key or variable it is about, so callers use errors.Is and users read a full sentence. Mapping to exit codes is the tool's job (standard section 11). ds:def id=sentinel-errors-mwtzt4d9 owner=@khanakia stability=stable
Functions ¶
func CleanEnv ¶
CleanEnv returns environ without any <prefix>_* variable: the Go twin of a dev-env.sh wrapper. Pure function. ds:def id=cleanenv-276nsr8w owner=@khanakia stability=stable
func ForTest ¶
ForTest isolates a test from the developer's real homes (standard section 13): it points HOME, USERPROFILE, <APP>_HOME, XDG_*, CLAUDE_CONFIG_DIR, CODEX_HOME and the temp folder (TMPDIR, and TMP and TEMP, which Windows reads) into a temp root, unsets <APP>_PROFILE and the GIT_* variables that leak a parent repo, and sets APPDIR_TEST_ROOT so New panics on any path outside it. Returns the root. ds:def id=fortest-56v4yh8s owner=@khanakia stability=stable
Types ¶
type ConfigFile ¶
type ConfigFile struct {
Path string `json:"path"`
Home Scope `json:"home"`
Local bool `json:"local"`
Committed bool `json:"committed"`
Profile Profile `json:"profile,omitempty"` // set on the profile's own config.local.jsonc
}
ConfigFile is one config file in read order (later wins per key).
type ConfigReader ¶
ConfigReader reads one JSONC file into a map. A missing file must return an error wrapping fs.ErrNotExist.
type DBAccess ¶
type DBAccess int
DBAccess is the result of the prod-db guard.
type Dirs ¶
type Dirs struct {
// contains filtered or unexported fields
}
Dirs is the resolved set of homes and paths for one app. It is immutable and safe for concurrent use.
func New ¶
New resolves every home and path for app. It never creates anything. It fails only for a bad option set or an unknown profile; a missing project home is reported by the methods that need one. ds:def id=new-mes9nm7s owner=@khanakia stability=stable
func (*Dirs) Banner ¶
Banner returns the one stderr line for a non-release profile ("[lore] profile: dev → ~/.lore-dev"), or "" for the release profile. ds:def id=dirs-banner-cwbb5293 owner=@khanakia stability=stable
func (*Dirs) CheckDB ¶
CheckDB is the prod-db guard (SPEC 8.4). Call it before opening a database and before any migration. ds:def id=dirs-checkdb-2r8b9xmq owner=@khanakia stability=stable
func (*Dirs) ChildEnv ¶
ChildEnv returns environ with <APP>_PROFILE set to this profile, for every child process the tool starts (SPEC 8.5). ds:def id=dirs-childenv-myszxsrp owner=@khanakia stability=stable
func (*Dirs) ConfigFiles ¶
func (d *Dirs) ConfigFiles() []ConfigFile
ConfigFiles returns the config files in read order (SPEC 6.1). Missing files are listed; the loader treats them as empty. ds:def id=dirs-configfiles-nzbecu5q owner=@khanakia stability=stable
func (*Dirs) DaemonDiscovery ¶
DaemonDiscovery returns the discovery file of the daemon profile. A client reads only this file and the socket it names, never the other profile's db. ds:def id=dirs-daemondiscovery-wb9urrua owner=@khanakia stability=stable
func (*Dirs) DaemonProfile ¶
DaemonProfile returns the profile whose daemon a client talks to: --daemon-profile, then <APP>_DAEMON_PROFILE, then its own profile.
func (*Dirs) Ensure ¶
Ensure creates a kind's folder (or a file kind's parent folder) on first use and returns the kind's path. It is the lazy creation point: reads never create anything (SPEC 4.8). ds:def id=dirs-ensure-mxbz3fmd owner=@khanakia stability=stable
func (*Dirs) EnsureSocketDir ¶
EnsureSocketDir creates what a daemon needs before it listens: run/ through Ensure in every case, plus the private fallback folder (0700, with the symlink and owner checks) when the socket is not under run/. run/ is created even for a fallback or a Windows pipe because the daemon writes run/socket (the pointer file), the pid and discovery.json there; one code path for every OS keeps the Windows pipe case covered by the Unix tests. ds:def id=dirs-ensuresocketdir-r9rr28ym owner=@khanakia stability=stable
func (*Dirs) ForProfile ¶
ForProfile resolves the same app with the same options as if --profile p were given. It reads only; it never opens the other profile's files. ds:def id=dirs-forprofile-g2gegg5p owner=@khanakia stability=stable
func (*Dirs) GitignoreBlock ¶
GitignoreBlock returns the marker block for .<app>/.gitignore (SPEC 5.7): ignore everything, then re-include the committed files, folders first because git cannot re-include a file under an excluded folder. ds:def id=dirs-gitignoreblock-8bujrmug owner=@khanakia stability=stable
func (*Dirs) Global ¶
Global returns the global home. With no $HOME and no override, its Rule is RuleDefaults and Base/Data are empty.
func (*Dirs) HasProject ¶
HasProject reports whether a usable project home was found.
func (*Dirs) InitHome ¶
InitHome creates a home at path with home.jsonc for scope: the `<app> init --home X` command, also used to create a pointer target. ds:def id=dirs-inithome-934qhf2j owner=@khanakia stability=stable
func (*Dirs) InitProject ¶
InitProject creates <dir>/.<app>/ with home.jsonc and, inside a git work tree, the .gitignore block: the `<app> init` command. A project home is never created any other way. Returns the new marker folder. ds:def id=dirs-initproject-wpmefq6e owner=@khanakia stability=stable
func (*Dirs) KindEnv ¶
KindEnv returns the <APP>_<KIND>_DIR name of a kind, or "" for anchored kinds.
func (*Dirs) MoveLegacy ¶
func (d *Dirs) MoveLegacy(ctx context.Context) (MoveResult, error)
MoveLegacy moves an old global home to the new one on first run (SPEC 9, standard section 8). It never deletes user data and never moves committed project folders. With several WithLegacyHome entries, the first that exists is used. ds:def id=dirs-movelegacy-aw98ygmb owner=@khanakia stability=stable
func (*Dirs) Name ¶
Name returns base for the release profile and base-<profile> otherwise. Every label, unit, marker, pipe and item name goes through it.
func (*Dirs) NameWith ¶
NameWith is Name with a custom separator: NameWith("com.org.app", ".") gives "com.org.app.dev". ds:def id=dirs-namewith-uyg39uh6 owner=@khanakia stability=stable
func (*Dirs) Path ¶
Path returns a kind's path in its effective home (reads only). For ScopeBoth kinds that is the project home when there is one, else the global home. ds:def id=dirs-path-asygw3vm owner=@khanakia stability=stable
func (*Dirs) PathIn ¶
PathIn returns a kind's path in one home: ScopeGlobal or ScopeProject. ds:def id=dirs-pathin-2j8zfrym owner=@khanakia stability=stable
func (*Dirs) Paths ¶
Paths returns every kind's path, for paths --json and doctor. ScopeBoth kinds appear once per home. ds:def id=dirs-paths-6kdzcjzg owner=@khanakia stability=stable
func (*Dirs) Project ¶
Project returns the project home, or an error wrapping ErrNoProject (or the pointer error that made it unusable).
func (*Dirs) ReleaseReason ¶
ReleaseReason says which rule decided release or dev.
func (*Dirs) Socket ¶
Socket returns the socket path: run/<app>.sock when short enough, else a per-user fallback (platform rules in socket_<os>.go). ds:def id=dirs-socket-brsjjca9 owner=@khanakia stability=stable
func (*Dirs) VerifyFile ¶
VerifyFile applies the symlink rule (SPEC 5.6): a file may be a symlink only when its real path is inside the real path of the home it belongs to. ds:def id=dirs-verifyfile-2nyrnmv3 owner=@khanakia stability=stable
func (*Dirs) WriteGitignore ¶
WriteGitignore writes the block into the project home's .gitignore. It returns false (and writes nothing) when the home is not in a git work tree.
type Entry ¶
type Entry struct {
Kind Kind `json:"kind"`
Home Scope `json:"home"`
Path string `json:"path"`
Type EntryType `json:"type"`
Git GitRule `json:"git"`
Rule Rule `json:"rule"`
Fallback bool `json:"fallback"`
Note string `json:"note,omitempty"`
Error string `json:"error,omitempty"`
// contains filtered or unexported fields
}
Entry is one kind's resolved path, for paths --json and doctor.
type Home ¶
type Home struct {
Scope Scope `json:"scope"` // global or project
Marker string `json:"marker,omitempty"` // the .<app>/ that was found (project only)
Base string `json:"base"` // holds home.jsonc and the config files
Data string `json:"data"` // holds every other kind
Rule Rule `json:"rule"`
Fallback bool `json:"fallback"`
Note string `json:"note,omitempty"`
Info *HomeInfo `json:"info,omitempty"` // parsed home.jsonc, nil when absent
}
Home is one resolved home folder.
type HomeInfo ¶
type HomeInfo struct {
App string `json:"app"`
Layout int `json:"layout"`
Scope Scope `json:"scope"`
}
HomeInfo is the content of home.jsonc.
type Kind ¶
type Kind string
Kind names one entry in a home's layout: a file or a folder.
const ( KindHome Kind = "home" // home.jsonc: app, layout, scope KindConfig Kind = "config" // config.jsonc: settings, committed KindConfigLocal Kind = "config-local" // config.local.jsonc: this machine only KindGitignore Kind = "gitignore" // .gitignore: written between markers KindDB Kind = "db" // <app>.db KindBackups Kind = "backups" // backups/ KindCache Kind = "cache" // cache/: safe to delete KindRun Kind = "run" // run/: lock, pid, socket, discovery KindLogs Kind = "logs" // logs/ )
Standard kinds, used when the tool's author changes nothing (SPEC 5.1).
type KindOption ¶
type KindOption func(*KindSpec)
KindOption changes one KindSpec inside WithKind.
func Anchored ¶
func Anchored() KindOption
Anchored keeps the kind in the home root of both profiles and gives it no <APP>_<KIND>_DIR: it is part of what makes a folder a home.
func Disposable ¶
func Disposable() KindOption
Disposable marks the kind safe to delete (cache-like): it gets CACHEDIR.TAG and may fall back to the temp folder.
type KindSpec ¶
type KindSpec struct {
Name Kind `json:"name"`
Path string `json:"path"` // slash-separated, relative to the home
Type EntryType `json:"type"`
Git GitRule `json:"git"`
Scope Scope `json:"scope"` // "" until New fills in the mode's data scope
Disposable bool `json:"disposable"`
Anchored bool `json:"anchored"` // lives in the home root, no env override
}
KindSpec describes one entry of the layout. Kinds() returns the specs in effect, so paths --json and doctor can show the names the author chose.
type LegacyHome ¶
type LegacyHome struct {
Dir string // folder name under the user's home, e.g. ".pm"
DaemonLocks []string // lock files inside it to probe; default ["run/daemon.lock"]
}
LegacyHome names an old global home folder to move from (standard section 8).
type LegacyVerify ¶
LegacyVerify runs after a cross-disk copy in MoveLegacy, before the old folder is renamed away; a tool passes its database integrity check here.
type MoveResult ¶
type MoveResult struct {
Status MoveStatus `json:"status"`
From string `json:"from,omitempty"`
To string `json:"to,omitempty"`
Note string `json:"note,omitempty"`
}
MoveResult is the outcome of MoveLegacy.
type MoveStatus ¶
type MoveStatus string
MoveStatus is the outcome of MoveLegacy.
const ( MoveNone MoveStatus = "none" MoveDone MoveStatus = "moved" MoveBothExist MoveStatus = "both-exist" MoveSkipped MoveStatus = "skipped" MoveAlready MoveStatus = "already" )
Move outcomes.
type Option ¶
type Option func(*config)
Option changes one setting of New. Every choice in the standard is an option with the standard's default (rule zero, D17).
func WithAllowRoot ¶
WithAllowRoot passes the tool's --allow-root flag.
func WithBuildInfo ¶
WithBuildInfo replaces debug.ReadBuildInfo for release detection.
func WithCacheTag ¶
WithCacheTag turns CACHEDIR.TAG and OS backup/index exclusions on or off. Default on.
func WithConfigReader ¶
func WithConfigReader(fn ConfigReader) Option
WithConfigReader replaces the JSONC reader for home.jsonc and pointer keys.
func WithDaemonProfile ¶
WithDaemonProfile passes the tool's --daemon-profile flag.
func WithDevProfile ¶
WithDevProfile sets the profile of a non-release build. Default dev.
func WithDirName ¶
WithDirName sets the home folder name. Default "." + app.
func WithEnvPrefix ¶
WithEnvPrefix sets the env prefix. Default: the app name upper-cased, with "-" and "." turned into "_".
func WithGitCommit ¶
WithGitCommit adds committed gitignore patterns (relative to the home).
func WithGitIgnore ¶
WithGitIgnore forces patterns out of git; it wins over every commit rule.
func WithHomeDir ¶
WithHomeDir replaces the user home lookup.
func WithKind ¶
func WithKind(name Kind, opts ...KindOption) Option
WithKind adds a kind, or changes an existing one in place (rename = change its path). A new kind starts as Folder(name), Ignore(), data scope.
func WithLayoutVersion ¶
WithLayoutVersion sets the layout version this binary knows. Default 1.
func WithLegacyHome ¶
func WithLegacyHome(l LegacyHome) Option
WithLegacyHome names an old global home that MoveLegacy moves from.
func WithLegacyVerify ¶
func WithLegacyVerify(fn LegacyVerify) Option
WithLegacyVerify adds a check after a cross-disk legacy copy.
func WithLookup ¶
WithLookup sets the project lookup style. Default WalkUp.
func WithProfile ¶
WithProfile passes the tool's --profile flag. Empty means not given.
func WithProfiles ¶
WithProfiles sets the allowed profiles. Default prod, dev.
func WithRelease ¶
WithRelease states whether this binary is a release build, from the tool's own -ldflags -X variable. Without it, appdir reads Go's build info.
func WithReleaseProfile ¶
WithReleaseProfile sets the profile of a release build, the one that keeps base names. Default prod.
func WithRunFile ¶
WithRunFile renames one file in run/.
func WithSocketMaxLen ¶
WithSocketMaxLen sets the longest socket path before the /tmp fallback. Default 100 bytes (macOS allows about 104).
func WithTempFallback ¶
WithTempFallback turns the temp fallback of disposable kinds on or off. Default on.
func WithTestGuard ¶
WithTestGuard turns the test-binary path guard on or off. Default on.
func WithWorkDir ¶
WithWorkDir fixes the folder the project lookup starts from.
type Profile ¶
type Profile string
Profile names a set of homes (prod, dev, or an author-added name).
type Rule ¶
type Rule string
Rule names the resolution rule that picked a path, for paths --json and doctor.
const ( RuleFlag Rule = "flag" // --home (WithHome) RuleEnvHome Rule = "env-home" // <APP>_HOME RuleEnvKind Rule = "env-kind" // <APP>_<KIND>_DIR RuleProject Rule = "project" // found by lookup RuleWorktree Rule = "worktree" // main checkout of a linked worktree RulePointer Rule = "pointer" // home: or db: key RuleGlobal Rule = "global" // ~/.<app> RuleTemp Rule = "temp" // <tmp>/<app>-<uid>/ RuleDefaults Rule = "defaults" // no $HOME: global config is code defaults )
Rules.
type RunFile ¶
type RunFile string
RunFile names a file in run/.
const ( RunLock RunFile = "lock" // run/lock: migrations, layout changes RunDaemonLock RunFile = "daemon-lock" // run/daemon.lock: held for a daemon's life RunPID RunFile = "pid" // run/<app>.pid: display only RunDiscovery RunFile = "discovery" // run/discovery.json RunSocket RunFile = "socket" // run/<app>.sock RunSocketFile RunFile = "socket-file" // run/socket: path of a fallback socket )
Run files (SPEC 7).
type Socket ¶
type Socket struct {
Path string `json:"path"`
Fallback bool `json:"fallback"` // not under run/; the daemon writes Path to PointerFile
PointerFile string `json:"pointer_file"` // run/socket
Dir string `json:"dir"` // folder to create; "" for a Windows pipe
}
Socket is where a daemon listens (SPEC 7).
type Warning ¶
type Warning struct {
Code WarningCode `json:"code"`
Message string `json:"message"`
}
Warning is something the tool should print once (to stderr).
type WarningCode ¶
type WarningCode string
WarningCode identifies a warning.
const ( WarnProfileEnvIgnored WarningCode = "profile-env-ignored" WarnEnvPointsToProd WarningCode = "env-points-to-prod" WarnPointerChain WarningCode = "pointer-chain-ignored" WarnPointerProfile WarningCode = "pointer-ignored-for-profile" WarnCeilingRelative WarningCode = "ceiling-relative" // WarnCeilingDropped: an <APP>_CEILING_DIRS entry that is not relative // but does not expand to an absolute path ($VAR without braces, an unset // ${VAR}, ~user); it is ignored, and without this warning a ceiling would // silently have no effect (finding D5). WarnCeilingDropped WarningCode = "ceiling-dropped" WarnWorktreeMainMissing WarningCode = "worktree-main-missing" )
Warning codes.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
config-files
command
Command config-files lists the config files appdir hands to a config loader, in read order, for the prod and dev profiles, with a home: pointer, with --home, with no $HOME and with config.local.jsonc dropped.
|
Command config-files lists the config files appdir hands to a config loader, in read order, for the prod and dev profiles, with a home: pointer, with --home, with no $HOME and with config.local.jsonc dropped. |
|
custom-layout
command
Command custom-layout changes the standard layout of a home and shows what follows from it: the kinds in effect and their env names, the gitignore block, writing it into a .gitignore that also has hand-written lines, Ignore() and unknown kinds, init without a home file, Ensure with owner-only permissions and CACHEDIR.TAG, WithPerm and WithCacheTag(false), the symlink rule, VerifyFile and the layout-version guard.
|
Command custom-layout changes the standard layout of a home and shows what follows from it: the kinds in effect and their env names, the gitignore block, writing it into a .gitignore that also has hand-written lines, Ignore() and unknown kinds, init without a home file, Ensure with owner-only permissions and CACHEDIR.TAG, WithPerm and WithCacheTag(false), the symlink rule, VerifyFile and the layout-version guard. |
|
daemon-paths
command
Command daemon-paths shows the paths a tool with a background daemon needs: the files in run/, the socket (with its fallback when the path is too long for a Unix socket), and how a client finds the daemon of another profile.
|
Command daemon-paths shows the paths a tool with a background daemon needs: the files in run/, the socket (with its fallback when the path is too long for a Unix socket), and how a client finds the daemon of another profile. |
|
demo
command
Command demo prints what appdir resolves for an app named "demo", as text or as JSON.
|
Command demo prints what appdir resolves for an app named "demo", as text or as JSON. |
|
doctor
command
Command doctor builds the two reports every tool on the standard ships: `paths --json` (every kind, its path and the rule that picked it) and `doctor` (config files, warnings, layout, gitignore block).
|
Command doctor builds the two reports every tool on the standard ships: `paths --json` (every kind, its path and the rule that picked it) and `doctor` (config files, warnings, layout, gitignore block). |
|
fallbacks
command
Command fallbacks shows what appdir does when the user's home is missing or cannot be written: config uses code defaults, data kinds fail with a clear error, and disposable kinds (the cache) use a private temp folder.
|
Command fallbacks shows what appdir does when the user's home is missing or cannot be written: config uses code defaults, data kinds fail with a clear error, and disposable kinds (the cache) use a private temp folder. |
|
internal/doccheck/mdlinks
command
Command mdlinks fails when a relative link or #anchor in the repository's Markdown does not resolve.
|
Command mdlinks fails when a relative link or #anchor in the repository's Markdown does not resolve. |
|
internal/doccheck/mdwrap
command
Command mdwrap reports Markdown files with hard-wrapped prose: a paragraph line that continues on the next physical line.
|
Command mdwrap reports Markdown files with hard-wrapped prose: a paragraph line that continues on the next physical line. |
|
internal/doccheck/snippets
command
Command snippets keeps code blocks in the guides identical to the example programs they are copied from.
|
Command snippets keeps code blocks in the guides identical to the example programs they are copied from. |
|
internal/doccheck/words
command
Command words reports files that contain a forbidden word, matched without regard to case.
|
Command words reports files that contain a forbidden word, matched without regard to case. |
|
legacy-move
command
Command legacy-move shows MoveLegacy: a tool that used to keep its global home in ~/.demo-old moves it to ~/.demo on the first run of the new version, leaves MOVED.txt behind, and reports every other outcome (already moved, both exist, skipped, busy) without ever deleting user data.
|
Command legacy-move shows MoveLegacy: a tool that used to keep its global home in ~/.demo-old moves it to ~/.demo on the first run of the new version, leaves MOVED.txt behind, and reports every other outcome (already moved, both exist, skipped, busy) without ever deleting user data. |
|
lookup
command
Command lookup shows how appdir finds the project home: the walk-up from the working folder, the walls that stop it (a repo root, the user's home, a ceiling folder), the real-path rule, nearest-wins in a monorepo, the here-only style, and the ErrNoProject message when nothing is found.
|
Command lookup shows how appdir finds the project home: the walk-up from the working folder, the walls that stop it (a repo root, the user's home, a ceiling folder), the real-path rule, nearest-wins in a monorepo, the here-only style, and the ErrNoProject message when nothing is found. |
|
overrides
command
Command overrides shows every way a user moves folders: --home (WithHome) and <APP>_HOME make one home for everything, <APP>_<KIND>_DIR moves one kind, and user paths expand ~ and ${VAR}.
|
Command overrides shows every way a user moves folders: --home (WithHome) and <APP>_HOME make one home for everything, <APP>_<KIND>_DIR moves one kind, and user paths expand ~ and ${VAR}. |
|
pointers
command
Command pointers shows the home: and db: pointer keys of a project home: a committed config.jsonc (with comments and trailing commas) that moves the project home into a private folder next to the repo, the errors a wrong pointer gives, the one-hop rule, what the dev profile does with both keys, the config files listed under a broken pointer, and an empty local home: that does not clear the committed one.
|
Command pointers shows the home: and db: pointer keys of a project home: a committed config.jsonc (with comments and trailing commas) that moves the project home into a private folder next to the repo, the errors a wrong pointer gives, the one-hop rule, what the dev profile does with both keys, the config files listed under a broken pointer, and an empty local home: that does not clear the committed one. |
|
prod-db-guard
command
Command prod-db-guard shows CheckDB, the guard a tool calls before it opens a database or runs a migration: a dev build refuses the prod databases, opens them read-only with DEMO_ALLOW_PROD=1, and opens its own read-write.
|
Command prod-db-guard shows CheckDB, the guard a tool calls before it opens a database or runs a migration: a dev build refuses the prod databases, opens them read-only with DEMO_ALLOW_PROD=1, and opens its own read-write. |
|
profiles
command
Command profiles shows how appdir picks a profile (flag, env, build), how a build is recognised as a release, how profiles get their own folders and names, and how a tool passes its profile to child processes.
|
Command profiles shows how appdir picks a profile (flag, env, build), how a build is recognised as a release, how profiles get their own folders and names, and how a tool passes its profile to child processes. |
|
project-init
command
Command project-init shows the two write calls that make a home: InitProject (the `lore init` command) and InitHome (`lore init --home X`), what they write into home.jsonc, and what they refuse.
|
Command project-init shows the two write calls that make a home: InitProject (the `lore init` command) and InitHome (`lore init --home X`), what they write into home.jsonc, and what they refuse. |
|
quickstart
command
Command quickstart is the first program a tool writes with appdir: resolve every home with New, read paths with Path, PathIn and Paths, and create a folder only when it is needed with Ensure.
|
Command quickstart is the first program a tool writes with appdir: resolve every home with New, read paths with Path, PathIn and Paths, and create a folder only when it is needed with Ensure. |
|
testing-setup
command
Command testing-setup is a tiny tool written so it can be tested without touching the developer's real homes.
|
Command testing-setup is a tiny tool written so it can be tested without touching the developer's real homes. |
|
worktree
command
Command worktree shows how appdir treats git worktrees and submodules without running git: a linked worktree uses the main checkout's .lore/, a main checkout without one makes the worktree look for its own (with a warning when the worktree has one; silent when neither has), a submodule is its own project, a worktree of a bare repo uses itself, and here-only lookup still uses the main checkout's home.
|
Command worktree shows how appdir treats git worktrees and submodules without running git: a linked worktree uses the main checkout's .lore/, a main checkout without one makes the worktree look for its own (with a warning when the worktree has one; silent when neither has), a submodule is its own project, a worktree of a bare repo uses itself, and here-only lookup still uses the main checkout's home. |
|
internal
|
|
|
flock
Package flock is the minimal OS file lock appdir needs: flock(LOCK_EX|LOCK_NB) on Unix, LockFileEx with LOCKFILE_FAIL_IMMEDIATELY on Windows.
|
Package flock is the minimal OS file lock appdir needs: flock(LOCK_EX|LOCK_NB) on Unix, LockFileEx with LOCKFILE_FAIL_IMMEDIATELY on Windows. |
|
jsonclite
Package jsonclite turns JSONC (JSON with // and /* */ comments and trailing commas) into plain JSON.
|
Package jsonclite turns JSONC (JSON with // and /* */ comments and trailing commas) into plain JSON. |