1 Commits

Author SHA1 Message Date
d12a1c0797 add README with dotfiles documentation
Nightshift-Task: docs-backfill
Nightshift-Ref: https://github.com/marcus/nightshift
2026-02-22 22:43:56 +01:00
5 changed files with 161 additions and 54 deletions

View File

@@ -9,12 +9,9 @@ set -s set-clipboard on
set -g allow-passthrough on set -g allow-passthrough on
# utf8 / colors # utf8 / colors
set -g default-terminal "tmux-256color" set -g default-terminal "screen-256color"
set -as terminal-overrides ",*:Tc" set -q -g status-utf8 on
set -as terminal-overrides ',*:Smulx=\E[4::%p1%dm' setw -q -g utf8 on
set -as terminal-overrides ',*:Setulc=\E[58::2::%p1%{65536}%/%d::%p1%{256}%/%{255}%&%d::%p1%{255}%&%d%;m'
set -g extended-keys on
set -as terminal-features 'xterm*:extkeys'
# panes retain path # panes retain path
bind '"' split-window -v -c "#{pane_current_path}" bind '"' split-window -v -c "#{pane_current_path}"
@@ -24,16 +21,6 @@ bind % split-window -h -c "#{pane_current_path}"
bind -n S-Left if-shell "[ #{window_index} -ne $(tmux list-windows -F '##{window_index}' | head -1) ]" "previous-window" bind -n S-Left if-shell "[ #{window_index} -ne $(tmux list-windows -F '##{window_index}' | head -1) ]" "previous-window"
bind -n S-Right if-shell "[ #{window_index} -ne $(tmux list-windows -F '##{window_index}' | tail -1) ]" "next-window" bind -n S-Right if-shell "[ #{window_index} -ne $(tmux list-windows -F '##{window_index}' | tail -1) ]" "next-window"
# alt+arrow pane switching
bind -n M-Left select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D
# alt+[ / alt+] pane switching (prev/next)
bind -n M-[ select-pane -t :.-
bind -n M-] select-pane -t :.+
# swap windows left/right with PgUp/PgDn (no wrap) # swap windows left/right with PgUp/PgDn (no wrap)
bind-key -n PgUp if-shell "[ #{window_index} -ne $(tmux list-windows -F '##{window_index}' | head -1) ]" "swap-window -t -1\; select-window -t -1" bind-key -n PgUp if-shell "[ #{window_index} -ne $(tmux list-windows -F '##{window_index}' | head -1) ]" "swap-window -t -1\; select-window -t -1"
bind-key -n PgDn if-shell "[ #{window_index} -ne $(tmux list-windows -F '##{window_index}' | tail -1) ]" "swap-window -t +1\; select-window -t +1" bind-key -n PgDn if-shell "[ #{window_index} -ne $(tmux list-windows -F '##{window_index}' | tail -1) ]" "swap-window -t +1\; select-window -t +1"
@@ -43,7 +30,6 @@ set -s escape-time 10
set -g base-index 1 set -g base-index 1
setw -g pane-base-index 1 setw -g pane-base-index 1
set -g renumber-windows on set -g renumber-windows on
set -g detach-on-destroy off
# Auto-rename windows: directory/process # Auto-rename windows: directory/process
set -g automatic-rename on set -g automatic-rename on
@@ -52,24 +38,21 @@ set -g automatic-rename-format '#{pane_current_command}@#{b:pane_current_path}#{
# Rename window (prefix + R) # Rename window (prefix + R)
bind R command-prompt -I "#{window_name}" "rename-window '%%'" bind R command-prompt -I "#{window_name}" "rename-window '%%'"
# Move window to session (prefix + M), creates session if needed
bind M run-shell 'tmux display-popup -E "tmux-move-to-session #{window_id}"'
# Fuzzy window switcher (prefix + f) # Fuzzy window switcher (prefix + f)
bind f display-popup -h 80% -E "tmux list-windows -F '#{window_index}: #{window_name}' | fzf --reverse --height=100% | cut -d: -f1 | xargs tmux select-window -t" bind f display-popup -E "tmux list-windows -F '#{window_index}: #{window_name}' | fzf --reverse | cut -d: -f1 | xargs tmux select-window -t"
# status bar # status bar
set -g status-style "bg=#262626,fg=#a8a8a8" set -g status-style "bg=colour235,fg=colour248"
set -g status-left "#[fg=#080808,bg=#00af00,bold]#S#[fg=#00af00,bg=#262626,nobold]" set -g status-left "#[fg=colour232,bg=colour34,bold]#S#[fg=colour34,bg=colour235,nobold]"
set -g status-left-length 30 set -g status-left-length 30
set -g status-right "" set -g status-right ""
set -g status-right-length 40 set -g status-right-length 40
# window tabs # window tabs
setw -g window-status-format "#{?#{m:*[13579],#{window_index}},#[fg=#262626]#[bg=#282828]#[fg=#848484] #I #W #[fg=#282828]#[bg=#262626],#[fg=#262626]#[bg=#1e1e1e]#[fg=#747474] #I #W #[fg=#1e1e1e]#[bg=#262626]}" setw -g window-status-format "#{?#{m:*[13579],#{window_index}},#[fg=colour235]#[bg=colour236]#[fg=colour250] #I #W #[fg=colour236]#[bg=colour235],#[fg=colour235]#[bg=colour233]#[fg=colour244] #I #W #[fg=colour233]#[bg=colour235]}"
setw -g window-status-current-format "#[fg=#262626,bg=#00af00]#[fg=#080808,bg=#00af00,bold] #I #W #[fg=#00af00,bg=#262626]" setw -g window-status-current-format "#[fg=colour235,bg=colour34]#[fg=colour232,bg=colour34,bold] #I #W #[fg=colour34,bg=colour235]"
setw -g window-status-separator "" setw -g window-status-separator ""
# pane borders # pane borders
set -g pane-border-style "fg=#444444" set -g pane-border-style "fg=colour238"
set -g pane-active-border-style "fg=#00af00" set -g pane-active-border-style "fg=colour34"

1
.vimrc
View File

@@ -24,6 +24,7 @@ set backupdir=~/.vim/backup//
set nobackup set nobackup
set mouse=a " mouse support set mouse=a " mouse support
noremap <Up> <NOP> noremap <Up> <NOP>
noremap <Down> <NOP> noremap <Down> <NOP>
noremap <Left> <NOP> noremap <Left> <NOP>

13
.zshenv
View File

@@ -1,13 +0,0 @@
# .zshenv — sourced for every zsh invocation (interactive, non-interactive, scripts).
# PATH lives here so cron, ssh host-command, and GUI-launched processes see it.
typeset -U path
path=(
/projects/bin
$HOME/.local/bin
$HOME/.cargo/bin
/usr/local/go/bin
$HOME/go/bin
/opt/homebrew/bin
$path
)

32
.zshrc
View File

@@ -36,10 +36,9 @@ zmodload zsh/stat
# plugin manager # plugin manager
ZINIT_HOME="${XDG_DATA_HOME:-${HOME}}/.zinit.git" ZINIT_HOME="${XDG_DATA_HOME:-${HOME}}/.zinit.git"
[ ! -d "$ZINIT_HOME" ] && mkdir -p "$(dirname $ZINIT_HOME)" [ ! -d $ZINIT_HOME ] && mkdir -p "$(dirname $ZINIT_HOME)"
[ ! -d "$ZINIT_HOME/.git" ] && git clone https://github.com/zdharma-continuum/zinit.git "$ZINIT_HOME" [ ! -d $ZINIT_HOME/.git ] && git clone https://github.com/zdharma-continuum/zinit.git "$ZINIT_HOME"
source "${ZINIT_HOME}/zinit.zsh" source "${ZINIT_HOME}/zinit.zsh"
functions[@zinit-scheduler]="setopt localoptions; set +u; ${functions[@zinit-scheduler]}"
zinit light zsh-users/zsh-autosuggestions zinit light zsh-users/zsh-autosuggestions
zinit light zsh-users/zsh-syntax-highlighting zinit light zsh-users/zsh-syntax-highlighting
@@ -110,7 +109,17 @@ zinit light starship/starship
git --git-dir=$HOME/.dotgit/ --work-tree=$HOME pull --ff-only -q 2>/dev/null git --git-dir=$HOME/.dotgit/ --work-tree=$HOME pull --ff-only -q 2>/dev/null
} &! } &!
# paths live in ~/.zshenv so non-interactive shells (cron, ssh cmd, GUI) see them # paths
typeset -U path
path=(
/projects/bin
$HOME/.local/bin
$HOME/.cargo/bin
/usr/local/go/bin
$HOME/go/bin
/opt/homebrew/bin
$path
)
# fzf (if available) # fzf (if available)
if (( $+commands[fzf] )); then if (( $+commands[fzf] )); then
@@ -140,17 +149,16 @@ fi
alias .g='git --git-dir=$HOME/.dotgit/ --work-tree=$HOME' alias .g='git --git-dir=$HOME/.dotgit/ --work-tree=$HOME'
# aliases: tmux # aliases: tmux
alias t="tmux new-session -A -s auto" alias tmuxr="tmux new-session -A -s auto"
alias tmuxr="tmux new-session -A -s auto" # attach-or-create "auto" alias tmuxn="tmux new-session -A -s auto \; new-window"
alias tmuxn="tmux new-session -A -s auto \; new-window" # same + new window alias tmuxa="tmux new-session -A -s"
alias tmuxa="tmux new-session -A -s" # attach-or-create named
# yazi wrapper (cd to dir on exit) # yazi wrapper (cd to dir on exit)
function y() { function y() {
local tmp="$(mktemp -t "yazi-cwd.XXXXXX")" cwd local tmp="$(mktemp -t "yazi-cwd.XXXXXX")" cwd
command yazi "$@" --cwd-file="$tmp" command yazi "$@" --cwd-file="$tmp"
IFS= read -r -d '' cwd < "$tmp" IFS= read -r -d '' cwd < "$tmp"
[[ "$cwd" != "$PWD" ]] && [[ -d "$cwd" ]] && builtin cd -- "$cwd" [ "$cwd" != "$PWD" ] && [ -d "$cwd" ] && builtin cd -- "$cwd"
rm -f -- "$tmp" rm -f -- "$tmp"
} }
@@ -171,7 +179,7 @@ function clip {
function mkcd { function mkcd {
: "${1:?where?}" : "${1:?where?}"
[[ -e $1 ]] && { echo "file exists"; return 1 } [[ -e $1 ]] && { echo "file exists"; return 1 }
mkdir -p "$1" && cd "$1" mkdir -p $1 && cd $1
} }
function cdtmp { function cdtmp {
@@ -188,13 +196,9 @@ alias dcu='docker compose up --force-recreate --detach'
alias dcd='docker compose down --remove-orphans' alias dcd='docker compose down --remove-orphans'
alias dcl='docker compose logs -f' alias dcl='docker compose logs -f'
# aliases: rsync with sane defaults
alias rsync2='rsync --info=PROGRESS2 --progress --recursive --compress --human-readable --update --times --no-whole-file --itemize-changes --stats --verbose --links --no-perms --chmod=ugo=rwX'
# aliases: misc # aliases: misc
alias c="claude" alias c="claude"
alias ,cd="IS_SANDBOX=1 claude --dangerously-skip-permissions" alias ,cd="IS_SANDBOX=1 claude --dangerously-skip-permissions"
alias wm="workmux"
alias zshreload="exec zsh" alias zshreload="exec zsh"
alias -g LATEST='*(om[1])' # glob: most recently modified alias -g LATEST='*(om[1])' # glob: most recently modified
alias FUNCTION_PRELUDE="setopt LOCAL_OPTIONS PIPE_FAIL XTRACE ERR_RETURN" alias FUNCTION_PRELUDE="setopt LOCAL_OPTIONS PIPE_FAIL XTRACE ERR_RETURN"

132
README.md Normal file
View File

@@ -0,0 +1,132 @@
# dotfiles
Bare-git managed dotfiles for zsh/vim/tmux on Linux and macOS.
## How it works
This repo uses a **bare git repository** at `~/.dotgit` with the work tree set to `$HOME`. This avoids symlinks and lets dotfiles live at their native paths.
The alias that drives everything:
```bash
alias .g='git --git-dir=$HOME/.dotgit/ --work-tree=$HOME'
```
`.g status`, `.g add`, `.g diff`, `.g commit`, `.g push` — same as git, just scoped to the dotfiles repo. Untracked files are hidden by default (`showUntrackedFiles = no` in config).
## Bootstrap on a new machine
```bash
git clone --bare https://gitea.abra.me/svxf/dotfiles.git $HOME/.dotgit
alias .g='git --git-dir=$HOME/.dotgit/ --work-tree=$HOME'
.g checkout
.g config status.showUntrackedFiles no
```
If checkout conflicts with existing files, back them up first:
```bash
.g checkout 2>&1 | grep "^\t" | xargs -I{} mv {} {}.bak
.g checkout
```
On next shell start, zinit will bootstrap itself and install all plugins automatically.
## Tracked files
| File | What it does |
|---|---|
| `.zshrc` | Shell config — plugins, aliases, functions, keybindings, PATH |
| `.vimrc` | Vim config — space-leader, persistent undo, arrow keys disabled |
| `.tmux.conf` | tmux config — mouse, green accent, fzf window switcher, auto-rename |
| `.starship.toml` | Prompt — two-line, git status, docker indicators, command duration |
| `.gitignore_global` | Global ignores — `*~`, `.DS_Store`, `__pycache__`, `.idea`, `.ipynb_checkpoints` |
## Key features
### Zinit plugin stack (`.zshrc`)
- **zsh-autosuggestions** — inline fish-style suggestions
- **zsh-syntax-highlighting** — live command coloring
- **zsh-completions** — extra completion definitions
- **zsh-history-substring-search** — up/down searches from prefix
- **starship** — installed via zinit from GitHub releases
### Async dotfiles pull
On shell start, a background job pulls `--ff-only` from origin once per day (marker at `~/.cache/.dotfiles-pull`). Silent, non-blocking.
### Starship prompt (`.starship.toml`)
Two-line layout:
- **Line 1**: docker container indicator → docker-compose status → git branch/status → (fill) → directory
- **Line 2**: `➤` character (green=ok, red=error)
- **Right**: command duration (>5s) → user@host → time
Custom modules detect `/.dockerenv` for container awareness and parse `docker compose ps` for service status.
### fzf integration (`.zshrc`)
Sources fzf keybindings and completion when available. Default opts: `--height 40% --reverse`.
### Project switcher — `pj` (`.zshrc`)
Fuzzy-finds directories under `/projects` or `~/projects` using fzf. `pj foo` pre-fills the query.
### Yazi wrapper — `y` (`.zshrc`)
Wraps the yazi file manager so the shell `cd`s to wherever you navigated on exit.
### Docker compose aliases (`.zshrc`)
| Alias | Expands to |
|---|---|
| `,dcdu` | `docker compose --profile dev up service_dev --force-recreate --detach` |
| `,dcdd` | `docker compose --profile dev down --remove-orphans` |
| `,dcdl` | `docker compose --profile dev logs -f service_dev` |
| `dcu` | `docker compose up --force-recreate --detach` |
| `dcd` | `docker compose down --remove-orphans` |
| `dcl` | `docker compose logs -f` |
### Tmux aliases (`.zshrc`)
| Alias | What it does |
|---|---|
| `tmuxr` | Attach-or-create session named "auto" |
| `tmuxn` | Same + opens a new window |
| `tmuxa NAME` | Attach-or-create a named session |
### Tmux keybindings (`.tmux.conf`)
- **Shift+Left/Right** — switch windows (no wrap)
- **PgUp/PgDn** — swap window position left/right
- **prefix+f** — fzf fuzzy window switcher
- **prefix+R** — rename window
- Splits retain current path. 1-indexed windows, auto-rename shows `command@directory`.
### Vim (`.vimrc`)
Space as leader. `jk` exits insert mode. Persistent undo in `~/.vim/undo/`. Arrow keys disabled (hjkl only). Mouse enabled. Smart case search. 8-line scroll margin.
### Utility functions (`.zshrc`)
| Function | Purpose |
|---|---|
| `clip` | Pipe stdin to system clipboard via OSC 52 (works over SSH/tmux) |
| `mkcd DIR` | mkdir + cd in one step |
| `cdtmp [label]` | Create and cd into a timestamped temp dir under `~/tmp/` |
### Other aliases (`.zshrc`)
- `c``claude`
- `,cd``claude --dangerously-skip-permissions` (with sandbox flag)
- `zshreload``exec zsh`
- `LATEST` — global alias expanding to `*(om[1])` (most recently modified file)
### Shell options (`.zshrc`)
Extended history (100k lines, shared, deduped). Case-insensitive globbing. Auto-pushd on cd. No flow control (Ctrl-S disabled). Emacs keybindings with Ctrl+X,E / Alt+E for `$EDITOR`.
### Machine-local overrides
`~/.zshrc-extra` is sourced at the end if it exists — for per-machine config that doesn't belong in version control.