setup_env/dotfiles
2026-05-10 02:12:15 -04:00
..
bin add td week subcommand, nvim centralization, and README 2026-04-24 17:25:06 -04:00
nvim add td week subcommand, nvim centralization, and README 2026-04-24 17:25:06 -04:00
.bashrc add .bashrc_paths for machine-specific PATH and tool inits 2026-05-10 02:12:15 -04:00
.bashrc_local_example move machine-specific config out of bashrc into bashrc_local_example 2026-05-10 01:51:28 -04:00
.bashrc_paths_example add .bashrc_paths for machine-specific PATH and tool inits 2026-05-10 02:12:15 -04:00
.gitconfig merge local additions and incorporate remote improvements 2026-05-10 01:36:30 -04:00
.pspgconf install neovim script 2024-11-05 19:42:26 -05:00
.psqlrc updates 2026-01-07 09:39:19 -05:00
.tmux.conf initial 2024-10-29 20:11:58 -04:00
.vimrc initial 2024-10-29 20:11:58 -04:00
README.md add td week subcommand, nvim centralization, and README 2026-04-24 17:25:06 -04:00

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:

./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):

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.