xdg

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. ~/.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

AppName is the directory component used under every state root.

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.

const RepoHashLen = 16

Variables

ErrRepoPathRequired is returned when a caller passes an empty repo path.

var ErrRepoPathRequired = errors.New("xdg: repo path is required")

func StateRoot

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).

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/<repo-hash>/ — 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

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

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