bash.d/CLAUDE.md
Ole-Morten Duesund 6a00847d4e Speed up shell startup 9x (1.9s → 0.2s)
Lazy-load Intel oneAPI setvars.sh (~1.5s) via wrapper functions that
source the environment on first use of icc/icx/ifort/etc.

Cache all shell completion outputs to ~/.cache/bash.d/ so they are
sourced from disk instead of regenerated via subprocess on every
shell start.  Cache invalidates automatically when the tool binary
is updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 09:27:12 +01:00

73 lines
3.4 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Overview
This is a modular bash configuration directory (`~/.bash.d/`). Files here are sourced by `~/.bashrc` to set up the shell environment. Each file handles a specific concern (PATH additions, environment variables, shell completions). See `README.md` for a full description of the directory and its contents.
## File Naming Convention
Files use numeric prefixes to control load order:
- **00-** : Helper functions (loads first — used by other scripts)
- **10-** : PATH configuration (foundational)
- **20-** : Build tool settings (depends on paths)
- **30-** : Shell/prompt setup
- **50-** : Shell completions (named `50-<tool>-completion`)
- **99-** : Application config, credentials (loads last)
## Available Helpers (defined in `00-*`)
Use these in all scripts — do not manipulate `PATH` or check permissions manually:
- `path_append <dir>` — add directory to end of `$PATH` (checks existence, prevents duplicates)
- `path_prepend <dir>` — add directory to start of `$PATH`
- `require_private <file>` — warn if file is group/world-accessible; use in credential files
- `cached_completion <tool> <gen-cmd...>` — cache completion output to `~/.cache/bash.d/`; regenerates when the tool binary is updated. Use this for all new completion scripts instead of `eval` or `. <()`
## Writing Scripts
- Every file must start with `# shellcheck shell=bash`
- Guard external tools with `command -v <tool> &>/dev/null` before using them
- Guard directory-dependent exports with `[[ -d <path> ]]` before exporting
- Do not suppress stderr from external scripts — only redirect stdout when needed
- Avoid `eval` when `. <(cmd)` (process substitution) works
- For shell completions, use `cached_completion` instead of `eval` or `. <()` to avoid subprocess overhead on every shell start
- For slow environment scripts, use lazy-loading (see `20-oneapi` for the wrapper-function pattern)
- Prevent `LD_LIBRARY_PATH` duplicates with a `case` guard (see `20-oneapi` for example)
## Permissions
- Directory `~/.bash.d/` itself: mode `700`
- Regular scripts (`00-*` through `50-*`): mode `755` (executable is **required** for sourcing)
- Credential files (`99-*` with secrets): mode `700` and must call `require_private "${BASH_SOURCE[0]}"` as the first functional line
- Non-credential config files (e.g. `20-android`): mode `755` like regular scripts
## Validation
Validate all shell scripts with shellcheck before committing:
```bash
shellcheck <filename> # single file
shellcheck [0-9][0-9]-* # all scripts at once
```
To test changes, open a new shell or source a single file:
```bash
source ~/.bash.d/20-ninja # reload one file in the current shell
```
## Security
Credential files are **excluded from git** via `.gitignore`. Each has a tracked `.example` template with placeholder values.
To set up a credential:
1. Copy the template: `cp 99-foo.example 99-foo`
2. Fill in your real secret
3. Restrict permissions: `chmod 700 99-foo`
When adding new credential files:
- Create a `.example` template (mode `644`) tracked in git
- Add the real filename to `.gitignore`
- Use mode `700` on the real file: `chmod 700 <file>`
- Call `require_private "${BASH_SOURCE[0]}"` as the first functional line
- **Never commit real secrets**
- Be aware that `export`ed tokens are visible to all child processes