From 1fd92fcaf3aadea1e9509f859340f57100218c41 Mon Sep 17 00:00:00 2001 From: "Simen A. W. Olsen" Date: Sat, 21 Mar 2026 13:49:10 +0100 Subject: refactor: consolidate dotfiles into declarative Nix modules - Remove nvim git submodule, use flake input instead - Inline all shell configurations into Nix modules - Remove legacy bootstrap.sh and macos/macos script - Add NixOS system configuration support - Update documentation with platform-specific setup - Add claude-code to macOS Homebrew - Remove stow-based dotfile management approach --- modules/darwin/homebrew.nix | 1 + modules/home/default.nix | 14 +++- modules/home/ghostty.nix | 11 ++- modules/home/starship.nix | 4 +- modules/home/tmux.nix | 28 +++++++- modules/home/zsh.nix | 159 ++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 204 insertions(+), 13 deletions(-) (limited to 'modules') diff --git a/modules/darwin/homebrew.nix b/modules/darwin/homebrew.nix index 3c3f469..9ac9816 100644 --- a/modules/darwin/homebrew.nix +++ b/modules/darwin/homebrew.nix @@ -134,6 +134,7 @@ "tldr" "starship" "gh" + "claude-code" # HTTP and web servers "caddy" diff --git a/modules/home/default.nix b/modules/home/default.nix index bf1900d..1ff1c19 100644 --- a/modules/home/default.nix +++ b/modules/home/default.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: +{ pkgs, lib, ... }: { imports = [ @@ -16,9 +16,17 @@ stateVersion = "24.11"; }; + home.packages = with pkgs; [ + nodejs_22 + ]; + # Let home-manager manage itself programs.home-manager.enable = true; - # Link neovim config (managed as a git submodule) - home.file.".config/nvim".source = ../../nvim/.config/nvim; + # Install Claude Code via npm on Linux (on macOS it's managed by Homebrew) + home.activation.installClaudeCode = lib.mkIf (!pkgs.stdenv.isDarwin) + (lib.hm.dag.entryAfter [ "writeBoundary" ] '' + export PATH="${pkgs.nodejs_22}/bin:$PATH" + npm install -g @anthropic-ai/claude-code 2>/dev/null || true + ''); } diff --git a/modules/home/ghostty.nix b/modules/home/ghostty.nix index e854c6e..1d42944 100644 --- a/modules/home/ghostty.nix +++ b/modules/home/ghostty.nix @@ -1,5 +1,14 @@ { ... }: { - home.file.".config/ghostty/config".source = ../../ghostty/.config/ghostty/config; + home.file.".config/ghostty/config".text = '' + theme = tokyonight-storm + + window-padding-x = 12 + window-padding-y = 12 + window-decoration = true + window-theme = "dark" + window-inherit-working-directory = true + window-inherit-font-size = true + ''; } diff --git a/modules/home/starship.nix b/modules/home/starship.nix index 05a70f3..4f3cb61 100644 --- a/modules/home/starship.nix +++ b/modules/home/starship.nix @@ -1,5 +1,7 @@ { ... }: { - home.file.".config/starship.toml".source = ../../starship/.config/starship.toml; + programs.starship = { + enable = true; + }; } diff --git a/modules/home/tmux.nix b/modules/home/tmux.nix index 473ce5e..fa01331 100644 --- a/modules/home/tmux.nix +++ b/modules/home/tmux.nix @@ -1,5 +1,31 @@ { ... }: { - home.file.".tmux.conf".source = ../../tmux/.tmux.conf; + home.file.".tmux.conf".text = '' + unbind r + bind r source-file ~/.tmux.conf \; display-message "Config reloaded" + + set -g default-terminal "tmux-256color" + set -ag terminal-overrides ",xterm-256color:RGB" + + set -g prefix C-s + + set -g mouse on + + set -g base-index 1 + set-window-option -g mode-keys vi + + bind g new-window -c "#{pane_current_path}" -n "lazygit" lazygit + + bind f run-shell "tmux neww twm" + bind F run-shell "tmux neww twm -l" + bind s run-shell "tmux neww twm -e" # i rebind the original `s` to `S` so I can still use it + bind e run-shell "tmux switch -t $TWM_DEFAULT" # i set TWM_DEFAULT in my shellrc, just a session that is always available as a scratch area + + set -g @plugin 'tmux-plugins/tpm' + set -g @plugin 'christoomey/vim-tmux-navigator' + set -g @plugin 'tmux-plugins/tmux-sensible' + + run '~/.tmux/plugins/tpm/tpm' + ''; } diff --git a/modules/home/zsh.nix b/modules/home/zsh.nix index b7dc9c1..1b24133 100644 --- a/modules/home/zsh.nix +++ b/modules/home/zsh.nix @@ -1,12 +1,157 @@ -{ ... }: +{ pkgs, ... }: { home.file = { - ".zshenv".source = ../../zsh/.zshenv; - ".hushlogin".source = ../../zsh/.hushlogin; - ".config/zsh/.zshrc".source = ../../zsh/.config/zsh/.zshrc; - ".config/zsh/aliases".source = ../../zsh/.config/zsh/aliases; - ".config/zsh/path".source = ../../zsh/.config/zsh/path; - ".config/zsh/extras".source = ../../zsh/.config/zsh/extras; + ".zshenv".text = '' + ##!/bin/zsh + # + # .zshenv - Zsh environment file, loaded always. + # + + # Set ZDOTDIR if you want to re-home Zsh. + export XDG_CONFIG_HOME=''${XDG_CONFIG_HOME:-$HOME/.config} + export XDG_DATA_HOME=''${XDG_DATA_HOME:-$HOME/.local/share} + export XDG_CACHE_HOME=''${XDG_CACHE_HOME:-$HOME/.cache} + export ZDOTDIR=''${ZDOTDIR:-$XDG_CONFIG_HOME/zsh} + + # Ensure path arrays do not contain duplicates. + typeset -gU path fpath + + # Set the list of directories that zsh searches for commands. + path=( + $HOME/{,s}bin(N) + $HOME/.local/{,s}bin(N) + /opt/{homebrew,local}/{,s}bin(N) + /usr/local/{,s}bin(N) + $path + ) + '' + ( + if pkgs.stdenv.isDarwin then '' + eval "$(/opt/homebrew/bin/brew shellenv)" + '' else "" + ) + '' + [ -f "$HOME/.cargo/env" ] && . "$HOME/.cargo/env" + ''; + + ".hushlogin".text = ""; + + ".config/zsh/.zshrc".text = '' + #!/bin/bash + # ^----- get shellcheck hints based on bash + # https://github.com/koalaman/shellcheck/issues/809 + # shellcheck disable=SC1090 # sourced filenames with variables + + # Download Znap, if it's not there yet. + [[ -r ~/.zsh_repos/znap/znap.zsh ]] || + git clone --depth 1 -- \ + https://github.com/marlonrichert/zsh-snap.git ~/.zsh_repos/znap + source ~/.zsh_repos/znap/znap.zsh # Start Znap + + znap eval starship 'starship init zsh --print-full-init' + znap prompt + + znap source marlonrichert/zsh-autocomplete + znap source zsh-users/zsh-autosuggestions + znap source jeffreytse/zsh-vi-mode + + for file in ~/.config/zsh/{aliases,path,extras}; do + if [[ -r "$file" ]] && [[ -f "$file" ]]; then + # shellcheck source=/dev/null + source "$file" + fi + done + + eval "$(twm --print-zsh-completion)" + + bindkey '^I^I' autosuggest-accept + ''; + + ".config/zsh/aliases".text = '' + # Git aliases + alias git-unpushed='git log --branches --not --remotes --no-walk --decorate --oneline' + alias gb='git checkout -b' + alias gfr='git fetch upstream && git rebase upstream/main' + alias git-undo='git reset --soft HEAD~1' + alias git-clean-branches="git for-each-ref --format '%(refname:short)' refs/heads | grep -v 'master\|main' | xargs git branch -D" + alias :q='exit' + alias ls='ls --color' + alias tailscale='/Applications/Tailscale.app/Contents/MacOS/Tailscale' + + # Generic / Random / Utility + alias rg="rg --hidden --glob '!.git' --glob '!node_modules'" + alias r='cd $REPOS/github.com/' + alias c='clear' + alias afk='pmset displaysleepnow' + alias dl="cd ~/Downloads" + alias l='ls -l' + alias todo='nt' + alias tasks="open 'obsidian://open?file=-%20Oppgaver'" + alias todos="mt ~/ghq/github.com/simenandre/notes/" + alias today="open 'obsidian://advanced-uri?daily=true'" + alias tre="tree -I '.git|node_modules'" + alias timeliste="open 'https://tripletex.no/execute/updateHourlist?contextId=11208568'" + alias t="open 'https://tripletex.no/execute/updateHourlist?contextId=11208568'" + alias fork-cleaner="fork-cleaner --token $(cat ~/.secrets/github-token)" + alias vi="nvim" + alias vim="nvim" + alias v="nvim" + + alias dump-issues="getBjerkIssues > ~/Downloads/issues-$(date -I).json" + ''; + + ".config/zsh/path".text = '' + #!/bin/bash + + # Add directories to the PATH and prevent to add the same directory multiple times upon shell reload. + add_to_path() { + if [[ -d "$1" ]] && [[ ":$PATH:" != *":$1:"* ]]; then + export PATH="$1:$PATH" + fi + } + + GOPATH="$HOME/go" + + add_to_path "$HOME/.volta/bin" + add_to_path "$GOPATH/bin" + add_to_path "/Library/Frameworks/Firebird.framework/Resources/bin" + add_to_path "/opt/homebrew/opt/libpq/bin" + ''; + + ".config/zsh/extras".text = '' + NOTES_DIR=$HOME/ghq/github.com/simenandre/notes/ + function note() { + if [ $1 ]; then + FILE=$NOTES_DIR/$(date +%Y-%m-%d).md + + if [ $2 ]; then + FILE=$2 + fi + + echo $1 >> $FILE + fi + } + + function nt() { + if [ $1 ]; then + CONTENT="- [ ] $1" + note $CONTENT $2 + fi + } + + function getBjerkIssues() { + gh issue list --repo bjerkio/internal \ + --search "-label:backlog -label:kind/system" \ + --json title,body,url,createdAt,assignees,number,labels,comments \ + --jq 'map({url, createdAt, title, labels: [.labels[].name], assignees: [.assignees[].login], body, number: "#\(.number)", comments: .comments | map({ body: .body, createdAt: .createdAt })})' + } + + function g() { + export GOOGLE_CLOUD_PROJECT="sokkel-sandbox" + export GOOGLE_CLOUD_LOCATION="europe-north1" + export GOOGLE_GENAI_USE_VERTEXAI=true + + gemini + } + ''; }; } -- cgit v1.2.3