This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Personal dotfiles for the user's dev environment on the Flatiron CCQ cluster. Files at the repo root mirror their target paths under $HOME and are deployed by symlinking — i.e. ~/.zshrc, ~/.tmux.conf, ~/bin, etc. are symlinks back into this repo. Editing a file here edits the live config; editing the file via its ~/... path edits this repo.
A few targets that also hold tool-managed runtime state (~/.claude, ~/.codex, ~/.config/nvim) are not whole-directory symlinks — each is a real directory at $HOME, populated with per-entry symlinks into this repo for the tracked config files only. Runtime state (auth tokens, session transcripts, history, caches) stays outside the repo working tree.
The default branch is master (not main) and is the working branch — there is no PR/feature-branch workflow for this repo.
./link.sh is the deploy script. It is destructive: for every top-level entry except a hard-coded exclusion list, it rm -rfs the existing $HOME/<name> and replaces it with a symlink into the repo. Do not run it casually on a populated home directory.
The exclusion list covers .config, .claude, and .codex — these are handled at the bottom of the script via per-entry loops (so runtime state at $HOME/.claude and $HOME/.codex survives a re-run, and .config/nvim is the only .config/ entry deployed). Adding a new tracked entry under any of these dirs requires updating the corresponding loop in link.sh.
$HOME/.codex/skills needs a second level of the same treatment: it must stay a real directory because Codex keeps its own bundled skills in $HOME/.codex/skills/.system/, so link.sh symlinks each skill individually out of .claude/skills/. New skills are picked up by that loop automatically. $HOME/.claude/skills, by contrast, holds no runtime state and is a plain whole-directory symlink.
After cloning, run git submodule update --init --recursive. Submodules: .oh-my-zsh, .solarized/dircolors-solarized, .jupyter/nbextensions/vim_binding, .vim/autoload/vim-plug, .config/nvim.
- The user's global excludes file is
~/.glob_git_ignore(set viacore.excludesfile), and it ignoresCLAUDE.md,AGENTS.md, and.claudeamong others. Tracking any file with one of those names — e.g. this repo's rootCLAUDE.md, or.codex/AGENTS.md— requiresgit add -f. - This repo's
.gitignorelistsbin/*(mixed dir of tracked helpers and untracked scratch scripts on$PATH). Tracked files there stay tracked and editable; new files inbin/requiregit add -fto stage.
.claude/— user-global Claude Code config (deployed per-entry into~/.claude/)..claude/skills/<name>/SKILL.mdare the user-global skills, each invocable as/<name>(see below);.claude/CLAUDE.mdis the user's global CLAUDE.md loaded on every project;.claude/settings.jsondefines hooks, permissions, and env vars;.claude/hooks/tmux-status.shpowers the per-window tmux status dot;.claude/statusline.shis the statusline command..claude/skills/— shared by both agents: Claude Code reads~/.claude/skills/, Codex reads~/.codex/skills/, andlink.shpoints both at this one directory. Consequences for authoring:- Codex requires
name:in the frontmatter (Claude Code treats it as an optional display label and derives the command from the directory name), so everySKILL.mdhere carries one, matching its directory. - The directory name is the command name in Claude Code. There is no directory-namespacing as there was under the old
commands/layout — a subdirectory there became a/prefix:namecommand, which is how a straycommands/bkp/once shipped as a live/bkp:refine-command. Group by name prefix (release-*) instead, and don't park backups in here. - Skills replace what used to live in
.claude/commands/*.md. Commands still work but are the legacy path; per the docs they "have been merged into skills," and only skills support bundled supporting files. - Every skill sets
disable-model-invocation: true, and new ones should too. Skills here are invoked deliberately with/<name>, never auto-activated by Claude. This also keeps their descriptions out of context entirely, so the whole set costs nothing until used. Dropping the flag on a new skill is a deliberate exception, not the default. - Detail that's a lookup rather than a step belongs in
references/*.md, and executable tooling inscripts/addressed as${CLAUDE_SKILL_DIR}/scripts/…— both load only when needed, whereasSKILL.mditself stays in context for the whole session once invoked.semantic-scholar/scripts/s2lit.pyis the reference case: it used to be a 266-line Python program pasted inside the prompt.
- Codex requires
.codex/— OpenAI Codex CLI config (deployed per-entry into~/.codex/)..codex/config.tomlis the main config;.codex/AGENTS.mdis an internal symlink to.claude/CLAUDE.mdso global instructions are shared between the two agents. Codex reaches the skills two independent ways:~/.codex/skills/— the per-skill loop inlink.sh, covering all 19. This is the mechanism Codex actually documents..codex/prompts/<name>.md— a repo-side symlink per skill, pointing at../../.claude/skills/<name>/SKILL.md, deployed as a whole-directory link. A deliberate belt-and-braces fallback in case Codex doesn't traverse symlinks when discovering skill directories. Only the 16 self-contained skills are linked:merge-app4triqs,migrate-to-c2py, andsemantic-scholarare excluded because their bodies point atreferences//scripts/paths that resolve only through the skills mechanism, so a prompt link would hand Codex instructions referencing files it can't find. Adding a supporting file to a currently-linked skill means dropping its prompt link.- Two consequences: the YAML frontmatter renders as literal text in a Codex prompt (harmless, and true of the old
commands/symlink too), and if skills discovery does work, those 16 appear twice in Codex's/menu. Drop.codex/promptsonce skills discovery is confirmed if the duplication bothers you.
bin/— personal helper scripts on$PATH(added in.zprofile):build_*.sh— from-source builds for GCC, LLVM, neovim, vim, boost, kokkos, libcxx-msan, scinumpy+MKL; each installs to~/opt/<name>.gen_copyright— rewrites GPL/Apache copyright headers on C++/Python/CMake files usinggit blame -w -M --incremental. Has TRIQS-specific author/years special cases. Edits files in place. Invoke asgen_copyright -license Apache-Minimal -project <name> file1 file2 ....tmux-next-agent— used by.tmux.conf(prefix o/prefix u) to cycle between tmux panes running Claude Code or Codex CLI.parse_commits,mkdiag.sh,mymake.sh,pymake,setup_venv.sh,triqs_setup.sh,fixbb.sh,2to3_nb.
.shrc— shared shell aliases and functions sourced from.zshrc. Containstmuxdev(sets up the user's standard 16-window TRIQS tmux layout withgcc/san/prof/dbgbuild envs pre-sourced),cmakedd,prof/pprint/hprof/hpprint(gperftools wrappers), and slurm/cluster aliases (interactive,sls,cluster_usage)..zprofiledefinesaddlib/addpath/addenvhelpers used to extendCPLUS_INCLUDE_PATH,LD_LIBRARY_PATH,LIBRARY_PATH,PKG_CONFIG_PATH,PATH, andMANPATHconsistently for software in~/opt..zshrcends with_tmux_auto_rename, achpwdhook that renames tmux windows 1–8 to the current git repo's basename (or "Coding" outside a repo).
Changes are live for new shells/sessions only. The user's existing tmux server and shells will not pick up edits to .tmux.conf, .zshrc, .zprofile, etc. until reloaded (tmux source-file ~/.tmux.conf, exec zsh, etc.) — point this out rather than assuming a change has taken effect.