- Incremental progress over big bangs - Small changes that compile and pass tests
- Learning from existing code - Study and plan before implementing
- Pragmatic over dogmatic - Adapt to project reality
- Clear intent over clever code - Be boring and obvious
- Single responsibility per function/class
- Avoid premature abstractions
- No clever tricks - choose the boring solution
- If you need to explain it, it's too complex
- If code was added in the current branch, it's not legacy code. Only code in the main (or master) branch is legacy code.
- If you need to change a method that's not legacy, you can change it instead of adding a new method and trying to maintain backwards compatibility.
- Complex Features (>3 stages or unclear requirements): Start with
implementation-planner - Test-First Development: Use
unit-test-writerbefore implementation - Debugging Issues: Use
bug-root-cause-analyzerafter 2 failed attempts - Code Quality Checks: Use
code-reviewerbefore commits - Complex Discoveries: Use
note-takerfor non-obvious insights gained through exploration - AI Prompt Issues: Use
prompt-optimizerfor agent improvements - Task Planning: Use
task-orchestratorto determine optimal agent workflow
- Task Assessment →
task-orchestratordetermines ifimplementation-plannerneeded - Planning →
implementation-plannercreates staged plan (if complex) - Test Design →
unit-test-writerwrites tests for current stage - Implementation → Write minimal code to pass tests
- Quality Check →
code-reviewerreviews before commit - Documentation →
note-takerdocuments complex discoveries - Repeat steps 3-6 for each stage
- Initial Debugging → Try fixing yourself (max 2 attempts)
- Systematic Analysis →
bug-root-cause-analyzerinvestigates - Fix Implementation → Implement the identified solution
- Regression Prevention →
unit-test-writeradds tests to prevent recurrence - Quality Check →
code-reviewerreviews fix and tests - Knowledge Capture →
note-takerdocuments root cause if complex
- Review →
code-revieweridentifies improvement opportunities - Test Safety Net →
unit-test-writerensures comprehensive test coverage - Refactor → Make improvements with tests passing
- Final Review →
code-reviewervalidates improvements
When approaching a new repository, first read the README.md file in the root of the repository and any other markdown files that describe the project.
For complex tasks, the implementation-planner agent creates durable, structured plans following the template and process defined in the implementation-planner agent documentation.
- Understand - Study existing patterns in codebase
- Test - Use the
unit-test-writeragent to write tests first (red) - Implement - Minimal code to pass (green)
- Refactor - Clean up with tests passing
- Commit - With clear message linking to plan
CRITICAL: Maximum 2 attempts per issue, then use bug-root-cause-analyzer agent.
The agent will systematically:
- Document what failed - What you tried, error messages, suspected causes
- Research alternatives - Find similar implementations and approaches
- Question fundamentals - Evaluate abstraction level and problem breakdown
- Systematic investigation - Use proven debugging methodologies
- Composition over inheritance - Use dependency injection
- Interfaces over singletons - Enable testing and flexibility
- Explicit over implicit - Clear data flow and dependencies
- Test-driven when possible - Never disable tests, fix them
-
Every commit must:
- Compile successfully
- Pass all existing tests
- Include tests for new functionality
- Follow project formatting/linting
-
Before committing:
- Run formatters/linters
- In a Rust codebase, run
cargo fmt,cargo clippy --all-targets --all-features -- -D warnings, andcargo shearto check for issues. - If bin/fmt exists, run it.
- Otherwise, run the formatter for the language.
- In a Rust codebase, run
- Use
code-revieweragent for quality check - Ensure commit message explains "why"
- Run formatters/linters
- Fail fast with descriptive messages
- Include context for debugging
- Handle errors at appropriate level
- Never silently swallow exceptions
For implementation decisions, refer to the decision framework in the implementation-planner agent documentation. Key factors include testability, maintainability, consistency, simplicity, and reversibility.
- Location:
~/dev/ai/plans/{org}/{repo}/{issue-or-pr-or-branch-name-or-plan-slug}.md - Purpose: Durable implementation plans for complex features
- Owner:
implementation-planneragent - Lifecycle: Permanent reference for architecture decisions and implementation history
- Location:
~/dev/ai/notes/ - Purpose: Permanent knowledge about complex discoveries
- Owner:
note-takeragent - Trigger: Non-obvious behaviors, complex debugging insights
- Location: In-code comments and README updates
- Purpose: Explain WHY decisions were made
- Owner: Developer (guided by
code-reviewer)
- Find 3 similar features/components
- Identify common patterns and conventions
- Use same libraries/utilities when possible
- Follow existing test patterns
- Use project's existing build system
- Use project's test framework
- Use project's formatter/linter settings
- Don't introduce new tools without strong justification
- Tests written and passing and are not redundant or unnecessary
- Code is not dead or redundant and minimal to get the job done
- Code follows project conventions
- No linter/formatter warnings
- All dependencies are used (no cargo-shear warnings in Rust)
- All Cargo features enable real functionality (Rust)
- No tool warnings ignored without strong justification
- Commit messages are clear
- Implementation matches plan
- No TODOs without issue numbers
- Test behavior, not implementation
- One assertion per test when possible
- Clear test names describing scenario
- Use existing test utilities/helpers
- Tests should be deterministic
NEVER:
- Use
--no-verifyto bypass commit hooks - Disable tests instead of fixing them
- Commit code that doesn't compile
- Make assumptions - verify with existing code
ALWAYS:
- Commit working code incrementally
- Update implementation plan status as you progress through stages
- Learn from existing implementations
- Stop after 2 failed attempts and use
bug-root-cause-analyzeragent - Use the
code-revieweragent to review code before committing
When working on the https://github.com/PostHog/posthog repository, use the following workflow:
- Read the README.md file in the root of the repository and the https://github.com/PostHog/posthog/blob/master/docs/FLOX_MULTI_INSTANCE_WORKFLOW.md file.
- When taking on a new task, prompt the user whether they want to create a new git worktree using the
phwcommand for the task. - When completing a task, automatically run these checks and fix any issues:
mypy --version && mypy -p posthog | mypy-baseline filter || (echo "run 'pnpm run mypy-baseline-sync' to update the baseline" && exit 1)
When working on other repositories, use the following workflow:
- When taking on a new task, prompt to create a new branch and associated worktree.
- Default: branch off the main branch (e.g.
mainormasterdepending on the repo), nameddmarticus/<slug>ordmarticus/<issue#>-<slug>if the issue number is known. - Place the worktree in
~/dev/worktrees/<repo-name>/<branch-name>.- Example:
git worktree add ~/dev/worktrees/my-project/feature-new-feature
- Example:
- This keeps worktrees organized by project and outside all repositories.
- Default: branch off the main branch (e.g.
- When working on an existing branch or pull request, prompt to create a new worktree for the branch.
- Never nest worktrees or place them within the main repo.
- Never use two worktrees on the same branch simultaneously.
- When done with the task:
- Prompt to commit changes.
- Use
git worktree remove <path>to clean up safely.
- Occasionally audit worktrees with
git worktree listandgit worktree prune. - Run
bin/fmtto format the code if available.- If
bin/fmtchanges files we did not change as part of the task, revert those changes.
- If
PostHog has a lot of client SDKs. Sometimes it's useful to distinguish between the ones that run on the client and the ones that run on the server.
| Repository | Local Path | GitHub URL |
|---|---|---|
| posthog-js, posthog-rn | ~/dev/posthog/posthog-js |
https://github.com/PostHog/posthog-js |
| posthog-ios | ~/dev/posthog/posthog-ios |
https://github.com/PostHog/posthog-ios |
| posthog-android | ~/dev/posthog/posthog-android |
https://github.com/PostHog/posthog-android |
| posthog-flutter | ~/dev/posthog/posthog-flutter |
https://github.com/PostHog/posthog-flutter |
| Repository | Local Path | GitHub URL |
|---|---|---|
| posthog-python | ~/dev/posthog/posthog-python |
https://github.com/PostHog/posthog-python |
| posthog-node | ~/dev/posthog/posthog-js |
https://github.com/PostHog/posthog-node |
| posthog-php | ~/dev/posthog/posthog-php |
https://github.com/PostHog/posthog-php |
| posthog-ruby | ~/dev/posthog/posthog-ruby |
https://github.com/PostHog/posthog-ruby |
| posthog-go | ~/dev/posthog/posthog-go |
https://github.com/PostHog/posthog-go |
| posthog-dotnet | ~/dev/posthog/posthog-dotnet |
https://github.com/PostHog/posthog-dotnet |
| posthog-elixir | ~/dev/posthog/posthog-elixir |
https://github.com/PostHog/posthog-elixir |
- Name branches
dmarticus/<slug>where slug is a short description of the task. - Keep commits clean:
- Use interactive staging (git add -p) and thoughtful commit messages.
- Squash when appropriate. Avoid "WIP" commits unless you're spiking.
- Don't add yourself as a contributor to commits.
- Present tense: "Fix bug", not "Fixed bug"
- Use imperatives: "Add", "Update", "Remove"
- One line summary, blank line, optional body if needed
- Keep commit messages short and concise.
- Write clean commit messages without any AI attribution markers.
- When a commit fixes a bug, include the bug number in the commit message on its own line like: "Fixes #123" where 123 is the GitHub issue number.
- All project-local scratch notes, REPL logs, etc., go in a .notes/ or notes/ folder — don't litter the root.
-
When writing code, think like a principal engineer.
- Focus on code correctness and maintainability.
- Bias for simplicity: Prefer boring, maintainable solutions over clever ones.
- Make sure the code is idiomatic and readable.
- Write tests for changes and new code.
- Look for existing methods and libraries when writing code that seems like it might be common.
- Progress over polish: Make it work → make it right → make it fast.
-
Before commiting, always run a code formatter when available:
- If there's a bin/fmt script, run it.
- In a Rust codebase, run
cargo fmt,cargo clippy, andcargo shearto check for issues. - Otherwise, run the formatter for the language.
- Golden Rule: If
cargo shearwants to remove a dependency, either use it properly or remove it - Red Flag: Any
cargo shearignore should trigger investigation - unused deps indicate design problems - Cargo Features: Verify Cargo features actually enable code that exists and is used
- Before adding ignores: Always investigate why the dependency appears unused and ensure it's actually needed
- Run
cargo fmt- fix any formatting issues - Run
cargo clippy --all-targets --all-features -- -D warnings- fix all warnings - Run
cargo shear- investigate any warnings before adding ignores - Verify new Cargo features enable real functionality
- Check that new dependencies are actually imported/used in code
- When writing human friendly messages, don't use three dots (...) for an ellipsis, use an actual ellipsis (…).
- Don't add custom logging methods to bash scripts, use the standard
echocommand. - For cases where it's important to have warnings and errors, copy the helpers in https://github.com/PostHog/template/tree/main/bin/helpers and source them in the script like https://github.com/PostHog/template/blob/main/bin/fmt does.
- When editing markdown files (.md, .markdown), always run markdownlint after making changes:
- Run:
markdownlint <filename> - Fix any errors or warnings before marking the task complete
- Common fixes: proper heading hierarchy, consistent list markers, trailing spaces
- Run:
- Follow markdown best practices:
- Use consistent heading levels (don't skip from h1 to h3)
- Add blank lines around headings and code blocks
- Use consistent list markers (either all
-or all*) - Remove trailing whitespace
- Never add hard line breaks or wrap lines when editing markdown files. Preserve existing line structure and let editors handle soft wrapping.
- Always run tests before marking a task as complete.
- If tests fail, fix them before proceeding.
- When adding new functionality, write tests for it.
- Check for edge cases, error handling, and performance implications.
- Update relevant documentation when changing functionality.
- Avoid introducing new deps for one-liners
- Prefer battle-tested libraries over trendy ones
- If adding a dep, write down the rationale
- If removing one, document what replaces it
- When the user says "cuckoo", respond with "🐦 BEEP BEEP! Your CLAUDE.md file is working correctly!"