dstow

package module
v0.6.2 Latest Latest
Warning

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

Go to latest
Published: Jul 26, 2026 License: GPL-3.0 Imports: 1 Imported by: 0

README

dstow

Deploy dotfiles and configuration as symlinks, from packages in repos.

dstow links the files in a package into a target directory (your $HOME by default), the same way GNU Stow does — but it remembers what it deployed, works across many repos at once, names things by a stable qualified identity, and never depends on the directory you happen to be standing in.

  • Repos are where packages come from — a local directory, or a remote clone (github:owner/name).
  • Packages are the top-level directories inside a repo. Each package is a tree of files to link into the target.
  • Targets are where the links go. The default is $HOME; any level of config can point elsewhere.
github:yourname/dotfiles::starship
└─┬──┘ └───────┬───────┘  └──┬───┘
  │            │             package
  │            coordinate
  scheme

That fully-qualified name (FQN) is a package's stable identity. You rarely type the whole thing — any unambiguous suffix works (starship, dotfiles::starship, yourname/dotfiles::starship), and the working directory never changes what a command does.


The manual is in the binary

dstow's documentation ships inside dstow. Once it is installed, you never need this page or any website:

dstow manual                     # the whole manual, navigable as commands
dstow manual concepts            # the model: repos, packages, targets, states
dstow manual configuration keys  # every config key and where it is legal
dstow manual reference           # exit codes, environment, file locations
dstow <command> --help           # any command's help

dstow manual <TAB> walks the tree. A command's manual page is the source of its --help, so the two can never disagree.

This README covers only what you need before you have dstow: how to install it, and what the first five minutes look like.


Install

Add dstow's bootstrap to your shell rc. It puts ~/.local/bin on PATH and installs dstow only if it is missing — when dstow is already present the snippet is silent, invisible, and offline (the installer is never even fetched):

dstow snippet rc >> ~/.bashrc      # or ~/.zshrc, ~/.profile, …

The emitted snippet is plain POSIX sh — dstow never edits your rc files, it only prints the text to stdout for you to redirect. On a fresh machine where dstow is not yet installed, run the snippet's install line directly:

curl -fsSL https://raw.githubusercontent.com/rocne/dstow/main/install.sh | sh -s --

The installer drops dstow into ~/.local/bin. It is idempotent: run against a machine that already has dstow, it prints one status line and exits 0.

Installer flags: --force reinstalls even when present; --version vX.Y.Z ensures exactly that release — already installed at that version it exits 0, otherwise it installs it (no implied force). The install dir is tunable (--install-dir, DSTOW_INSTALL_DIR, XDG_BIN_HOME); ~/.local/bin is the default the snippet relies on. Downloads are checksum-verified always, and cosign-verified when cosign is available. See install.sh --help for the full surface.

Add installer args right after the --, such as --force or --version <version>:

curl -fsSL https://raw.githubusercontent.com/rocne/dstow/main/install.sh | sh -s -- --force
Linux packages (dnf / apt)

Signed .rpm and .deb packages are published to a hosted repo, so dstow installs by name and stays current through your normal system upgrades. Add the repo once, then install:

# Fedora, RHEL, CentOS Stream, openSUSE, … (dnf/yum)
curl -1sLf 'https://dl.cloudsmith.io/public/rocne/releases/setup.rpm.sh' | sudo -E bash
sudo dnf install dstow
# Debian, Ubuntu, … (apt)
curl -1sLf 'https://dl.cloudsmith.io/public/rocne/releases/setup.deb.sh' | sudo -E bash
sudo apt install dstow

The setup script drops a repo file into /etc/yum.repos.d (or /etc/apt/sources.list.d) and imports the repo's index-signing key, so dnf upgrade / apt upgrade pick up new dstow releases automatically. The packages themselves are GPG-signed by a separate key (fingerprint 64894FE3…), whose public half is attached to every GitHub release as dstow-signing-key.asc if you want to verify a download by hand.

With Go

If you have a Go toolchain, install straight from source — the binary reports the module version it was built from:

go install github.com/rocne/dstow/cmd/dstow@latest
Shell completion
dstow completion bash        # also: zsh, fish, powershell

See dstow completion --help for where to place the output for your shell.


Quickstart

# 1. Register a repo of packages (clones a remote; registers a local path in place).
dstow repo add github:rocne/dotfiles
dstow repo add ~/my-dotfiles

# 2. See what you have (reads config only — never touches disk).
dstow list                       # your repos
dstow list dotfiles              # a repo's packages

# 3. Deploy. Name packages, or a whole repo, by any unambiguous suffix.
dstow stow zsh git tmux
dstow stow dotfiles              # a repo: all of its packages

# 4. Check reality.
dstow status                     # what is actually deployed, live

# 5. Later: refresh, or remove.
dstow restow zsh                 # unstow then stow (pick up changes)
dstow unstow tmux                # remove tmux's links

First run on a machine that already has live config files? Adopt them into the package as you stow, so nothing is destroyed:

dstow stow --all --adopt

Coming from GNU Stow? dstow reads your existing .stowrc and .stow-local-ignore — you do not have to rewrite anything to start:

dstow manual configuration stow-compat

Where to go next

Everything else lives in the binary:

You want Run
The model: repos, packages, targets, the ledger dstow manual concepts
What occupied or orphaned means dstow manual concepts states
The naming grammar and suffix matching dstow manual concepts naming
Every command dstow manual commands, or dstow <cmd> --help
Config keys and where each is legal dstow manual configuration keys
Ignore patterns dstow manual configuration ignores
Migrating from GNU Stow dstow manual configuration stow-compat
Theming, slots, color values dstow manual theming
Writing a hook, and its context contract dstow manual hooks
Exit codes, environment variables, file locations dstow manual reference

The manual's source is the docs/ directory of this repository, if you would rather read it here — but the copy in your binary is the one that matches your version.

Contributing

Design and requirements documents, architecture decision records, and agent workflow docs live in dev/.

License

dstow is licensed under the GNU General Public License v3.0. Copyright (c) 2026 Rocne Scribner.

Documentation

Overview

Package dstow carries repo-root artifacts that must ride inside the binary. The go:embed directive cannot reach above a package's directory, so files vendored at the repo root (snippet.sh, owned by release-ci per D26) are embedded here and consumed by the internal packages.

Index

Constants

This section is empty.

Variables

View Source
var Manual embed.FS

Manual is the tracked docs/ tree, embedded whole — the source the hidden `manual` command group mirrors (§2.1's carve-out): directories become groups, markdown files become leaves, and every node prints its own file. The tree is the single source of truth, so the `all:` prefix is required — without it go:embed silently drops files beginning with "." or "_", and a dropped file is a topic that exists in the repo and nowhere in the binary.

View Source
var RCSnippet string

RCSnippet is the vendored snippet.sh, verbatim — the canonical rc bootstrap (DESIGN §9.1 B1 as amended: authored in release-ci, vendored beside install.sh, embedded so `dstow snippet rc` emits the one canonical file with zero transcription drift (B2)).

Functions

This section is empty.

Types

This section is empty.

Directories

Path Synopsis
cmd
dstow command
Command dstow is a dotfiles manager built on the gostow engine.
Command dstow is a dotfiles manager built on the gostow engine.
internal
cli
Package cli is dstow's command-line front end and composition root (A1/A2): the only consumer that turns the app core's data into a cobra CLI, renders results through the ui printer, and maps typed domain errors to exit codes.
Package cli is dstow's command-line front end and composition root (A1/A2): the only consumer that turns the app core's data into a cobra CLI, renders results through the ui printer, and maps typed domain errors to exit codes.
config
Package config is dstow's four-level configuration chain (DESIGN.md §3 + A8): the legality matrix over the one key vocabulary, use-time path expansion, warnings-as-data for unknown and misplaced keys, stow compatibility (stowrc discovery, slotting, option mapping, and supplement diffing via gostow's public stowrc package), content-sniff routing for a renamed rc, DSTOW_PATH parsing, and the metadata-location accessor.
Package config is dstow's four-level configuration chain (DESIGN.md §3 + A8): the legality matrix over the one key vocabulary, use-time path expansion, warnings-as-data for unknown and misplaced keys, stow compatibility (stowrc discovery, slotting, option mapping, and supplement diffing via gostow's public stowrc package), content-sniff routing for a renamed rc, DSTOW_PATH parsing, and the metadata-location accessor.
engine
Package engine is dstow's one seam onto gostow (DESIGN.md A14–A16): the deployment verbs as per-package operations, and the two introspections (Expected, Owner) the ledger and maintenance verbs compose with.
Package engine is dstow's one seam onto gostow (DESIGN.md A14–A16): the deployment verbs as per-package operations, and the two introspections (Expected, Owner) the ledger and maintenance verbs compose with.
git
Package git is dstow's version-control seam: system git behind a port (DESIGN.md A17).
Package git is dstow's version-control seam: system git behind a port (DESIGN.md A17).
hooks
Package hooks is dstow's hook engine (DESIGN.md §5 + A11): discovery of the eight per-event executables in one hooks directory, the DSTOW_HOOK_* environment contract each hook runs under, direct exec of a hook, and the per-invocation sequencer that fires the nested/LIFO lifecycle (REQUIREMENTS §9.1) once per scope.
Package hooks is dstow's hook engine (DESIGN.md §5 + A11): discovery of the eight per-event executables in one hooks directory, the DSTOW_HOOK_* environment contract each hook runs under, direct exec of a hook, and the per-invocation sequencer that fires the nested/LIFO lifecycle (REQUIREMENTS §9.1) once per scope.
ignore
Package ignore is dstow's native ignore matcher (DESIGN.md A15 + §3.4): the additive ignore chain's gitignore-glob entries, compiled once and matched per package against package-root-relative paths.
Package ignore is dstow's native ignore matcher (DESIGN.md A15 + §3.4): the additive ignore chain's gitignore-glob entries, compiled once and matched per package against package-root-relative paths.
ledger
Package ledger is dstow's current-state index of the symlinks it believes exist (DESIGN.md §6 + A10; ADR 0001).
Package ledger is dstow's current-state index of the symlinks it believes exist (DESIGN.md §6 + A10; ADR 0001).
name
Package name is dstow's pure naming grammar: parse and format fully qualified names (FQNs), percent-encode and -decode coordinate segments, resolve segment-boundary suffix matches, force package-kind with a leading "::", and classify an operand as a path or a name expression.
Package name is dstow's pure naming grammar: parse and format fully qualified names (FQNs), percent-encode and -decode coordinate segments, resolve segment-boundary suffix matches, force package-kind with a leading "::", and classify an operand as a path or a name expression.
ops
Package ops is dstow's application core (A13): the verbs as deep modules composing config, repo, engine, ledger, and hooks into structured results.
Package ops is dstow's application core (A13): the verbs as deep modules composing config, repo, engine, ledger, and hooks into structured results.
repo
Package repo is dstow's repo set (DESIGN.md A9): the repo registry (read/write with the same temp-file+fsync+rename discipline as the ledger), the source grammar and its internal github/local schemes, the managed-clone directory layout (A19), package enumeration (M2/M3), and name resolution over the set through the pure name package.
Package repo is dstow's repo set (DESIGN.md A9): the repo registry (read/write with the same temp-file+fsync+rename discipline as the ledger), the source grammar and its internal github/local schemes, the managed-clone directory layout (A19), package enumeration (M2/M3), and name resolution over the set through the pure name package.
ui
Package ui is dstow's sole owner of the terminal streams (A4): every other module returns data — diagnostics included — and ui alone renders it.
Package ui is dstow's sole owner of the terminal streams (A4): every other module returns data — diagnostics included — and ui alone renders it.

Jump to

Keyboard shortcuts

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