CLAUDE.md
Repository Overview
This is Profpatsch's personal development repository containing experimental projects and utilities.
NEVER use delegation to subagents unless I explicitely ask for it.
IMPORTANT: Instructions
When the user tells you to use INSTRUCTION, you must ALWAYS run the instructions between :
<GIT_COMMIT> Read the file ./.claude/CLAUDE-git EVEN IF YOU READ IT BEFORE, and create a git commit </GIT_COMMIT>
<USE_RELATIVE_TMP> If you need to write temporary files, put them into ./tmp from where you are currently working. Don’t use /tmp </USE_RELATIVE_TMP>
Active Projects:
The following projects are active projects I’m working on:
./users/Profpatsch/git-blimey :: A git-blame TUI written in go ./users/Profpatsch/timetrack :: A freelancing timetracker for multiple clients
Development Environment
Primary Build System: Nix
- You can build packages with
nix build .#<package>from the repo root. - Legacy:
nix-build ~/kot/Profpatsch -A users.Profpatsch.<package>still works. - When you are running in this repo, you will be inside a
nix-shellthat uses the environment defined in./shell.nix
Installing Services with systemd
For projects that have .service files (systemd user services):
# 1. List packages installed in the user profile
nix profile list
# 1.2.a Upgrade package if installed
nix profile upgrade <package-name>
# 1.2.a Install from flake if not installed
nix profile install .#<package-name>
# 2 only if service does not exist yet, else 3
# 2.1 Copy the service file to systemd user directory
cp ~/kot/Profpatsch/users/Profpatsch/<service>/<service>.service ~/.config/systemd/user/
# 2.2 Reload systemd user daemon
systemctl --user daemon-reload
# 2.3 Enable and start the service
systemctl --user enable <service>.service
systemctl --user start <service>.service
# 3 Restart service if it was already running
systemctl --user restart <service>.service
File Operations Rules
NEVER use cd commands - Always use paths relative to the project in commands instead:
# BAD:
cd /home/philip/depot/users/Profpatsch && git add ./foo/bar
# GOOD:
git add users/Profpatsch/foo/bar
- Use tools like
Read,Edit,Writewith repository-relative paths - For bash commands, specify full paths instead of changing directories
Special workflows
Git Operations → ALWAYS read .claude/CLAUDE-git.md before any git commit
If the user specifies "for ", only commit files related to the given project
(in users/Profpatsch/<project>)
Deploying machines → Machine configs live in ./machines/profpatsch/ and
are wired up as nixosConfigurations in flake.nix. After pushing to
codeberg, deploy with:
# Deploy to any machine (runs nixos-rebuild switch on the remote)
deploy <machine> # e.g. deploy legosi, deploy haku
# Or directly with nixos-rebuild from a local checkout:
sudo nixos-rebuild switch --flake ~/kot/Profpatsch#<machine>
The deploy binary (at users/Profpatsch/deploy/) builds the system closure
locally, copies it to the target via nix copy, then activates it remotely.
NixOS machines: rolery (workstation), legosi, haku, leguin (servers)
Deploying the website (profpatsch.de) → The website is NOT deployed via
nixos-rebuild/deploy. It is served from a git remote on legosi. Push the
canon branch to the legosi-web remote
(ssh://root@legosi:7001/var/www/web.git); a post-receive hook rebuilds and
publishes the site:
git push legosi-web canon
The site sources live in users/Profpatsch/web/ (rendered HTML) and
users/Profpatsch/blog/ (markdown source). Verify a change went live with the
users/Profpatsch/link-check tool:
nix-build . -A users.Profpatsch.link-check
./result/bin/link-check https://profpatsch.de https://sfttime.softwaregardening.org
link-check is a recursive link checker: it crawls the live site, recurses
into in-scope hosts, liveness-checks outbound links, and exits non-zero on dead
links. NOTE: the site host is profpatsch.de (there is no www. record).
Interactive Development with Tmux + GHCi
For rapid iteration with long-running REPL sessions:
# Start tmux session with better defaults (wider, taller, larger scrollback)
tmux new-session -d -s project-repl -x 120 -y 50
tmux set-option -t project-repl history-limit 10000
tmux send-keys -t project-repl "cabal repl <package>" Enter
# NEVER use sleep! Capture large context instead
tmux capture-pane -t project-repl -S -200 -p
# Send commands to REPL
tmux send-keys -t project-repl "COMMAND_HERE" Enter
# Always capture large context for debugging
tmux capture-pane -t project-repl -S -200 -p
# For really long outputs or complete session history
tmux capture-pane -t project-repl -S - -p
# Reload after file changes
tmux send-keys -t project-repl ":reload" Enter
# Kill session when done
tmux kill-session -t project-repl
Tmux Capture Best Practices
Always use large context capture to see full execution flow:
# Default: Capture last 200 lines (shows context and results)
tmux capture-pane -t session -S -200 -p
# For complete session history (debugging complex issues)
tmux capture-pane -t session -S - -p
# Only use small context for quick status checks
tmux capture-pane -t session -S -10 -p
# Save output to file for analysis
tmux capture-pane -t session -S -200 -p > debug-output.txt
# Resize existing session if output is truncated
tmux resize-window -t session -x 120 -y 50
Multi-line Input with tmux send-keys
When sending multi-line inputs to a tmux pane, use the following strategies:
# Option 1: Escape newlines with quotes
tmux send-keys -t project-repl "long command with \
multiple lines \
and continuation" Enter
# Option 2: Use single quoted string
tmux send-keys -t project-repl '
multiline
input
goes here
' Enter
Anti-Pattern: NEVER use sleep commands - they slow down development and don't guarantee operations complete. Use large context capture instead.
mblaze Tools (maildir-varlink)
CRITICAL: When working with mblaze tools (mscan, mshow, mlist, mpick, magrep, etc.):
- ALWAYS read the manpage first using
man <tool>before making assumptions about flags or behavior - Many flags have non-obvious meanings:
mscan -noutputs filenames only, NOT "no pager"- Pager behavior is controlled by
MBLAZE_PAGERenvironment variable
- Default behavior often requires understanding the format strings (e.g.,
mscan -f "%10d %17f %s") - These tools are designed for interactive use but require careful configuration for programmatic use
Example pitfall: Using mscan -n will only output message paths, not summaries. You need either:
-
No
-nflag with default format, OR -
Custom format with
-fflag likemscan -f "%10d %17f %s" -
Use
go run <project>from the toplevel directory to run go projects (they appear in go.work)