Skip to content

Latest commit

 

History

History
217 lines (167 loc) · 8.75 KB

File metadata and controls

217 lines (167 loc) · 8.75 KB

CLAUDE.md

Critical Rules

IMPORTANT: These rules must NEVER be violated:

  1. Never modify global git config — Do not change global git user name, email, or any other global settings. This applies to both manual work and automated tests. Tests must use local config only.
  2. Never use this repository for testing — This project's own git repo must never be used as a test subject for worktree commands. Tests must always create isolated temporary repositories.

Safe Local Testing with Git

When manually testing git operations (e.g. cloning, worktree creation) in scratch directories:

  • Never run git config --global — not even temporarily. Use git config --local or per-command env vars instead.
  • Set test identity via environment variables, not config:
    GIT_AUTHOR_NAME="Test" GIT_AUTHOR_EMAIL="test@test.com" \
    GIT_COMMITTER_NAME="Test" GIT_COMMITTER_EMAIL="test@test.com" \
    git commit -m "test"
  • Never commit to this repo's branches from scratch/temp directories — stray commits from test repos must not leak onto working branches.
  • Always cd back to the worktree directory after testing — a deleted temp directory as cwd will silently break subsequent shell commands.
  • Clean up temp directories when done: rm -rf /tmp/daft-test-* or use mktemp -d.

Build, Test & Lint Commands

mise run dev                # Build + create symlinks (quick dev setup)
mise run test               # Run all tests (unit + integration)
mise run test:unit          # Rust unit tests only
mise run test:integration   # Integration tests (bash + YAML, full matrix)
mise run test:manual -- --ci           # YAML manual tests only (all scenarios)
mise run test:manual -- --ci checkout  # YAML tests for one command
mise run test:manual -- checkout:basic # Interactive mode for one scenario
mise run clippy             # Lint (must pass with zero warnings)
mise run fmt                # Auto-format code
mise run fmt:check          # Verify formatting
mise run ci                 # Simulate full CI locally
mise run bench:tests:integration       # Benchmark bash vs YAML (TUI)

IMPORTANT: Before committing, always run mise run fmt, mise run clippy, and mise run test:unit. These checks are required and enforced in CI.

IMPORTANT: Every bug fix must include a regression test that reproduces the issue. Add a YAML scenario in tests/manual/scenarios/ or a unit test that fails without the fix and passes with it.

XDG Conventions

This project follows the XDG Base Directory Specification. Use the dirs crate for cross-platform path resolution. Never hardcode ~/ paths for config or data storage.

Architecture

Multicall binary: All commands route through a single daft binary (src/main.rs). The binary examines argv[0] to determine which command was invoked, then dispatches to the matching module in src/commands/. Symlinks like git-worktree-clone → daft enable Git subcommand discovery. Shortcut aliases (e.g., gwtco) are resolved in src/shortcuts.rs before routing.

Shell integration: daft shell-init generates shell wrappers that create a temp file and pass its path via DAFT_CD_FILE. When set, commands write the cd target to that file, and the wrapper reads it after the command finishes to cd into new worktrees. Stdout flows directly to the terminal.

Hooks system: Lifecycle hooks in .daft/hooks/ with trust-based security. Hook types: post-clone, worktree-pre-create, worktree-post-create, worktree-pre-remove, worktree-post-remove. Old names without worktree- prefix are deprecated (removed in v2.0.0).

TUI navigation: All interactive TUI interfaces that support arrow key navigation must also support Vim-style hjkl keys.

Branch Naming & PRs

  • Branch names: daft-<issue number>/<shortened issue name>
  • PRs target master and are always squash merged (linear history required)
  • PR titles use conventional commit format: feat: add dark mode toggle
  • Issue references go in PR body, not title: Fixes #42

PR Tagging

Every PR must be tagged with:

  • Assignee: repository owner (avihut)
  • Label: matches the conventional commit type (feat, fix, docs, refactor, style, perf, test, chore, ci)
  • Milestone: Public Launch (current active milestone)

Commits

Conventional Commits format: <type>[scope]: <description>

Types: feat, fix, docs, style, refactor, perf, test, chore, ci

Release Process

Uses release-plz: push to master → Release PR auto-created → merge it → GitHub Release + tag → binary builds. All commits produce patch bumps; edit Cargo.toml in the Release PR for minor/major bumps.

Adding a New Command

  1. Create src/commands/<name>.rs with clap Args struct (include about, long_about, arg(help) attributes for man pages)
  2. Add module to src/commands/mod.rs
  3. Add routing in src/main.rs
  4. Add to COMMANDS array and get_command_for_name() in xtask/src/main.rs
  5. Add to help output in src/commands/docs.rs (get_command_categories())
  6. Run mise run man:gen and commit the generated man page
  7. Add YAML test scenarios in tests/manual/scenarios/<name>/ (see tests/README.md for schema reference)
  8. Add bash integration tests in tests/integration/ following existing patterns

Shell Completions

Shell completions live in src/commands/completions/. When adding, removing, or renaming commands, verbs, or arguments, update all of these:

  • mod.rsCOMMANDS, VERB_ALIAS_GROUPS, get_command_for_name()
  • bash.rsDAFT_BASH_COMPLETIONS (verb alias cases, top-level subcommand list)
  • zsh.rsDAFT_ZSH_COMPLETIONS (verb alias cases, top-level subcommand list)
  • fish.rsDAFT_FISH_COMPLETIONS (subcommand registrations, branch completion triggers), verb alias flag comment
  • fig.rs — Fig/Amazon Q spec generation

Flag completions for git-worktree-* commands are auto-generated from clap Args structs, but the hardcoded string constants in bash/zsh/fish contain verb names and subcommand lists that must be updated manually.

Man Pages

Pre-generated in man/ and committed. Regenerate after changing command help text:

mise run man:gen      # Generate/update man pages
mise run man:verify   # Check if man pages are up-to-date (also runs in CI)

Test Plans

Manual test plans live in test-plans/. Each file is a markdown checklist tied to a branch via YAML frontmatter:

---
branch: feat/progressive-adoption
---

# Progressive Adoption

## Layout resolution

- [ ] Default layout is sibling when no config exists
- [ ] CLI --layout flag overrides config
  • File name: descriptive feature name, not the branch name (progressive-adoption.md, not feat-progressive-adoption.md)
  • branch: frontmatter: must match the full branch name — used by the sandbox test-plan command to auto-resolve the plan for the current worktree
  • Committed to the repo: serves as documentation of what was manually tested
  • In the sandbox: test-plan opens the current branch's plan in treemd, test-plan <name> opens a specific plan by filename

Documentation Site

docs/ contains the project documentation (VitePress/Markdown). Update when adding or changing user-facing features.

  • docs/getting-started/ — installation, quick start, shell integration
  • docs/guide/ — in-depth guides (hooks, configuration, workflow, shortcuts)
  • docs/cli/ — one reference page per command, follow docs/cli/daft-doctor.md as template
  • Every page needs title and description YAML frontmatter
  • No emoji in docs
  • Update SKILL.md when changes affect how an agent should interact with daft — new or removed commands, changed feature behavior, configuration format changes (e.g., hooks moving from shell scripts to YAML), renamed hook types, new template variables, etc. The skill is what teaches AI coding agents to use daft correctly.

Docs Site (VitePress)

The docs site at daft.avihu.dev is built from docs/ using VitePress + Biome, with Bun as the package manager.

mise run docs:site          # Dev server at localhost:5173
mise run docs:site:build    # Build the site
mise run docs:site:preview  # Preview built site
mise run docs:site:check    # Lint config with Biome
mise run docs:site:format   # Auto-fix config with Biome
  • Prettier (root): *.{md,yml,yaml} files everywhere
  • Biome (docs): docs/.vitepress/config.ts and docs/.vitepress/theme/ only
  • Auto-deploys to Cloudflare Pages on push to master when docs/** changes
  • Playwright screenshots: Save to .playwright-mcp/ directory (gitignored), not the project root. Use filename like .playwright-mcp/screenshot.png.