go-homedir
A tiny, cgo-free Go library for detecting and expanding the current user's home directory across platforms.
Repository Health
Technical Analysis
go-homedir is a small, dependency-free Go library that solves one specific problem: reliably locating the current user’s home directory without invoking cgo. The built-in os/user package requires cgo on Darwin, which breaks cross-compilation for Go programs that target other platforms from a single build machine. go-homedir sidesteps this by checking the HOME environment variable first, then falling back to platform-specific lookups (dscl on macOS, getent passwd on Linux/Unix, environment variables on Windows) and finally a shell fallback, all without a single cgo call.
The library exposes just two functions in practice: Dir() to get the home directory and Expand() to resolve a leading ~ in a path to that directory. Results are cached in memory by default (toggleable via DisableCache) and can be cleared with Reset() for testing. It has no external dependencies and is widely vendored as a transitive dependency across the Go ecosystem, including HashiCorp tooling.
What You Get
Dir()— returns the current user’s home directory using OS-appropriate detection, without cgoExpand()— resolves a leading~(or~/...) in a path string to the full home directory pathDisableCacheandReset()— control and clear the in-memory home-directory cache, useful for tests that swap$HOME- Cross-platform fallbacks — layered detection order (env var, OS-native lookup, shell fallback) for Unix-like systems, Windows, and Plan 9
Common Use Cases
- CLI tools that accept file paths with a leading
~and need to expand them the way a shell would - Cross-compiled Go binaries (e.g. built for multiple OS/arch targets from one CI machine) that can’t rely on cgo-dependent
os/user - Locating a user-level config or cache directory (e.g.
~/.myapp/config.yaml) without shelling out manually - Testing code that depends on the home directory, using
DisableCache/Reset()to simulate a different$HOMEper test case
Under The Hood
Architecture
The package is a single flat file exposing two public functions, Dir() and Expand(), plus a Reset() helper, backed by an unexported OS-dispatch layer (dirUnix, dirWindows) that branches at runtime on runtime.GOOS rather than using Go build tags, and a package-level result cache guarded by a sync.RWMutex (cacheLock) that can be disabled via the exported DisableCache flag. Dir() checks the cache, then dispatches to dirUnix() (tries $HOME, falls back to dscl on Darwin or getent passwd elsewhere, then a final shell fallback of sh -c "cd && pwd") or dirWindows() (checks $HOME, then $USERPROFILE, then $HOMEDRIVE+$HOMEPATH), caching whatever it finds. Expand() layers ~-prefix path logic on top of Dir(). There is no further layering — it’s a flat, single-purpose utility module, so any change to the core cache/dispatch logic in Dir() ripples directly into every consumer of Expand() and the package itself.
Tech Stack
Pure Go standard library, no external dependencies — go.mod declares only the module path with no require entries. It uses os, os/exec (to shell out to dscl/getent/sh), path/filepath, runtime, strconv, strings, sync, bytes, and errors. There’s no build system beyond go build/go test, no ORM, web framework, or database involved — this is a general-purpose library meant to be imported by other Go programs, not a standalone deployable.
Code Quality
A single test file (homedir_test.go) provides a benchmark (BenchmarkDir) and table-driven-style tests (TestDir, TestExpand) covering the core happy paths plus one error case (an ambiguous ~foo/foo expansion). Testing relies solely on the standard testing package — no assertion library, no mocking. Error handling is explicit and idiomatic (errors.New, propagated returns) rather than swallowed, and naming follows conventional Go style (exported Dir/Expand/Reset, unexported dirUnix/dirWindows). Coverage is present but narrow: the Darwin dscl and Windows-specific code paths aren’t exercised outside whichever OS the tests happen to run on, and no linter or CI configuration is visible in the repository.
What Makes It Unique
go-homedir doesn’t introduce a novel algorithm — home-directory detection is a well-understood problem — but its specific value is enabling fully cgo-free cross-compilation: the standard library’s os/user package requires cgo on Darwin, which breaks single-machine cross-compilation for Go binaries targeting multiple platforms. go-homedir reimplements just enough of that lookup logic (environment variables, dscl/getent shell-outs, shell fallback) to avoid the cgo dependency entirely, which is why it became a widely vendored transitive dependency in cross-compiled Go tooling.
Used by 5 apps in this directory
Cog
AI Development · Devops · Developer Tools
An open-source CLI that packages machine learning models into standard, production-ready Docker containers — no Dockerfile wrangling, no CUDA version hell.
infracost
Devops · Developer Tools
Infracost shows cloud cost estimates for Terraform, CloudFormation, and AWS CDK before you deploy — in your terminal, editor, AI coding agent, and pull requests.
MinIO
File Storage
High-performance, S3-compatible object storage built for AI/ML and analytics workloads — run it anywhere from a laptop to a petabyte-scale cluster.
Netdata
Monitoring · Devops
Real-time per-second metrics, ML-powered anomaly detection, and zero-config observability for any infrastructure.
Okteto
Devops · Developer Tools
Develop applications directly inside your Kubernetes cluster with real-time file sync and instant hot-reload — no more docker build/redeploy cycles.