move readme to root, update readme and claude.md to reflect current setup

This commit is contained in:
Paul Trowbridge 2026-05-10 03:19:16 -04:00
parent 8931988ec7
commit 226cdd64c6
3 changed files with 190 additions and 203 deletions

191
CLAUDE.md
View File

@ -4,147 +4,120 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Repository Overview ## Repository Overview
This is a personal development environment setup repository containing: Personal Linux development environment setup. Clone and run one script to get a consistent shell and editor across machines.
- Shell scripts for automated installation of development tools
- Dotfiles for bash, vim, tmux, git, psql, and pspg
- The main `setup_env.sh` script deploys dotfiles as symlinks and installs base packages
## Key Commands ## Key Commands
### Environment Setup ### Fresh machine setup
```bash ```bash
# Initial setup - installs packages, plugin managers, and creates symlinks git clone git@gitea.hptrow.me:pt/setup_env.git ~/setup_env
./setup_env.sh cd ~/setup_env && ./setup_env.sh
```
# Individual tool installations `setup_env.sh` installs packages, downloads Neovim, clones plugin managers, deploys all dotfile symlinks, and sets up NvChad.
### Day-to-day sync
```bash
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)
```bash
./install_postgres.sh # PostgreSQL from official apt repository ./install_postgres.sh # PostgreSQL from official apt repository
./install_python3.sh # Latest Python 3 from deadsnakes PPA ./install_python3.sh # Latest Python 3 from deadsnakes PPA
./install_java_dev.sh # SDKMAN for Java development ./install_java_dev.sh # SDKMAN for Java development
./install_neovim.sh # Latest Neovim release, extracted to /opt/
./install_nvchad.sh # NvChad Neovim config
./install_visidata.sh # VisiData for terminal data exploration ./install_visidata.sh # VisiData for terminal data exploration
``` ```
After running `setup_env.sh`, activate plugins: ### After plugin manager install
- **Tmux**: Press `prefix + I` (Ctrl-b + I) to install TPM plugins - **Tmux**: press `Ctrl-b + I` to install TPM plugins
- **Vim**: Run `:PluginInstall` inside vim to install Vundle plugins - **Vim**: run `:PluginInstall` inside vim
### Git Operations
```bash
# Automated commit and push (defined in .bashrc)
vc # git add . && commit with timestamp && push
# Custom git aliases (defined in .gitconfig)
git pushall # Push to all remotes
```
## Architecture ## Architecture
### Dotfile Management System ### Scripts
The repository uses **symlink-based configuration deployment**. When `setup_env.sh` runs:
1. `deploy_configs` symlinks each dotfile in `dotfiles/` to `~/.<filename>` (backing up any existing file)
2. `deploy_bin` symlinks every file in `dotfiles/bin/` to `~/.local/bin/<filename>`
3. This allows version control of configs and user-local scripts while keeping them in their expected locations
All dotfiles are symlinked, not copied. Editing `~/.<file>` directly modifies files in the repository. - `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 latest Neovim binary to `/opt/`. Called by `setup_env.sh`.
- `install_nvchad.sh` — clones nvim config from gitea on fresh install, or `git pull`s if already present. Called by both `setup_env.sh` and `sync.sh`.
- `install_*.sh` — optional installs, run manually per machine.
### Dotfile Management
**Critical Files:** Symlink-based deployment. Editing `~/.<file>` directly edits the repo file. `git status` shows config drift.
- `dotfiles/.bashrc` - Main bash configuration with extensive aliases and functions
- `dotfiles/.bashrc_local` - Machine-specific secrets and credentials (PG, MS connection strings)
- `dotfiles/.bashrc_local_example` - Template for `.bashrc_local`
- `dotfiles/.bashrc_paths` - Machine-specific PATH additions and tool inits
- `dotfiles/.bashrc_paths_example` - Template for `.bashrc_paths`
- `dotfiles/.vimrc` - Vim configuration using Vundle plugin manager
- `dotfiles/.tmux.conf` - Tmux configuration with vim-style pane navigation
- `dotfiles/.gitconfig` - Git configuration with custom log format and vimdiff
- `dotfiles/.psqlrc` - PostgreSQL client configuration
- `dotfiles/.pspgconf` - pspg (PostgreSQL pager) configuration
- `dotfiles/bin/td` - Python CLI for time-tracking markdown todos (see Time tracking section)
### Custom Bash Workflow `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.
The `.bashrc` contains a sophisticated workflow for working with: **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 lua modules
**Database Query Management:** **Gitignored** (machine-specific, auto-bootstrapped from examples):
- `dotfiles/.bashrc_local` — secrets and credentials
- `dotfiles/.bashrc_paths` — PATH additions and tool inits
PostgreSQL workflow: ### Two-repo nvim setup
- `xnspa()` function - Interactive file selector for running PostgreSQL queries through nvim swap files, outputs to VisiData as CSV. Accepts extra psql args (e.g. `xnspa -v var=val`).
- `xnsp` - Select and execute SQL file through fzf with pspg output
- `xns` - Select and execute SQL file through fzf
- `PG` environment variable - psql connection string to database (defined in `.bashrc_local`)
SQL Server workflow: 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.
- `xmspa()` function - Interactive file selector for SQL Server queries through nvim swap files, outputs to VisiData with pipe-delimited format
- `xmsp` - Select SQL file via fzf, execute with sqlcmd, pipe to pspg `dotfiles/nvim/td.lua` and `td_mappings.lua` are deployed as symlinks into `~/.config/nvim/lua/` by `deploy_nvim`. The nvim repo's `mappings.lua` loads them via `require "td_mappings"`. The nvim repo does not track these files — setup_env owns them.
- `xms` - Select SQL file via fzf, execute with sqlcmd
- `MS` environment variable - sqlcmd connection string to SQL Server (defined in `.bashrc_local`) **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.
- `MSC` environment variable - sqlcmd connection string with pipe-delimited output format (defined in `.bashrc_local`)
- `MSW` environment variable - Windows sqlcmd connection (optional, defined in `.bashrc_local`) ## 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: General:
- `ons` - List open nvim files in current directory tree - `ons` — list open nvim swap files in current directory tree
**Git workflow aliases:** ### Git Aliases
- `gs` - git status short format - `gs` — git status short
- `ga` - Interactive git add using fzf for file selection - `ga` — interactive git add via fzf
- `gx` - Interactive git checkout using fzf - `gx` — interactive git checkout via fzf
- `gr` - git reset HEAD - `vc()``git add -u`, commit with timestamp, push
- `gc` - git commit verbose - `gr`, `gc`, `gd`, `gl` — reset, commit, difftool, log
- `gd` - git difftool
- `gl` - Pretty git log with colors
**Todo grep aliases (rg-based):** ### Todo Grep (rg-based)
- `td` - Find unchecked todo items using ripgrep - `td` — find unchecked todos
- `tdp` - Find priority todos (with 🔼 or ⏫) - `tdp` / `tdtp` — priority todos (🔼 / ⏫)
- `tdtp` - Find top priority todos (⏫ only) - `tdo` / `tdop` — open todo in nvim at exact line
- `tdo` - Open todo in nvim at exact line
- `tdop` - Open priority todo in nvim at exact line
**Time tracking (functions wrapping `dotfiles/bin/td`):** ### Time Tracking
- `tstart <tid>` - Start a timer on a task identified by a `^tid-*` block-ref Shell wrappers around `dotfiles/bin/td` (bypasses the `td` rg alias via `command td`):
- `tstop` - Stop the running timer - `tstart` / `tstop` / `treport` / `tweek`
- `treport [filter]` - Show totals per tid, filterable by tid or filename
- `tweek [filter]` - Show this week's time summary
- Wrappers use `command td` to bypass the `td` rg alias. The CLI writes one row per entry to `$TD_LOG` (default `./time.csv`, cwd-scoped).
- Companion nvim integration (in the separate `~/.config/nvim` repo) adds `<leader>ts/tp/tr` keymaps with auto-generated tids.
**Other useful aliases:** Nvim keymaps (via `td_mappings.lua`): `<leader>ts/tp/tr/tw`
- `nv` - Launch Neovim from custom installation path
- `cj` - Navigate to journal directory
- `jr` - Journal sync (pull, commit, push)
- `hc` - hc companies notes sync (pull, push)
### Plugin Managers ### Other Aliases
- **Vim**: Vundle (installed to `~/.vim/bundle/Vundle.vim`) - `cj` — cd to journal
- **Tmux**: TPM - Tmux Plugin Manager (installed to `~/.tmux/plugins/tpm`) - `jr` / `hc` — sync journal / hc notes
- Plugins: tmux-resurrect, jimeh/tmux-themepack
- **Bash**: bash-git-prompt (installed to `~/.bash-git-prompt`)
### Package Dependencies ## Machine-specific Configuration
Base packages installed by `setup_env.sh`:
- tmux, vim, git, pspg, bat, fzf, ripgrep
## Important Conventions `.bashrc` sources two gitignored files:
### Machine-specific configuration - **`.bashrc_local`** — secrets: DB connection strings, passwords, tokens
- **`.bashrc_paths`** — PATH additions: nvim, cargo, nvm, java, etc.
There are two gitignored files for machine-specific configuration, both sourced by `.bashrc`: 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`.
- **`.bashrc_local`** — secrets and credentials: database connection strings, passwords, tokens. Use `dotfiles/.bashrc_local_example` as a template. ## Git Commit Style
- **`.bashrc_paths`** — PATH additions and tool initializations: neovim, cargo, nvm, java, etc. Use `dotfiles/.bashrc_paths_example` as a template.
On a new machine, copy both examples and fill them in: Simple lowercase messages: "add cargo", "visidata", "fix nv alias path"
```bash
cp dotfiles/.bashrc_local_example dotfiles/.bashrc_local
cp dotfiles/.bashrc_paths_example dotfiles/.bashrc_paths
```
When a tool (cargo, nvm, conda, etc.) auto-appends lines to `.bashrc`, `git status` will show the modification — that's your signal to move those lines to `.bashrc_paths` instead.
### Symlink Pattern
When modifying dotfiles, remember they are symlinked. Changes are automatically tracked by git since the actual files are in the repository's `dotfiles/` directory.
### Git Commit Messages
This repository uses simple lowercase commit messages describing the change (e.g., "add cargo", "visidata", "install sdkman").

108
README.md Normal file
View File

@ -0,0 +1,108 @@
# setup_env
Personal Linux development environment. Clone once, run one script, get a consistent shell and editor across machines.
## Fresh machine
```bash
git clone git@gitea.hptrow.me:pt/setup_env.git ~/setup_env
cd ~/setup_env && ./setup_env.sh
```
`setup_env.sh` handles everything in order:
- Installs base packages (tmux, vim, git, fzf, ripgrep, pspg, bat)
- Downloads and installs latest Neovim to `/opt/`
- Clones TPM, Vundle, bash-git-prompt
- Deploys all dotfile symlinks
- Clones and sets up NvChad nvim config from gitea
After install:
- **Tmux**: press `Ctrl-b + I` to install TPM plugins
- **Vim**: run `:PluginInstall` to install Vundle plugins
- Edit `dotfiles/.bashrc_local` with your real credentials (auto-created from example)
- Edit `dotfiles/.bashrc_paths` with PATH additions for tools on this machine (auto-created from example)
## Day-to-day sync
```bash
cd ~/setup_env && ./sync.sh
```
Pulls the latest setup_env and nvim config repos, redeploys all symlinks. Safe to run anytime.
## Optional installs
Run manually on machines that need them:
```bash
./install_postgres.sh # PostgreSQL from official apt repository
./install_python3.sh # Latest Python 3 from deadsnakes PPA
./install_java_dev.sh # SDKMAN for Java development
./install_visidata.sh # VisiData for terminal data exploration
```
## Dotfile deployment
All config files are symlinked, not copied — editing `~/.<file>` edits the repo file directly. `git status` always shows config drift.
| Source | Deployed to | Notes |
|---|---|---|
| `dotfiles/.bashrc` | `~/.bashrc` | Main shell config |
| `dotfiles/.bashrc_local` | `~/.bashrc_local` | Secrets/credentials — gitignored |
| `dotfiles/.bashrc_paths` | `~/.bashrc_paths` | PATH and tool inits — gitignored |
| `dotfiles/.vimrc`, `.gitconfig`, `.tmux.conf`, etc. | `~/<filename>` | Standard dotfiles |
| `dotfiles/bin/*` | `~/.local/bin/<name>` | Executable scripts |
| `dotfiles/nvim/*.lua` | `~/.config/nvim/lua/<name>` | Nvim lua modules |
When a tool appends lines to `.bashrc`, `git status` shows the modification — move those lines to `.bashrc_paths` instead.
## Machine-specific config
Two gitignored files sourced by `.bashrc`, auto-bootstrapped from examples on first run:
- **`.bashrc_local`** — DB connection strings, passwords, tokens
- **`.bashrc_paths`** — PATH additions (nvim, cargo, nvm, java, etc.)
---
## td — markdown todo time tracking
Track time on markdown todos identified by a block-ref `^tid-*`. Data lives in `time.csv` at the vault root.
### Surfaces
| Surface | Location | How to use |
|---|---|---|
| CLI | `bin/td``~/.local/bin/td` | `command td <subcommand>` |
| Shell wrappers | `.bashrc` | `tstart`, `tstop`, `treport`, `tweek` |
| Nvim | `nvim/td.lua` + `nvim/td_mappings.lua` | `<leader>ts/tp/tr/tw` or `:TdStart/Stop/Report/Week` |
### Subcommands
| Command | What it does |
|---|---|
| `td start <tid> [--file PATH] [--desc TEXT]` | Start timer, auto-stops any running entry |
| `td stop` | Close the open entry |
| `td report [filter]` | Total time per tid (filter matches tid or file) |
| `td week [--since DATE]` | Tasks from git log joined with time data |
| `td current` | Print the currently-running tid |
| `td tidgen` | Generate a fresh tid |
### How `td week` works
Scans `git log -p` from cwd, pairs `-`/`+` task-line diffs within each commit by tid:
- `[x]` **done**`- [ ]``- [x]` transition
- `[ ]` **new** — added `- [ ]` line with a fresh tid
- `[+]` **done+new** — created and completed in the same commit
- `[o]` **reopen**`- [x]``- [ ]` transition
### Nvim integration
`<leader>ts` on a `- [ ]` line auto-generates a `^tid-*` block ref if missing, saves the buffer, and starts the timer. `<leader>tp` stops, `<leader>tr` shows a report float, `<leader>tw` shows the week float. Close floats with `q` or `<Esc>`.
### Gotchas
- **`td` alone is aliased to `rg`** for todo-grepping. Use `tweek`, `treport` etc. or `command td` to reach the CLI directly.
- **CSV is cwd-scoped.** Run subcommands from the vault root. The nvim wrapper walks up to find it; shell wrappers trust your cwd.
- **Data-model changes go in `bin/td`.** Shell and nvim surfaces stay thin wrappers.

View File

@ -1,94 +0,0 @@
# dotfiles
Symlink-deployed config. The parent `~/setup_env/setup_env.sh` installs each file here to its destination path — edit the file in this repo, the change goes live.
| Source in this repo | Deployed to | Deployed by |
| --- | --- | --- |
| `.bashrc`, `.vimrc`, `.gitconfig`, `.pspgconf`, `.psqlrc`, `.tmux.conf`, `.bashrc_local` | `~/<filename>` | `deploy_configs` |
| `bin/*` | `~/.local/bin/<name>` | `deploy_bin` |
| `nvim/*.lua` | `~/.config/nvim/lua/<name>.lua` | `deploy_nvim` |
On a fresh machine: clone the `setup_env` repo, then from `~/setup_env/` run:
```bash
./install_neovim.sh
./install_nvchad.sh
./install_python3.sh
./setup_env.sh # creates all the symlinks + installs apt packages
```
After install you still need to add one line to the NvChad-provided `~/.config/nvim/lua/mappings.lua` (it's not tracked here because NvChad owns that file):
```lua
require("td_mappings")
```
Everything else picks up automatically.
---
## td — markdown todo time tracking
Track time on markdown todos identified by an Obsidian block-ref `^tid-*` at the end of the task line. Data lives in `time.csv` at the vault root; reports cross-join time with git history to show what was created vs. completed.
### The three surfaces (one script)
All logic is in `bin/td` — a Python 3 stdlib script. The other surfaces are thin wrappers so the script is reachable from each editing context.
| Surface | Location | Purpose |
| --- | --- | --- |
| Python script | `bin/td``~/.local/bin/td` | Single source of truth. All subcommands. |
| Shell wrappers | `.bashrc` (`tstart` / `tstop` / `treport` / `tweek`) | Bypass the `td` alias (see gotcha). |
| Nvim module | `nvim/td.lua` + `nvim/td_mappings.lua` | `:TdStart` / `:TdStop` / `:TdReport` / `:TdWeek` commands + `<leader>t{s,p,r,w}` keymaps. |
### Data model
`time.csv` at the vault root:
```
started_at, stopped_at, tid, file, description
```
- `tid` — block-ref identifier, format `tid-YYYYMMDD-HHMMSS`, appended as `^tid-...` to the task line in the markdown file
- `started_at` / `stopped_at` — ISO-8601 local timestamps; a running entry has an empty `stopped_at`
- one row per time segment; `td stop` fills in `stopped_at` on the open row
Vault root is discovered by walking up from the current buffer file looking for `time.csv` or `.obsidian/`.
### Subcommands
| Command | What it does |
| --- | --- |
| `td start <tid> [--file PATH] [--desc TEXT]` | Start a timer. Auto-stops any running entry first. If `--file` / `--desc` aren't given, greps the vault for the tid to populate them. |
| `td stop` | Close the open entry. |
| `td report [FILTER]` | Total time per tid (filter matches tid or file substring). |
| `td current` | Print the currently-running tid (or nothing). |
| `td tidgen` | Print a fresh `tid-YYYYMMDD-HHMMSS`. |
| `td week [--since DATE]` | Task create/complete events from `git log -p`, joined with `time.csv`. Default range: since Monday 00:00 of this week. |
### How `td week` works
Scans `git log -p --reverse --no-renames` from cwd, pairs `-`/`+` task-line diffs within each commit by tid, classifies each event:
- `[x]` **done**`- [ ]``- [x]` transition in one commit
- `[ ]` **new** — added `- [ ]` line with a fresh tid
- `[+]` **done+new**`- [x]` added with no prior `- [ ]` for that tid (created and completed in the same commit)
- `[o]` **reopen**`- [x]``- [ ]` transition
Event timestamp is commit time, not toggle time — batched commits share one timestamp. Fine for weekly "what did I get done" reports; not precise enough for hourly auditing.
### Nvim integration
`<leader>ts` / `:TdStart` on a `- [ ]` task line:
1. If the line has no `^tid-*` block ref, auto-generates `tid-YYYYMMDD-HHMMSS`, appends it, saves the buffer.
2. Starts the timer with the file path (relative to vault root) and the task text (minus checkbox + block ref) as description.
Other mappings: `<leader>tp` stop, `<leader>tr` report float, `<leader>tw` week float. `q` or `<Esc>` closes a float.
Known limitation: NvChad defers `mappings.lua` via `vim.schedule`, so `:TdStart` etc. aren't available inside `-c` arguments on headless invocations. Interactive use is fine.
### Gotchas
- **`td` alone is aliased to `rg`** (for the `td` / `tdp` / `tdo` todo-grep family, defined in `.bashrc`). So `td week` runs `rg "\- \[[^(x|~)]\]" week` and errors out. Use `tweek` (shell wrapper that calls `command td week`) or `command td week` directly.
- **CSV is cwd-scoped.** `$TD_LOG` defaults to `./time.csv`, so subcommands must be run from (or under) the vault root. The nvim wrapper handles this by walking up to find the vault root; the shell wrappers trust your cwd.
- **Data-model changes go in `bin/td`.** The shell and nvim surfaces should stay thin — if a new subcommand is useful in nvim too, add it to `bin/td`, then a one-line `tfoo()` wrapper in `.bashrc` and a `M.foo` + mapping in `nvim/td.lua` / `nvim/td_mappings.lua`.