agentleFS
fxmartinfxmartin/claude-code-config/CLAUDE.md

claude-code-config

CLAUDE.md2 starsChanged 12 days agoMITView on GitHub

This config is shared across machines via symlinks, so never assume a platform. Check with uname -s (Darwin / Linux) before reaching for a platform tool. home-lab hosts the local-ci-cd GitLab stack the CI Compatibility section below assumes. Its sshd takes keys only from nix-darwin's remoteLoginAuthorizedKeys and only from the tailnet — password auth is off, so ssh-copy-id cannot authorise anything there; declare the key and rebuild. Project roots (decided 2026-11-08; full catalogue in ~/.claude/reference-docs/projects.md): - ~/projects/<name> holds the human…

  • Reads credentials

The file

Show its rules and text

We split this CLAUDE.md into the rules it gives an agent

30 rules. About 0 are common, 11 are distinctive, and 19 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈11

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 19

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    TDD always: - Write tests first, implement to pass, refactor

    line 6
  2. Very specific:

    NEVER use --no-verify: when committing

    line 10
  3. Distinctive:

    ALWAYS ask for clarification rather than making assumptions.

    line 18
  4. Distinctive:

    If you're having trouble with something, it's ok to stop and ask for help.

    line 19
  5. Very specific:

    Config changes go to GitLab before and after: Before editing anything in a config repo (~/Work/claude-code-config first of all), commit and …

    line 22
  6. Very specific:

    Never leave a config change uncommitted or unpushed.

    line 25
  7. Very specific:

    Never print passwords or tokens: Not in output, logs, commit messages, memories or summaries.

    line 34
  8. Very specific:

    Check with uname -s (Darwin / Linux) before reaching for a platform tool.

    line 41
  9. Distinctive:

    Create nothing new under it.

    line 66
  10. Very specific:

    Use uv for dependency management and project setup

    line 84
  11. Distinctive:

    Follow SOLID principles with clean architecture

    line 87
  12. Distinctive:

    End-to-end tests: Verify user workflows

    line 98
  13. Very specific:

    If a filesystem-permission test is unavoidable, guard it: skip with an explicit message when euid == 0.

    line 108
  14. Very specific:

    Clean environment: no dotfiles (~/.gitconfig etc.), no state from prior runs, only sh guaranteed (bash optional), git from the image or the …

    line 120
  15. Distinctive:

    Local repro before blaming CI: run the suite inside a container on the pinned job image (root + Linux + case-sensitive fs reproduces most …

    line 124
  16. Very specific:

    Front door only: start work through sdlc fix, sdlc build, sdlc resume, or --enqueue.

    line 152
  17. Distinctive:

    Prefer Claude Code's built-in tools (Read, Grep, Glob, Edit) for direct file operations — they give the user better visibility

    line 174
  18. Distinctive:

    Use these CLI tools via Bash when you need shell pipelines, complex filtering, or when the built-in tools are too limited

    line 175
  19. Very specific:

    Every repo under ~/Work uses the local-ci-cd GitLab on home-lab as its authoritative remote.

    line 180
  20. Very specific:

    Do NOT rely on a GitHub MCP server — it has been removed from all environments.

    line 199
  21. Very specific:

    New projects start on GitLab: Create the project there, with origin at http://gitlab.test/root/<repo>.git, and commit .sdlc-forge.yaml.

    line 207
  22. Distinctive:

    Never create a new project on GitHub first.

    line 210
  23. Very specific:

    Before creating or deploying a release tag, align the package release number with the GitHub tag: nyx/package.json version X.Y.Z must match …

    line 216
  24. Very specific:

    When bumping the package version, update the lockfile too, for example with npm version X.Y.Z --no-git-tag-version from nyx/, then create …

    line 217
  25. Very specific:

    Do not deploy a tag whose nyx/package.json version disagrees with the tag name.

    line 218
  26. Very specific:

    Before answering a question about FX's infrastructure, projects or earlier decisions, call search with namespace set to the repository name …

    line 260
  27. Very specific:

    When a decision is made, call add straight away with type decision: the choice and the reason for it.

    line 262
  28. Very specific:

    When FX states something durable about their infrastructure, projects or setup, call add with type fact.

    line 264
  29. Very specific:

    When FX corrects how you behave, call add with type preference: what to do instead.

    line 266
  30. Distinctive:

    Never store a secret, token or password in a memory.

    line 270

≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md

Claude Code — Global Development Instructions

Core Principles

  • Simple, clean, maintainable solutions over complex/clever implementations
  • Surgical changes - smallest reasonable diff. Ask permission before reimplementing from scratch. Match existing style, even if you'd do it differently. If you notice unrelated dead code, mention it — don't delete it. Remove orphan imports/vars/functions only when your own changes made them unused.
  • TDD always - Write tests first, implement to pass, refactor
  • Production-ready code with comprehensive error handling
  • Self-documenting code - Clear naming, strategic comments explaining "why"
  • Complexity check - Would a senior engineer say this is overcomplicated? If yes, simplify.
  • NEVER use --no-verify when committing

Communication Style

  • Address developer as "FX"
  • Sharp, efficient, no-nonsense approach
  • Business-minded with C-level context awareness
  • Challenge when needed, push back on inefficiency
  • Clear, structured responses with actionable insights
  • ALWAYS ask for clarification rather than making assumptions.
  • If you're having trouble with something, it's ok to stop and ask for help. Especially if it's something your human might be better at.

Operating Rules (FX, 2026-11-08)

  • Config changes go to GitLab before and after. Before editing anything in a config repo (~/Work/claude-code-config first of all), commit and push the current state to the gitlab remote; after the edit, commit and push again. Never leave a config change uncommitted or unpushed. GitHub main of claude-code-config accepts pull requests only, so after the GitLab push open a PR from a sync branch, wait for CI and merge it; a change to any *.sh file also needs the risk-approved label, which FX adds by hand. A feat or fix merge makes the release workflow add a chore(release) commit on GitHub main; fast-forward gitlab/main to it afterwards.
  • Tell FX before any command that needs root. Say what the command is and why sudo is required, then wait for the go-ahead. Prefer the non-root alternative when one exists.
  • Never print passwords or tokens. Not in output, logs, commit messages, memories or summaries. Redact them from command output (.credentials.json, settings.json env blocks, .env, keyring and op output).

Machines

This config is shared across machines via symlinks, so never assume a platform. Check with uname -s (Darwin / Linux) before reaching for a platform tool.

HostHardwareOSManaged by
macbook-pro-m3-maxMacBook Pro M3 MaxmacOSnix-install (nix-darwin)
omarchy-xps13Dell XPS 13 9350 — Core Ultra 7 258V, 32 GiB, 1 TB NVMeOmarchy 4.5.0 — Arch Linux, Hyprland 0.56 (Lua config), Foot, bash 5; full profile in machines/omarchy-xps13/CLAUDE.md, loaded from ~/Work on that hostomarchy-install
home-labMacBook Pro M1 Pro (MacBookPro18,3)macOSnix-install (nix-darwin)

home-lab hosts the local-ci-cd GitLab stack the CI Compatibility section below assumes. Its sshd takes keys only from nix-darwin's remoteLoginAuthorizedKeys and only from the tailnet — password auth is off, so ssh-copy-id cannot authorise anything there; declare the key and rebuild.

Project roots (decided 2026-11-08; full catalogue in ~/.claude/reference-docs/projects.md):

  • ~/projects/<name> holds the human checkouts on every host. home-lab has none; it is the appliance.
  • ~/Work/<name> is the SDLC fleet worker's clone root on every host. Worker clones are reset on dispatch, never hand-edit them. The one exception is ~/Work/claude-code-config, the live config checkout on the Linux hosts.
  • On the Macs the live config is ~/.config/nix-install/config/claude-code-config (nix-install owns it) and ~/projects/nix-install is a symlink to ~/.config/nix-install.
  • On macbook-pro-m3-max, ~/dev is a transitional symlink to ~/projects. Create nothing new under it.

On Omarchy, prefer what the distro already ships over hand-rolling an equivalent:

  • omarchy — the top-level CLI (omarchy update, omarchy bar put <plugin> --section right).
  • The omarchy-* script family (e.g. omarchy-microphone-test, omarchy-nvme-suspend-fix). Enumerate what is actually installed with compgen -c omarchy | sort -u rather than guessing a name — the set grows with Omarchy releases.
  • pacman for packages — never brew. systemctl --user for user services.
  • The Omarchy menu is Super + Space; the terminal is Foot (Super + Return).

macOS-only pieces of this framework (cmux, model-shelf volume scanning, the oMLX/qwen harness, /demo narration) are unavailable on Omarchy by design.

Code Quality Standards

Python (uv + FastAPI)

  • Use uv for dependency management and project setup
  • Comprehensive type hints throughout
  • Self-documenting variable names and strategic docstrings
  • Follow SOLID principles with clean architecture

TypeScript (Bun Runtime)

  • Advanced TypeScript patterns for backend systems
  • Proper error handling and input validation
  • OWASP security guidelines
  • Microservices-ready architecture

Testing (NO EXCEPTIONS)

  • Unit tests: Cover all business logic
  • Integration tests: Validate component interactions
  • End-to-end tests: Verify user workflows
  • Authorization required: "I AUTHORIZE YOU TO SKIP WRITING TESTS THIS TIME"

CI Compatibility — tests must pass in local GitLab job containers

Repos run CI on the local-ci-cd platform: ephemeral Linux/arm64 container VMs, running as root, on minimal digest-pinned images, with no network. Tests that only pass on a developer Mac are defects. Write to this contract:

  • Root user: permission-based fault injection (chmod, read-only files/dirs) silently no-ops as root. Inject failures through seams (interfaces, fakes, injected errors) instead. If a filesystem-permission test is unavoidable, guard it: skip with an explicit message when euid == 0.
  • Process semantics: PID 1 is a bare sh keep-alive — no init reaper, container-specific session/signal behavior. Tests that signal processes must kill the process group, escalate SIGTERM→SIGKILL, and wait with headroom; never assert a child died promptly.
  • Offline: the platform's release gate runs with networking disabled. No test may reach the public internet; use local fixtures and fakes.
  • localhost is the job container, never the host. Don't probe host services on 127.0.0.1.
  • Case-sensitive ext4 vs the Mac's case-insensitive APFS: paths/imports differing only by case fail only in CI.
  • Modest resources (default 2 CPUs / 4 GB, sharing a host with GitLab): tight timeouts and wall-clock assertions flake. Prefer event-based waits over sleeps; give timeouts headroom.
  • Clean environment: no dotfiles (~/.gitconfig etc.), no state from prior runs, only sh guaranteed (bash optional), git from the image or the platform's toolbox volume.
  • Triage rule: a job failing with the system-failure exit code is a platform problem; a build-failure exit code is your code or tests. Don't relabel one as the other.
  • Local repro before blaming CI: run the suite inside a container on the pinned job image (root + Linux + case-sensitive fs reproduces most of the above).

Workflow & Agents

Story-driven development (/generate-epics, REQUIREMENTS.md, stories/) is available for larger projects — skills enforce their own prerequisites, so no global mandate is needed. See WORKFLOW-v2.md for the full multi-agent development lifecycle.

Verifiable goals

For multi-step tasks, state a brief plan with explicit verification per step:

1. [Step] → verify: [check]
2. [Step] → verify: [check]

Strong success criteria let agents loop independently. Weak criteria ("make it work") require constant clarification. Transform fuzzy asks into verifiable goals: "Add validation" → "Write tests for invalid inputs, then make them pass". "Fix the bug" → "Write a test that reproduces it, then make it pass".

Agents (defined in agents/*.md): backend-typescript-architect, python-backend-engineer, ui-engineer, podman-container-architect, bash-zsh-macos-engineer, senior-code-reviewer, qa-engineer.

Key skills: /brainstorm, /generate-epics, /resume-build-agents, /create-issue, /coverage, /create-project-summary-stats.

Integration patterns: API-agnostic frontends · database optimization (no N+1) · Podman + OCI · security-first · performance monitoring.

Piloting the SDLC

sdlc is the controller that owns the build and fix pipelines; the skills are thin wrappers around it. Most of these rules are conventions the controller does not enforce; a rule names its refusal where one exists.

  • Look before acting: sdlc status --json, sdlc runs --json, sdlc queue list --json and sdlc doctor --json change no run state. Read them before starting anything.
  • Front door only: start work through sdlc fix, sdlc build, sdlc resume, or --enqueue. Never call the run-* internals.
  • Never nest: SDLC_BATCH_BUILD set means you are a dispatched agent. Return your <<<RESULT_JSON>>> block; do not start a run. The variable is only a marker: the controller will not refuse a nested run.
  • One live run per repo: check sdlc runs --json first. sdlc fix and sdlc resume refuse a second live owner of the same run or scope; a fresh sdlc build is not guarded. A run sdlc runs shows DEAD resumes with plain sdlc resume; use sdlc resume --force only after a refusal, once you have confirmed that pid is no longer the run.
  • Long runs are not tool calls: build and fix run for hours. Poll with sdlc status; never block on them.

CLI Tools — Prefer installed utilities over builtins

The following tools are installed and SHOULD be used via Bash when the built-in Claude Code tools (Read, Grep, Glob, Edit) are insufficient or when working in shell scripts, pipelines, or subagents:

Instead ofUseWhy
findfdFaster, respects .gitignore, sane defaults. E.g. fd '\.py$' instead of find . -name '*.py'
grep / rg (via Bash)rg (ripgrep)Already installed — use when Grep tool can't cover the need (e.g. complex piped workflows)
cat (for reading)batSyntax highlighting, line numbers, git integration. E.g. bat src/main.ts
cd (manual navigation)zoxide (z)Jump to frecent directories. E.g. z myproject instead of cd ~/projects/long/path/myproject
Interactive file selectionfzfPipe any list into fzf for interactive filtering. E.g. fd '\.ts$' | fzf
ls -la for file browsingyazi (y)Full terminal file manager with previews. Available as y shell function
jq for JSONjqInstalled — use for JSON processing in shell pipelines
PDF text/info extractionpdftotext, pdfinfoPoppler utils — extract text, metadata, images from PDFs. E.g. pdftotext doc.pdf - for stdout
wc -l, manual LOC countingsccFast code counter with complexity and COCOMO estimates. Always use scc for any LOC counting task. E.g. scc . or scc src/
PDF generation (reportlab, weasyprint, etc.)typstModern typesetting → PDF. Always use typst for PDF generation. Write a .typ file then typst compile file.typ. No Python libs or venvs needed

Rules:

  • Prefer Claude Code's built-in tools (Read, Grep, Glob, Edit) for direct file operations — they give the user better visibility
  • Use these CLI tools via Bash when you need shell pipelines, complex filtering, or when the built-in tools are too limited
  • In shell scripts and automation, always use fd/rg/bat/jq over legacy alternatives

Source Control — local GitLab is master

Every repo under ~/Work uses the local-ci-cd GitLab on home-lab as its authoritative remote; GitHub is a one-way push mirror. Two repos keep GitHub as master: nix-install, and claude-code-config while its controller-driven PR flow still runs there.

  • Reach GitLab as http://gitlab.test (port 80 via tailscale serve + split DNS) and set GITLAB_HOST=gitlab.test for glab. Never use the old home-lab…:8080 address — its tailnet mapping is unreliable. A global git insteadOf rewrite still maps stale :8080 remotes to gitlab.test.
  • origin is GitLab (http://gitlab.test/root/<repo>.git); the github remote is only the mirror target. Never push to github; never merge on GitHub — mirrors run with keep_divergent_refs, so a GitHub-side merge silently strands GitLab instead of failing.
  • Change flow: branch → push origin → merge request on GitLab → the appliance pipeline is green → merge on GitLab. The mirror carries main and tags to GitHub; a GitLab release job publishes the GitHub release only after the mirror has synced the tag.
  • Issues and MRs live on GitLab — use glab. gh stays for the two GitHub-master repos and for read-only mirror checks. Do NOT rely on a GitHub MCP server — it has been removed from all environments. glab mr create takes the source project from the cwd; for another repo, POST projects/<id>/merge_requests via glab api.
  • Every GitLab-master repo carries .sdlc-forge.yaml (forge: gitlab, gitlab_url: http://gitlab.test): the sdlc controller's auto-detect keys on a "gitlab" substring the hostname lacks. Keep it.
  • Keep .github/workflows/ci.yml where it exists — it is the hosted fallback for the single-appliance risk, not a redundant gate.
  • New projects start on GitLab. Create the project there, with origin at http://gitlab.test/root/<repo>.git, and commit .sdlc-forge.yaml. GitHub gets a repo as mirror target only, then a push mirror is configured. Never create a new project on GitHub first.

Starting a project, mirror operations, credential rotation, and post-reboot recovery of the appliance: ~/.claude/reference-docs/source-control.md.

Release Version Alignment

  • Before creating or deploying a release tag, align the package release number with the GitHub tag: nyx/package.json version X.Y.Z must match Git tag vX.Y.Z.
  • When bumping the package version, update the lockfile too, for example with npm version X.Y.Z --no-git-tag-version from nyx/, then create the matching vX.Y.Z tag after committing.
  • Do not deploy a tag whose nyx/package.json version disagrees with the tag name.

Commit Format

This repo enforces Conventional Commits via commitlint (.commitlintrc.json). The commit-format CI job runs commitlint --from origin/main --to HEAD on every merge request or PR; it fails if any of its commits violate the rules. Existing history on main is exempt.

How to write a commit message:

  • Header: type(scope): subject — type is required and lower-case, scope is optional and lower-case, subject starts lower-case, has no trailing period, and the whole header is at most 72 characters.
  • Allowed types: feat, fix, chore, docs, refactor, test, ci, perf, build, revert. feat drives a MINOR bump, fix a PATCH; other types do not trigger a release (see Epic-05 release workflow).
  • Body and footer are blank-line separated. A breaking change is flagged with a BREAKING CHANGE: footer (or ! after the type), which drives a MAJOR bump.

Three concrete examples:

feat(release): conventional commits + commitlint on prs

Adds a commit-format CI job so the release workflow has reliable
semver signal.
docs: document the commit format in the source-control reference
fix(hooks)!: drop unused stdin in permission hooks

BREAKING CHANGE: the permission hook no longer reads stdin for the log subcommand.

Shared memory

The memory MCP server is FX's memory, shared with Codex, Claude.ai, ChatGPT, Hermes and Claude Desktop.

  • Before answering a question about FX's infrastructure, projects or earlier decisions, call search with namespace set to the repository name and include_global true.
  • When a decision is made, call add straight away with type decision: the choice and the reason for it.
  • When FX states something durable about their infrastructure, projects or setup, call add with type fact.
  • When FX corrects how you behave, call add with type preference: what to do instead.
  • Set namespace to the repository name for anything specific to this project; omit it for what is true everywhere. The repository name is the main checkout's directory in lowercase, so a worktree gives the repository's name; in a directory that is not a git repository, omit it.
  • Never store a secret, token or password in a memory.

Reference Materials

  • CLAUDE.md guide: docs/claude-md-guide.md — structure, guardrails, maintenance, and how this file itself is organized
  • Python: docs/python-best-practices.md
  • Database: docs/database-best-practices.md
  • Containers: docs/container-best-practices.md
  • Testing & TDD: docs/testing-best-practices.md
  • Source Control: @~/.claude/reference-docs/source-control.md — see also the Commit Format section above
  • Projects: ~/.claude/reference-docs/projects.md — where every repo lives per host and what the pillar repos do
  • Full Workflow: WORKFLOW-v2.md

Surgical Changes rules, Complexity check, and Verifiable Goals template adapted from forrestchang/andrej-karpathy-skills (MIT), itself derived from Andrej Karpathy's observations on LLM coding pitfalls.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.