setup_env/CLAUDE.md

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 + I to install TPM plugins
  • Vim: run :PluginInstall inside 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 by setup_env.sh.
  • install_nvchad.sh — clones nvim config from gitea on fresh install, or git pulls if already present. Called by both setup_env.sh and sync.sh.
  • reinstall_nvchad.sh — wipes all nvim data and re-runs install_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 config
  • dotfiles/.vimrc, .gitconfig, .tmux.conf, .psqlrc, .pspgconf
  • dotfiles/bin/td — time-tracking CLI
  • dotfiles/nvim/td.lua, td_mappings.lua — nvim time-tracking integration
  • dotfiles/nvim/rename_term.lua — vault-wide find-and-replace with confirmation popup (<leader>rn)
  • dotfiles/nvim/telescope_tasks.lua — vault-wide task pickers (<leader>tl open tasks, <leader>tL priority tasks)

Gitignored (machine-specific, auto-bootstrapped from examples):

  • dotfiles/.bashrc_local — secrets and credentials
  • dotfiles/.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.lua and is tracked by the nvchad git repo. Edit it there, push from ~/.config/nvim.
  • setup_env owns feature modulestd.lua, td_mappings.lua, rename_term.lua, telescope_tasks.lua. These are deployed as symlinks into ~/.config/nvim/lua/ by deploy_nvim. The nvchad repo does NOT track them. mappings.lua loads them via require.

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 pspg
  • xns — 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 VisiData
  • xmsp — same, output to pspg
  • xms — same, raw output

General:

  • ons — list open nvim swap files in current directory tree

Git Aliases

  • gs — git status short
  • ga — interactive git add via fzf
  • gx — interactive git checkout via fzf
  • vc()git add -u, commit with timestamp, push
  • gr, gc, gd, gl — reset, commit, difftool, log

Todo Grep (rg-based)

  • td — find unchecked todos
  • tdp / 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 journal
  • jr / 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 with create_policy commented out. If a future TSUpdate sql adds 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"