docs: establish domain model, MVI spec, and environment reference

Capture the design work for the NixOS migration before any implementation:

- .claude/CONTEXT.md: domain glossary (Host, Module, Skeleton, Auto-loader,
  Enable convention, unstable/stable overlay)
- .claude/adr/0001-sops-nix-for-secrets.md: secrets tooling decision
- .claude/spec/laptop-mvi.md: frozen minimum-viable-install spec for neogaia

- reference/: read-only snapshot of the current CachyOS configs (secrets and
  state excluded), plus ENVIRONMENT.md profiling the live environment to guide
  replication
This commit is contained in:
2026-07-18 00:54:25 -04:00
parent 42491d3dd0
commit d5b67947f9
91 changed files with 3409 additions and 0 deletions

View File

@@ -0,0 +1,196 @@
# This is terribly complicated
# It's because:
# 1. bun run has to have dynamic completions
# 2. there are global options
# 3. bun {install add remove} gets special options
# 4. I don't know how to write fish completions well
# Contributions very welcome!!
function __fish__get_bun_bins
string split ' ' (bun getcompletes b)
end
function __fish__get_bun_scripts
set -lx SHELL bash
set -lx MAX_DESCRIPTION_LEN 40
string trim (string split '\n' (string split '\t' (bun getcompletes z)))
end
function __fish__get_bun_packages
if test (commandline -ct) != ""
set -lx SHELL fish
string split ' ' (bun getcompletes a (commandline -ct))
end
end
function __history_completions
set -l tokens (commandline --current-process --tokenize)
history --prefix (commandline) | string replace -r \^$tokens[1]\\s\* "" | string replace -r \^$tokens[2]\\s\* "" | string split ' '
end
function __fish__get_bun_bun_js_files
string split ' ' (bun getcompletes j)
end
set -l bun_install_boolean_flags yarn production optional development no-save dry-run force no-cache silent verbose global
set -l bun_install_boolean_flags_descriptions "Write a yarn.lock file (yarn v1)" "Don't install devDependencies" "Add dependency to optionalDependencies" "Add dependency to devDependencies" "Don't update package.json or save a lockfile" "Don't install anything" "Always request the latest versions from the registry & reinstall all dependencies" "Ignore manifest cache entirely" "Don't output anything" "Excessively verbose logging" "Use global folder"
set -l bun_builtin_cmds_without_run dev create help bun upgrade discord install remove add update init pm x repl
set -l bun_builtin_cmds_accepting_flags create help bun upgrade discord run init link unlink pm x update
function __bun_complete_bins_scripts --inherit-variable bun_builtin_cmds_without_run -d "Emit bun completions for bins and scripts"
# Do nothing if we already have a builtin subcommand,
# or any subcommand other than "run".
if __fish_seen_subcommand_from $bun_builtin_cmds_without_run
or not __fish_use_subcommand && not __fish_seen_subcommand_from run
return
end
# Do we already have a bin or script subcommand?
set -l bins (__fish__get_bun_bins)
if __fish_seen_subcommand_from $bins
return
end
# Scripts have descriptions appended with a tab separator.
# Strip off descriptions for the purposes of subcommand testing.
set -l scripts (__fish__get_bun_scripts)
if __fish_seen_subcommand_from (string split \t -f 1 -- $scripts)
return
end
# Emit scripts.
for script in $scripts
echo $script
end
# Emit binaries and JS files (but only if we're doing `bun run`).
if __fish_seen_subcommand_from run
for bin in $bins
echo "$bin"\t"package bin"
end
for file in (__fish__get_bun_bun_js_files)
echo "$file"\t"Bun.js"
end
end
end
# Clear existing completions
complete -e -c bun
# Dynamically emit scripts and binaries
complete -c bun -f -a "(__bun_complete_bins_scripts)"
# Complete flags if we have no subcommand or a flag-friendly one.
set -l flag_applies "__fish_use_subcommand; or __fish_seen_subcommand_from $bun_builtin_cmds_accepting_flags"
complete -c bun \
-n $flag_applies --no-files -s 'u' -l 'origin' -r -d 'Server URL. Rewrites import paths'
complete -c bun \
-n $flag_applies --no-files -s 'p' -l 'port' -r -d 'Port number to start server from'
complete -c bun \
-n $flag_applies --no-files -s 'd' -l 'define' -r -d 'Substitute K:V while parsing, e.g. --define process.env.NODE_ENV:\"development\"'
complete -c bun \
-n $flag_applies --no-files -s 'e' -l 'external' -r -d 'Exclude module from transpilation (can use * wildcards). ex: -e react'
complete -c bun \
-n $flag_applies --no-files -l 'use' -r -d 'Use a framework (ex: next)'
complete -c bun \
-n $flag_applies --no-files -l 'hot' -r -d 'Enable hot reloading in Bun\'s JavaScript runtime'
# Complete dev and create as first subcommand.
complete -c bun \
-n "__fish_use_subcommand" -a 'dev' -d 'Start dev server'
complete -c bun \
-n "__fish_use_subcommand" -a 'create' -f -d 'Create a new project from a template'
# Complete "next" and "react" if we've seen "create".
complete -c bun \
-n "__fish_seen_subcommand_from create" -a 'next' -d 'new Next.js project'
complete -c bun \
-n "__fish_seen_subcommand_from create" -a 'react' -d 'new React project'
# Complete "upgrade" as first subcommand.
complete -c bun \
-n "__fish_use_subcommand" -a 'upgrade' -d 'Upgrade bun to the latest version' -x
# Complete "-h/--help" unconditionally.
complete -c bun \
-s "h" -l "help" -d 'See all commands and flags' -x
# Complete "-v/--version" if we have no subcommand.
complete -c bun \
-n "not __fish_use_subcommand" -l "version" -s "v" -d 'Bun\'s version' -x
# Complete additional subcommands.
complete -c bun \
-n "__fish_use_subcommand" -a 'discord' -d 'Open bun\'s Discord server' -x
complete -c bun \
-n "__fish_use_subcommand" -a 'bun' -d 'Generate a new bundle'
complete -c bun \
-n "__fish_seen_subcommand_from bun" -F -d 'Bundle this'
complete -c bun \
-n "__fish_seen_subcommand_from create; and __fish_seen_subcommand_from react next" -F -d "Create in directory"
complete -c bun \
-n "__fish_use_subcommand" -a 'init' -F -d 'Start an empty Bun project'
complete -c bun \
-n "__fish_use_subcommand" -a 'install' -f -d 'Install packages from package.json'
complete -c bun \
-n "__fish_use_subcommand" -a 'add' -F -d 'Add a package to package.json'
complete -c bun \
-n "__fish_use_subcommand" -a 'remove' -F -d 'Remove a package from package.json'
for i in (seq (count $bun_install_boolean_flags))
complete -c bun \
-n "__fish_seen_subcommand_from install add remove update" -l "$bun_install_boolean_flags[$i]" -d "$bun_install_boolean_flags_descriptions[$i]"
end
complete -c bun \
-n "__fish_seen_subcommand_from install add remove update" -l 'cwd' -d 'Change working directory'
complete -c bun \
-n "__fish_seen_subcommand_from install add remove update" -l 'cache-dir' -d 'Choose a cache directory (default: $HOME/.bun/install/cache)'
complete -c bun \
-n "__fish_seen_subcommand_from add" -d 'Popular' -a '(__fish__get_bun_packages)'
complete -c bun \
-n "__fish_seen_subcommand_from add" -d 'History' -a '(__history_completions)'
complete -c bun \
-n "__fish_seen_subcommand_from pm; and not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts) cache;" -a 'bin ls cache hash hash-print hash-string' -f
complete -c bun \
-n "__fish_seen_subcommand_from pm; and __fish_seen_subcommand_from cache; and not __fish_seen_subcommand_from (__fish__get_bun_bins) (__fish__get_bun_scripts);" -a 'rm' -f
# Add built-in subcommands with descriptions.
complete -c bun -n "__fish_use_subcommand" -a "create" -f -d "Create a new project from a template"
complete -c bun -n "__fish_use_subcommand" -a "build bun" --require-parameter -F -d "Transpile and bundle one or more files"
complete -c bun -n "__fish_use_subcommand" -a "upgrade" -d "Upgrade Bun"
complete -c bun -n "__fish_use_subcommand" -a "run" -d "Run a script or package binary"
complete -c bun -n "__fish_use_subcommand" -a "install" -d "Install dependencies from package.json" -f
complete -c bun -n "__fish_use_subcommand" -a "remove" -d "Remove a dependency from package.json" -f
complete -c bun -n "__fish_use_subcommand" -a "add" -d "Add a dependency to package.json" -f
complete -c bun -n "__fish_use_subcommand" -a "init" -d "Initialize a Bun project in this directory" -f
complete -c bun -n "__fish_use_subcommand" -a "link" -d "Register or link a local npm package" -f
complete -c bun -n "__fish_use_subcommand" -a "unlink" -d "Unregister a local npm package" -f
complete -c bun -n "__fish_use_subcommand" -a "pm" -d "Additional package management utilities" -f
complete -c bun -n "__fish_use_subcommand" -a "x" -d "Execute a package binary, installing if needed" -f
complete -c bun -n "__fish_use_subcommand" -a "outdated" -d "Display the latest versions of outdated dependencies" -f
complete -c bun -n "__fish_use_subcommand" -a "update" -d "Update dependencies to their latest versions" -f
complete -c bun -n "__fish_use_subcommand" -a "publish" -d "Publish your package from local to npm" -f
complete -c bun -n "__fish_use_subcommand" -a "repl" -d "Start a REPL session with Bun" -f
complete -c bun -n "__fish_seen_subcommand_from repl" -s "e" -l "eval" -r -d "Evaluate argument as a script, then exit" -f
complete -c bun -n "__fish_seen_subcommand_from repl" -s "p" -l "print" -r -d "Evaluate argument as a script, print the result, then exit" -f
complete -c bun -n "__fish_seen_subcommand_from repl" -s "r" -l "preload" -r -d "Import a module before other modules are loaded"
complete -c bun -n "__fish_seen_subcommand_from repl" -l "smol" -d "Use less memory, but run garbage collection more often" -f
complete -c bun -n "__fish_seen_subcommand_from repl" -s "c" -l "config" -r -d "Specify path to Bun config file"
complete -c bun -n "__fish_seen_subcommand_from repl" -l "cwd" -r -d "Absolute path to resolve files & entry points from"
complete -c bun -n "__fish_seen_subcommand_from repl" -l "env-file" -r -d "Load environment variables from the specified file(s)"
complete -c bun -n "__fish_seen_subcommand_from repl" -l "no-env-file" -d "Disable automatic loading of .env files" -f

View File

@@ -0,0 +1,34 @@
function __dot_custom_subcommands
echo init
echo help
path basename $HOME/.config/dot/commands/*.fish 2>/dev/null | path change-extension ''
for d in $HOME/.config/dot/commands/*/
test -d $d; or continue
set -l name (path basename $d)
test -f $d$name.fish; or continue
echo $name
end
end
complete -c dot -n __fish_use_subcommand -a "(__dot_custom_subcommands)"
# --- dot install ---
complete -c dot -n "__fish_seen_subcommand_from install; and not __fish_seen_argument -l restore" -l restore -d "reinstall every package from the saved list"
complete -c dot -n "__fish_seen_subcommand_from install; and not __fish_seen_argument -l no-sync" -l no-sync -d "skip the pacman -Sy database refresh"
complete -c dot -n "__fish_seen_subcommand_from install; and not __fish_seen_argument -l restore" -f -a "(__fish_print_pacman_packages)"
# --- dot setup ---
complete -c dot -n "__fish_seen_subcommand_from setup; and not __fish_seen_subcommand_from folders help" -f -a folders -d "bring the 8 standard XDG user directories under the short-name convention"
complete -c dot -n "__fish_seen_subcommand_from setup; and not __fish_seen_subcommand_from folders help" -f -a help -d "show usage"
complete -c dot -n "__fish_seen_subcommand_from setup; and __fish_seen_subcommand_from folders" -f -a help -d "show usage"
# --- dot kde ---
complete -c dot -n "__fish_seen_subcommand_from kde; and not __fish_seen_subcommand_from apply diff save help" -f -a apply -d "push manifest entries onto the live system"
complete -c dot -n "__fish_seen_subcommand_from kde; and not __fish_seen_subcommand_from apply diff save help" -f -a diff -d "scan for settings whose live value differs from its default"
complete -c dot -n "__fish_seen_subcommand_from kde; and not __fish_seen_subcommand_from apply diff save help" -f -a save -d "write live KDE settings into the manifest"
complete -c dot -n "__fish_seen_subcommand_from kde; and not __fish_seen_subcommand_from apply diff save help" -f -a help -d "show usage"
complete -c dot -n "__fish_seen_subcommand_from kde; and __fish_seen_subcommand_from apply diff save" -f -a help -d "show usage"
# Sourced live from the schema mapping table (real .kcfg files), not a
# hardcoded list -- same helper kde.py's own save/refresh logic builds from.
complete -c dot -n "__fish_seen_subcommand_from kde; and __fish_seen_subcommand_from save" -f -a "(python3 $HOME/.config/dot/commands/kde/kde.py complete 2>/dev/null)"

View File

@@ -0,0 +1,2 @@
complete --command fishtape --short v --long version --description "Print version"
complete --command fishtape --short h --long help --description "Print help"

View File

@@ -0,0 +1,4 @@
alias cp='cp -v'
alias vi=nvim
alias vim=nvim
alias tmx='tmux new-session -A -s'

View File

@@ -0,0 +1,4 @@
set -gx EDITOR nvim
set -x ANDROID_HOME $HOME/Android/Sdk
fish_add_path $ANDROID_HOME/platform-tools
fish_add_path $ANDROID_HOME/tools/bin

View File

@@ -0,0 +1 @@
source "$HOME/.cargo/env.fish"

View File

@@ -0,0 +1,17 @@
source /usr/share/cachyos-fish-config/cachyos-config.fish
set -gx EDITOR nvim
set -gx VISUAL nvim
# overwrite greeting
# potentially disabling fastfetch
#function fish_greeting
# # smth smth
#end
# bun
set --export BUN_INSTALL "$HOME/.bun"
set --export PATH $BUN_INSTALL/bin $PATH
# Pi
fish_add_path "/home/alexion/.local/opt/node-v24.18.0-linux-x64/bin"

View File

@@ -0,0 +1 @@
jorgebucaran/fishtape

View File

@@ -0,0 +1,130 @@
function dot --wraps=git --description 'Manage dotfiles via a bare repo checked out over $HOME'
set -l dotfiles_dir $HOME/.dotfiles
if test "$argv[1]" = init
set -e argv[1]
__dot_init $dotfiles_dir $argv
return $status
end
if test "$argv[1]" = help
__dot_help
return $status
end
set -l commands_dir $HOME/.config/dot/commands
set -l command_file $commands_dir/$argv[1].fish
set -l nested_command_file $commands_dir/$argv[1]/$argv[1].fish
if test -n "$argv[1]"
if test -f "$command_file"
source $command_file
_dot_$argv[1] $argv[2..-1]
return $status
else if test -f "$nested_command_file"
source $nested_command_file
_dot_$argv[1] $argv[2..-1]
return $status
end
end
git --git-dir=$dotfiles_dir --work-tree=$HOME $argv
end
# Kept inline (not a separate autoloaded function file) because this is the
# only subcommand that must work before the dotfiles repo has been cloned.
function __dot_init
set -l dotfiles_dir $argv[1]
set -e argv[1]
argparse 'url=' -- $argv
or return 1
set -l url $_flag_url
test -n "$url"; or set url ssh://gitea@git.alexion.dev:2022/alexion/dotfiles.git
if test -e $dotfiles_dir
echo "dot init: $dotfiles_dir already exists, refusing to re-initialize" >&2
return 1
end
git clone --bare $url $dotfiles_dir
or begin
echo "dot init: failed to clone $url" >&2
return 1
end
git --git-dir=$dotfiles_dir config status.showUntrackedFiles no
set -l checkout_output (git --git-dir=$dotfiles_dir --work-tree=$HOME checkout 2>&1)
set -l checkout_status $status
if test $checkout_status -ne 0
set -l conflicts
set -l in_block 0
for line in $checkout_output
if test $in_block -eq 1
if string match -rq '^\s' -- $line
set -a conflicts (string trim -- $line)
continue
else
set in_block 0
end
end
string match -q '*would be overwritten by checkout:*' -- $line
and set in_block 1
end
if test (count $conflicts) -eq 0
echo "dot init: checkout failed and no recoverable conflicts were found:" >&2
printf '%s\n' $checkout_output >&2
return 1
end
set -l backup_dir $HOME/.dotfiles-backup/(date +%Y%m%dT%H%M%S)
for f in $conflicts
mkdir -p (path dirname $backup_dir/$f)
mv $HOME/$f $backup_dir/$f
echo "dot init: backed up ~/$f to $backup_dir/$f"
end
git --git-dir=$dotfiles_dir --work-tree=$HOME checkout
or begin
echo "dot init: checkout still failing after backing up conflicts, aborting" >&2
return 1
end
end
echo "dot init: bootstrapped $dotfiles_dir from $url"
end
# The custom-subcommand glob is duplicated (not shared with
# completions/dot.fish) because fish only autoloads a function from a file
# named after that function; a shared helper would go undefined if `dot help`
# ran in a completion context before `dot` itself had ever been sourced.
function __dot_help
echo "dot: manage dotfiles via a bare repo checked out over \$HOME
Commands:
init bootstrap the dotfiles repo on a new machine
help show this message"
for f in $HOME/.config/dot/commands/*.fish
test -e $f; or continue
echo " "(path basename $f | path change-extension '')
end
for d in $HOME/.config/dot/commands/*/
test -d $d; or continue
set -l name (path basename $d)
test -f $d$name.fish; or continue
echo " $name"
end
echo "
Run 'dot <command> help' for flags on a specific command.
Any other command is passed through to git (dot status, dot add, dot commit, dot push, ...)."
end

View File

@@ -0,0 +1,116 @@
function fishtape --description "Test scripts, functions, and plugins in Fish"
switch "$argv"
case -v --version
echo "fishtape, version 3.0.1"
case "" -h --help
echo "Usage: fishtape <files ...> Run test files"
echo "Options:"
echo " -v or --version Print version"
echo " -h or --help Print this help message"
case \*
set --local files (realpath $argv)
for file in $files
if test ! -f $file
echo "fishtape: Invalid file or file not found: \"$file\"" >&2
return 1
end
end
set --local operators -{n,z,b,c,d,e,f,g,G,k,L,O,p,r,s,S,t,u,w,x}
set --local expectations \
"a non-zero length string" \
"a zero length string" \
"a block device" \
"a character device" \
"a directory" \
"an existing file" \
"a regular file" \
"a file with the set-group-ID bit set" \
"a file with same group ID as the current user" \
"a file with the sticky bit set" \
"a symbolic link" \
"a file owned by the current user" \
"a named pipe" \
"a file marked as readable" \
"a file of size greater than zero" \
"a socket" \
"a terminal tty file descriptor" \
"a file with the set-user-ID bit set" \
"a file marked as writable" \
"a file marked as executable"
set --universal _fishtape_test_number 0
set --universal _fishtape_test_passed 0
set --universal _fishtape_test_failed 0
function @echo
echo "# $argv"
end
function @test --argument-names name --inherit-variable operators --inherit-variable expectations
set --erase argv[1]
set --query argv[2] || set --append argv ""
set _fishtape_test_number (math $_fishtape_test_number + 1)
if test $argv
set _fishtape_test_passed (math $_fishtape_test_passed + 1)
echo "ok $_fishtape_test_number $name"
else
if test $argv[1] = "!"
set operator "! "
set expected "not "
set --erase argv[1]
end
if set --query argv[3]
set operator "$operator"$argv[2]
set expected (string escape -- $argv[3])
set actual (string escape -- $argv[1])
else
set operator "$operator"$argv[1]
set expected "$expected"$expectations[(contains --index -- $argv[1] $operators)]
set actual (string escape -- $argv[2])
end
set _fishtape_test_failed (math $_fishtape_test_failed + 1)
status print-stack-trace |
string replace --filter --regex -- "\s+called on line (\d+) of file (.+)" '$2:$1' |
read --local at
echo "not ok $_fishtape_test_number $name"
echo " ---"
echo " operator: $operator"
echo " expected: $expected"
echo " actual: $actual"
echo " at: $at"
echo " ..."
end
end
echo TAP version 13
for file in $files
fish --init-command=(functions @echo | string collect) --init-command=(functions @test | string collect) $file
end
echo
echo "1..$_fishtape_test_number"
echo "# pass $_fishtape_test_passed"
test $_fishtape_test_failed -eq 0 &&
echo "# ok" ||
echo "# fail $_fishtape_test_failed"
functions --erase @echo @test
set --local failed $_fishtape_test_failed
set --erase _fishtape_test_number
set --erase _fishtape_test_passed
set --erase _fishtape_test_failed
test $failed -eq 0
end
end