Tool that lets sessions log problems with the Claude Code setup for a later analysis

Collection of my personal dotfiles.
To install the majority of the dotfiles, use the Terminal GUI by starting "./dotfiles.py". There the specific dotfiles can be selected for installation. This will however will not install software and system wide configurations. When launching for the first time, it will download the required dependencies automatically. The dependencies used are listed in ./requirements.txt.
These dotfiles should also work on Windows, but requires some manual steps.
winget install Python Git.Git zig.zig ajeetdsouza.zoxide junegunn.fzf OpenJS.NodeJS Starship.Starship
winget install Neovide.Neovide SomePythonThings.WingetUIStore 7zip.7zip GitHub.cli
To uninstall the dotfiles, use the Terminal GUI by starting "./dotfiles.py" and just remove the dotfiles that were installed. This will revert the changes made by the dotfiles and leave the system in the same state as before the installation. Since it does not install software, it will not remove any software as well. ./config.json contains the configuration of theses dotfiles, it is required to correctly uninstall the dotfiles.
gw is a local helper script in this repo for git worktree workflows.
gw new -b <branch>: create a new worktree and new branch (from HEAD by default)gw new -b <branch> --from <ref>: create from another base refgw move: move the currently checked out branch into a new worktreegw ls / gw ls --json: list worktreesgw cd: pick and switch to a worktreegw rm: remove a worktreegw prune: prune stale worktree metadatagw doctor: validate worktree setup and healthCommon non-interactive flags:
--yes: auto-confirm destructive/interactive actions--no-prompt: fail instead of prompting--path / --index: explicit target selection for gw rm / gw cdFor shell wrappers, gw emits:
GW_CD_TARGET=<path>
Wrappers should only parse this machine-readable line for auto-cd.
Run:
./scripts/test-gw.sh
Software I use regularly. The software on this list is available on linux, but some is also compatible with windows.
See device_specific for device specific configurations and notes for my personal devices.
To set environment variables for a user on X11, write them to ~/.profile with the following format:
export VAR=value
This will not work for wayland with gnome. write them to ~/.config/environment.d/envvars.conf with the following format:
VAR=value
When using flatpak apps, just add the environment variables via Flatseal.
For Firefox (and I think Thunderbird), set the following environment variables for wayland support:
MOZ_USE_XINPUT2=1
MOZ_ENABLE_WAYLAND=1
For neovide, set the following environment variables:
NEOVIDE_MULTIGRID=true
For development of GObject Introspection based libraries, set the following environment variables (maybe use ~/.local/lib...?):
GI_TYPELIB_PATH=/usr/local/lib/girepository-1.0
For flutter development, set the following environment variables to not use Chrome (flatpak webbrowsers are as far as I know not supported):
CHROME_EXECUTABLE=brave
Maybe also set if using pyopengl (works on my intel integrated gpu):
PYOPENGL_PLATFORM=osmesa
I no longer use Awesome WM, but on very old systems it still works better than gnome. The configuration is not exactly finished (especially the app picker), but it works. It requres following software (some is optional): nm-applet, Jonaburg's picom, light-locker (with lightdm), unclutter, copyq, mate-volume-control-status-icon, blueman-applet, touchegg, polkit-gnome-authentication-agent-1, acpi Maybe some more, but I don't remember.
hooks/register.ts 47 lines1import type { Register } from 'claude-code'
2
3const TOOL = 'mcp__setup-notes__note'
4
5export const register: Register = on => {
6 on('session.start', async ($, e, next) => {
7 const started = await next(e)
8 await $.tool.register({
9 name: 'note',
10 description:
11 'Log one thing about the Claude Code setup (CLAUDE.md, project rules, skills, agents, mods, tools) that changed what you did: a rule that was unclear, conflicted with another or was missing for the case at hand, or a tool that got in the way. Write it without reading earlier notes.',
12 inputSchema: {
13 type: 'object',
14 properties: {
15 topic: { type: 'string', description: 'The rule, file or tool involved' },
16 note: { type: 'string', description: 'One sentence on what happened and what you did' },
17 },
18 required: ['topic', 'note'],
19 },
20 })
21
22 return started
23 })
24
25 on('tool.call', { tool: TOOL }, async ($, e) => {
26 if (typeof e.topic !== 'string' || typeof e.note !== 'string') {
27 return { deny: 'topic and note must be strings' }
28 }
29 const at = new Date(await $.clock.now()).toISOString()
30 const entry = {
31 at,
32 session: await $.session.id(),
33 cwd: await $.session.cwd(),
34 topic: e.topic,
35 note: e.note,
36 }
37 const home = await $.env.get('HOME')
38 // One file per note, since `$.fs` can't append and sessions run in parallel.
39 await $.fs.write(
40 `${home}/.claude/setup-notes/${at.replace(/[:.]/g, '-')}-${e.tool_use_id}.json`,
41 `${JSON.stringify(entry, null, 2)}\n`,
42 )
43
44 return { result: 'Noted.' }
45 })
46}
47