---
title: internal/xdg
description: Go API reference for the xdg package.
---
# xdg
```go
import "github.com/jbcom/radioactive-ralph/internal/xdg"
```
Package xdg resolves Ralph's state directory and per\-repo workspace paths.
State lives at one of these, in priority order:
1. $RALPH\_STATE\_DIR \(explicit override, for tests\)
2. $XDG\_STATE\_HOME/radioactive\-ralph \(Linux, WSL\)
3. \~/Library/Application Support/radioactive\-ralph \(macOS\)
4. %LOCALAPPDATA%/radioactive\-ralph \(Windows; only a few subcommands are supported on Windows natively, the full daemon expects POSIX\)
5. \~/.local/state/radioactive\-ralph \(POSIX default when XDG unset\)
Within that root, every per\-repo workspace is keyed by a stable hash of the absolute path of the operator's repo. Cloning the same repo to two locations yields two independent workspaces, which is the correct behavior because Ralph's worktrees and event log are tied to the source tree on disk, not to the remote URL.
## Index
- [Constants](<#constants>)
- [Variables](<#variables>)
- [func StateRoot\(\) \(string, error\)](<#StateRoot>)
- [type Paths](<#Paths>)
- [func Resolve\(repoPath string\) \(Paths, error\)](<#Resolve>)
- [func \(p Paths\) Ensure\(\) error](<#Paths.Ensure>)
## Constants
AppName is the directory component used under every state root.
```go
const AppName = "radioactive-ralph"
```
RepoHashLen is the number of hex characters of the repo hash we retain. Sixteen gives us a 64\-bit keyspace which is plenty for per\-machine collision avoidance and keeps paths readable.
```go
const RepoHashLen = 16
```
## Variables
ErrRepoPathRequired is returned when a caller passes an empty repo path.
```go
var ErrRepoPathRequired = errors.New("xdg: repo path is required")
```
## func [StateRoot]()
```go
func StateRoot() (string, error)
```
StateRoot returns the absolute path to the Ralph state root for this machine and user, respecting overrides. Honors the $RALPH\_STATE\_DIR override for tests.
Exported so packages outside the xdg package \(the plan subcommand, the MCP server bootstrap, etc.\) can land the plandag SQLite file and other global artifacts under the same root as per\-repo workspaces.
## type [Paths]()
Paths holds the resolved set of directories for a single repo workspace. All fields are absolute paths; no field is created on disk until a caller asks \(Paths is a plan, not a mkdir\).
```go
type Paths struct {
// StateRoot is the root of all Ralph workspaces on this machine, e.g.
// ~/.local/state/radioactive-ralph or
// ~/Library/Application Support/radioactive-ralph.
StateRoot string
// Workspace is StateRoot// — the per-repo tree.
Workspace string
// MirrorGit is Workspace/mirror.git — the bare mirror clone.
MirrorGit string
// Shallow is Workspace/shallow — shallow-clone checkout for variants
// that use shallow isolation.
Shallow string
// Worktrees is Workspace/worktrees — parent dir for per-variant worktrees.
Worktrees string
// Sessions is Workspace/sessions — per-variant socket/PID/log/alive files.
Sessions string
// Logs is Workspace/logs — per-variant rolling log files.
Logs string
// StateDB is Workspace/state.db — the SQLite event log path.
StateDB string
// Inventory is Workspace/inventory.json — capability discovery snapshot.
Inventory string
}
```
### func [Resolve]()
```go
func Resolve(repoPath string) (Paths, error)
```
Resolve returns the full Paths plan for the given absolute repo path.
The repo path is converted to its absolute, symlink\-resolved form before hashing so that \~/work and /Users/me/work produce the same hash.
### func \(Paths\) [Ensure]()
```go
func (p Paths) Ensure() error
```
Ensure creates the workspace subdirectories on disk with 0o700 mode.
Called by \`radioactive\_ralph init\` after the pre\-flight wizard. Idempotent — safe to run multiple times. Does NOT create mirror.git or state.db; those are the responsibility of the workspace manager and the db package.
Generated by [gomarkdoc]()