7.9 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Repository Overview
Personal Linux development environment setup. Clone and run one script to get a consistent shell and editor across machines.
Key Commands
Fresh machine setup
git clone git@gitea.hptrow.me:pt/setup_env.git ~/setup_env
cd ~/setup_env && ./setup_env.sh
setup_env.sh installs packages, downloads Neovim, clones plugin managers, deploys all dotfile symlinks, and sets up NvChad.
Day-to-day sync
cd ~/setup_env && ./sync.sh
Pulls setup_env and nvim config repos, redeploys symlinks. Safe to run anytime.
Optional tool installs (run manually per machine)
./install_postgres.sh # PostgreSQL from official apt repository
./install_python3.sh # Latest Python 3 from deadsnakes PPA (includes python3-venv)
./install_node.sh # Node.js via nvm (needed for prettier formatter in nvim)
./install_java_dev.sh # SDKMAN for Java development
./install_visidata.sh # VisiData for terminal data exploration
./reinstall_nvchad.sh # Wipe and reinstall NvChad from scratch
After plugin manager install
- Tmux: press
Ctrl-b + Ito install TPM plugins - Vim: run
:PluginInstallinside vim
Architecture
Scripts
setup_env.sh— fresh machine only. Installs everything in order.sync.sh— day-to-day. Pulls repos and redeploys symlinks. No apt, no sudo._lib.sh— shared deploy functions sourced by both scripts.install_neovim.sh— downloads Neovim v0.11.3 to/opt/, auto-adds to.bashrc_paths. Called bysetup_env.sh.install_nvchad.sh— clones nvim config from gitea on fresh install, orgit pulls if already present. Called by bothsetup_env.shandsync.sh.reinstall_nvchad.sh— wipes all nvim data and re-runsinstall_nvchad.sh. Run manually when nvim is broken.install_*.sh— optional installs, run manually per machine.
Dotfile Management
Symlink-based deployment. Editing ~/.<file> directly edits the repo file. git status shows config drift.
deploy_configs, deploy_bin, and deploy_nvim (in _lib.sh) handle symlinking. create_symlink skips if already correct. migrate_and_link (used for gitignored files) migrates existing real files into the repo, or bootstraps from _example if nothing exists.
Tracked dotfiles (in git):
dotfiles/.bashrc— main shell configdotfiles/.vimrc,.gitconfig,.tmux.conf,.psqlrc,.pspgconfdotfiles/bin/td— time-tracking CLIdotfiles/nvim/td.lua,td_mappings.lua— nvim time-tracking integrationdotfiles/nvim/rename_term.lua— vault-wide find-and-replace with confirmation popup (<leader>rn)dotfiles/nvim/telescope_tasks.lua— vault-wide task pickers (<leader>tlopen tasks,<leader>tLpriority tasks)
Gitignored (machine-specific, auto-bootstrapped from examples):
dotfiles/.bashrc_local— secrets and credentialsdotfiles/.bashrc_paths— PATH additions and tool inits
Two-repo nvim setup
The nvim config lives in a separate repo at git@gitea.hptrow.me:pt/nvchad.git (customize branch), deployed to ~/.config/nvim. install_nvchad.sh manages it.
Ownership boundary — important:
- nvchad repo owns
mappings.lua— this is the keymap entry point. It lives in~/.config/nvim/lua/mappings.luaand is tracked by the nvchad git repo. Edit it there, push from~/.config/nvim. - setup_env owns feature modules —
td.lua,td_mappings.lua,rename_term.lua,telescope_tasks.lua. These are deployed as symlinks into~/.config/nvim/lua/bydeploy_nvim. The nvchad repo does NOT track them.mappings.lualoads them viarequire.
Do NOT put mappings.lua in dotfiles/nvim/. It will conflict with the nvchad repo's tracked copy on every git pull during sync, producing .backup files on all machines.
Dependency: deploy_nvim must run after install_nvchad.sh has created ~/.config/nvim/lua/. On a fresh machine this is handled automatically by setup_env.sh ordering. On existing machines sync.sh handles it.
Custom Bash Workflow
Database Query Management
PostgreSQL (env var $PG defined in .bashrc_local):
xnspa([args])— fzf-select an open nvim swap file, run with$PG, output CSV to VisiData. Accepts extra psql args.xnsp— same, output to pspgxns— same, raw output
SQL Server (env vars $MS, $MSC, $MSW in .bashrc_local):
xmspa()— fzf-select swap file, run with$MSC, pipe-delimited output to VisiDataxmsp— same, output to pspgxms— same, raw output
General:
ons— list open nvim swap files in current directory tree
Git Aliases
gs— git status shortga— interactive git add via fzfgx— interactive git checkout via fzfvc()—git add -u, commit with timestamp, pushgr,gc,gd,gl— reset, commit, difftool, log
Todo Grep (rg-based)
td— find unchecked todostdp/tdtp— priority todos (🔼 / ⏫)tdo/tdop— open todo in nvim at exact line
Time Tracking
Shell wrappers around dotfiles/bin/td (bypasses the td rg alias via command td):
tstart/tstop/treport/tweek
Nvim keymaps (via td_mappings.lua): <leader>ts/tp/tr/tw
Other Aliases
cj— cd to journaljr/hc— sync journal / hc notes
How Neovim understands code (tree-sitter vs LSP)
Two parallel systems, different jobs:
tree-sitter: file → parser (.so grammar) → syntax tree → highlighting / aerial outline / folding
LSP: file → language server process → diagnostics / completion / hover / go-to-def
Tree-sitter is a structural parser. It turns text into a tree of named syntax nodes
(create_table, create_function, etc.) but knows nothing about semantics — it can't
tell you a column doesn't exist. Each language has a community-maintained grammar that
gets compiled to a .so file. nvim-treesitter manages downloading and compiling these.
Plugins like aerial ship .scm query files that pattern-match against node types in that
tree to extract symbols.
LSP (Language Server Protocol) is a separate process (installed via Mason) that understands the language semantically — it can autocomplete column names, validate queries against a real schema, etc. It has no idea tree-sitter exists.
Aerial can use either backend. If an LSP is attached to the file, aerial can ask it for document symbols and skip tree-sitter entirely.
Where things break: if a .scm query references a node type (e.g. create_policy)
that the installed grammar .so doesn't define, tree-sitter rejects the whole query at
parse time — before it even looks at your file. Fix: override the query in
~/.config/nvim/queries/<lang>/ so your version wins over the plugin's copy.
Treesitter Query Overrides
dotfiles/nvim/queries/ contains local query overrides that shadow plugin-provided queries in ~/.config/nvim/queries/. They are deployed as symlinks by deploy_nvim in _lib.sh (alongside lua/ and lua/plugins/).
Current overrides:
queries/sql/aerial.scm— aerial.nvim's upstream SQL query includes(create_policy ...), which is not a valid node type in the installed tree-sitter-sql grammar and causes aerial to crash on SQL files. This file is a full replacement withcreate_policycommented out. If a futureTSUpdate sqladds the node, remove the comment and retire the override.
Machine-specific Configuration
.bashrc sources two gitignored files:
.bashrc_local— secrets: DB connection strings, passwords, tokens.bashrc_paths— PATH additions: nvim, cargo, nvm, java, etc.
Both are auto-bootstrapped from _example files on first setup_env.sh run. When a tool appends to .bashrc, git status shows it — move those lines to .bashrc_paths.
Git Commit Style
Simple lowercase messages: "add cargo", "visidata", "fix nv alias path"