Personal environment configs for shell, Git, Claude Code, Codex, global Cursor runtime integration, status line, and editor/TUI tools. The installer deploys tracked configuration with symlinks and keeps secrets out of Git.
Run as a normal user on x86_64 Ubuntu/Debian or RHEL, Rocky Linux, or
AlmaLinux 8+ (glibc 2.28+). The account must have sudo access, but do not run
the installer itself as root or with sudo. Network access is required for
distribution packages, toolchains, release assets, plugins, and the skills
checkout:
./install.shThis is the single installation entry point. It uses sudo only for distro
package and repository operations (apt, dnf, or RHEL repository
enablement). Apart from those system prerequisites, missing language
toolchains and tools are installed in user-owned locations such as ~/.cargo,
~/.local, and ~/.nvm; compatible commands already on PATH are generally
retained. Node/npm are the deliberate exception: when ~/.nvm/nvm.sh is
absent, the installer installs NVM and an NVM-managed current Node/npm even if
compatible system commands are already on PATH.
On Rocky Linux and AlmaLinux it enables PowerTools for version 8 or CRB for
version 9 and newer; on RHEL it enables the matching CodeReady Builder
repository. Every RHEL-family path also installs EPEL. See the complete
mandatory package and command inventory in TOOLS.md.
One run installs Rust, Go, Node/npm, uv, the required CLI/TUI tools (including
Herdr), tmux and its plugins, and the Claude/Codex tooling before activating
the global Claude, Codex, and Cursor runtime content, linking configuration,
and validating the result. Both Yazi commands, yazi and ya, are mandatory
and are installed and validated separately. The Cursor application itself is
not installed.
The shared Claude, Codex, and Cursor runtime content requires
~/compute-ai-skills. If it is absent, the installer clones the expected
abchoudh-amd/compute-ai-skills repository. An existing checkout must have an
accepted origin. A clean main checkout is updated only with
pull --ff-only origin main; an update failure keeps the existing checkout
with a warning, while a dirty or non-main checkout is preserved without an
update. A non-repository path or checkout with an unexpected origin is a
required failure. If a failed initial clone leaves partial material, the
installer moves it into the same private backup tree used for link conflicts.
Herdr is also required. A herdr command on PATH that completes a version
probe is retained. If it is missing or broken, the installer runs the official
installer exactly as follows and then requires the resulting command to be on
PATH and pass the same probe:
curl -fsSL https://herdr.dev/install.sh | shIndependent phases continue after a failure so the final summary can report
everything that needs attention. A required failure produces a nonzero exit;
fix the reported issue and run ./install.sh again.
After a successful run, fully quit and reopen Cursor, and terminate and restart
Claude Code and Codex so all three reload their global runtime content and hook
configuration. In Codex, review the installed hooks with /hooks and complete
any trust prompt it presents. Then open a new shell so the installed paths and
shell initializers are active. The installer enables Codex hooks but does not
update trusted-hook hashes. Authentication remains a manual follow-up where
the summary requests it.
| Area | Files |
|---|---|
| Shell | shell/.bashrc, shell/.profile |
| Git | git/.gitconfig, git/gitignore |
| Prompt | config/starship.toml |
| Herdr | config/herdr/config.toml -> ~/.config/herdr/config.toml |
| Claude Code | settings, status line, theme, and claude/mcp-servers.json |
| Codex | codex/config.toml (key read from $LLM_GATEWAY_KEY at runtime) |
| Cursor | cursor/hooks.json (global fail-closed boundary hook manifest) |
| Editors / TUI | config/nvim, config/fish, config/btop |
| tmux | tmux/.tmux.conf, tmux/.gitmux.conf |
The installer exposes ~/compute-ai-skills globally under each tool's
user-home runtime. It links every immediate child of each source tree at the
matching destination name rather than replacing the destination directory:
| Runtime | Leaf-by-leaf trees |
|---|---|
| Claude | skills, native agents, agent-resources, hooks, and references |
| Codex | skills, native agents, agent-resources, and hooks |
| Cursor | skills, native agents, agent-resources, hooks, and rules |
For example, the children of ~/compute-ai-skills/.cursor/skills/ become
individual links under ~/.cursor/skills/; the other trees follow the same
source-to-runtime layout. This keeps unrelated entries in the runtime
directories available. All listed source trees are required and are checked
before reconciliation begins. Destination tree roots must be real directories;
an existing symlink or non-directory is rejected before any runtime content is
changed. The compute checkout also owns the Codex hook manifest, linked from
.codex/hooks.json to ~/.codex/hooks.json.
Stale-link cleanup is deliberately narrow and recoverable. A destination is
classified as an obsolete installer-owned link only when it is a symlink whose
target exactly names the same leaf in ~/compute-ai-skills and that source leaf
no longer exists. Such a link is moved into the normal timestamped backup tree;
it is not deleted. Personal files and directories, foreign symlinks, and other
unmanaged entries are not swept. If an existing path collides with a currently
managed source leaf, the installer's normal backup-and-link behavior applies.
The tracked claude/settings.json adds exactly one
boundary-hook group for each of PreToolUse, SubagentStart, and
SubagentStop. Each group runs
python3 "$HOME/.claude/hooks/agent-boundary.py", whose script is supplied by
the linked compute checkout.
Dotfiles owns cursor/hooks.json and links it globally as
~/.cursor/hooks.json. Its complete hook manifest runs the checkout-owned
$HOME/.cursor/hooks/agent-boundary.py with failClosed: true for these six
events: subagentStart, preToolUse, beforeShellExecution,
beforeMCPExecution, beforeReadFile, and subagentStop.
The adapters resolve their physical checkout path before importing the shared
agent_policy core, so that directory is validated in place rather than linked
separately into any runtime.
Final validation requires every source leaf to have the exact matching runtime
symlink and rejects any obsolete installer-owned link left behind. It also
checks the exact Codex hooks.json link, the dotfiles-owned Claude settings and
Cursor hook-manifest links, and all three Claude plus all six Cursor boundary
hook groups. The three boundary adapters and their shared policy source must
also exist and be readable, and Cursor's directly invoked adapter must be
executable. Any mismatch makes the installer exit nonzero.
The installer manages only Herdr's config.toml: it links the tracked
config/herdr/config.toml source to $HOME/.config/herdr/config.toml. Herdr
logs, sockets, locks, release notes, and session state remain machine-local;
they are not tracked or symlinked. The installer does not reload a running
Herdr server after creating or repairing the link.
This repository owns the tracked Claude hook
claude/hooks/herdr-agent-state.sh, which
the installer links to ~/.claude/hooks/herdr-agent-state.sh. It is vendored
from Herdr v0.7.5 with integration ID claude and integration version 7.
Claude's tracked settings invoke it on SessionStart; restart Claude Code
after installation so the new hook configuration is loaded.
The tracked Codex configuration enables hook support, while
~/compute-ai-skills owns the corresponding v0.7.5 Codex hook (integration ID
codex, version 6) and hooks.json. Inside a Herdr-managed pane, these hooks
report the native Claude or Codex session identity to Herdr's local socket. They
exit quietly outside that environment and do not report activity transitions,
so Herdr continues to derive agent status from pane output. Claude's
teammateMode remains tmux, and the Herdr integration does not replace or
change the tracked tmux configuration.
Warning: Do not run
herdr integration installagainst these managed integrations. The live hook paths are symlinks, so that command can rewrite the tracked hook targets. Update the vendored assets deliberately instead.
install.sh is idempotent: a correct symlink or compatible installed command is
left alone, while a missing or stale managed item is repaired. A no-op rerun
does not create another backup.
Before replacing an existing path, the installer moves it into a private
mode-0700 directory named
~/.dotfiles-backup-YYYYMMDD-HHMMSS.XXXXXX/. The backup tree mirrors the
original absolute path, and the final summary prints its exact location.
Claude state snapshots are copies within the same tree and are forced to mode
0600. Backups are retained for manual recovery; restore the corresponding
mirrored path after removing the installer-created target if you need to undo
a normal configuration replacement.
Claude MCP changes are transactional. If ~/.claude.json existed before the
run, an ordinary reconciliation failure restores its snapshot only when the
installer can prove that doing so will not overwrite unrelated state or an
unconfirmed managed-record write. If the path was initially absent, Claude
may create normal first-run metadata while adding the first MCP entry; the
installer preserves that generated baseline and restores an absent
destination only when it can prove the operation is safe. If either proof
fails, or Claude or another process changes state concurrently, the installer
does not overwrite the unexpected state. It exits nonzero and prints the
paths of the live, snapshot, displaced, or prepared recovery files that
actually exist; the destination itself may safely be absent. Close Claude
Code, inspect or merge the reported files, and rerun the installer.
Secret values remain in these untracked, gitignored locations:
secrets.envstores environment secrets such asLLM_GATEWAY_KEY. It is linked to~/.config/secrets.envand sourced by the shell configuration.secrets/stores credential blobs. When present, the installer linkssecrets/gh-hosts.ymlto~/.config/gh/hosts.ymlandsecrets/claude-credentials.jsonto~/.claude/.credentials.json.
On a first run, the installer seeds those files from usable values already on
the machine when possible; otherwise it warns so you can authenticate or fill
them in manually. It never commits them. To initialize the environment file
yourself, copy secrets.env.example to secrets.env and add the real value.
The tracked, non-secret
claude/mcp-servers.json manifest declares the
jira and confluence server names. The installer reconciles those two names
at Claude's global user scope, so they are available across projects. It owns
only those names: differing managed definitions are replaced, while all other
MCP servers and every non-MCP field are preserved.
Close Claude Code before running ./install.sh so it does not write
~/.claude.json while the installer is reconciling these user-scope entries.
Run the installer with CLAUDE_CONFIG_DIR unset:
unset CLAUDE_CONFIG_DIR
./install.shThe managed user-state location is always ~/.claude.json. The installer
fails safely instead of asking the Claude CLI to mutate state in an alternate
CLAUDE_CONFIG_DIR.
~/.claude.json is mutable state owned by Claude Code, so it is deliberately
neither tracked nor symlinked. Tracking or replacing the whole file would
capture machine-specific state and overwrite unrelated data. The installer
instead uses the Claude CLI to update only the managed names; the repository's
root .claude.json ignore rule also guards against accidentally committing a
copied live file.
Installation validates the definitions but does not authenticate them, test endpoint reachability, or require MCP health. Complete OAuth manually as needed:
claude mcp login jira
claude mcp login confluenceWarning: Never put headers, tokens, passwords, client secrets, environment secret values, or other credentials in
claude/mcp-servers.json; it is tracked by Git.
- ROCm or Slurm installation and cluster configuration.
- Desktop/GUI assets.
- Authentication or secret values. Existing credentials may be preserved or seeded, but the installer does not supply real values or perform logins.
- Claude/Codex/Cursor history, sessions, databases, caches, and other mutable state.