Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ TDD Guard ensures Claude Code follows Test-Driven Development principles. When y
- **Test-First Enforcement** - Blocks implementation without failing tests
- **Minimal Implementation** - Prevents code beyond current test requirements
- **Lint Integration** - Enforces refactoring using your linting rules
- **Multi-Language Support** - TypeScript, JavaScript, Python, PHP, Go, and Rust
- **Multi-Language Support** - TypeScript, JavaScript, Python, PHP, Go, Rust, and Nix
- **Customizable Rules** - Adjust validation rules to match your TDD style
- **Flexible Validation** - Choose faster or more capable models for your needs
- **Session Control** - Toggle on and off mid-session
Expand All @@ -33,7 +33,7 @@ TDD Guard ensures Claude Code follows Test-Driven Development principles. When y

- Node.js 18+
- Claude Code or Anthropic API key
- Test framework (Jest, Vitest, pytest, PHPUnit, Go 1.24+, or Rust with cargo/cargo-nextest)
- Test framework (Jest, Vitest, pytest, PHPUnit, Go 1.24+, Rust with cargo/cargo-nextest, or nix-unit)

## Quick Start

Expand Down Expand Up @@ -312,7 +312,7 @@ If you prefer to edit settings files directly, add all three hooks to your chose
## Additional Configuration

- [Custom instructions](docs/custom-instructions.md) - Customize TDD validation rules
- [Lint integration](docs/linting.md) - Automated refactoring support
- [Lint integration](docs/linting.md) - Automated refactoring support (ESLint, Statix)
- [Strengthening enforcement](docs/enforcement.md) - Prevent agents from bypassing validation
- [Ignore patterns](docs/ignore-patterns.md) - Control which files are validated
- [Validation Model](docs/validation-model.md) - Choose faster or more capable model
Expand Down
1 change: 1 addition & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ See the [Quick Start guide](../README.md#3-configure-claude-code-hooks) in the m
- **PHP**: See [PHPUnit reporter configuration](../reporters/phpunit/README.md#configuration)
- **Go**: See [Go reporter configuration](../reporters/go/README.md#configuration)
- **Rust**: See [Rust reporter configuration](../reporters/rust/README.md#configuration)
- **Nix**: See [Nix reporter configuration](../reporters/nix/README.md)

## Custom Validation Rules

Expand Down
99 changes: 90 additions & 9 deletions docs/linting.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Linting and Refactoring Support

TDD Guard can optionally check code quality during the refactoring phase (when tests are green) using ESLint.
TDD Guard can optionally check code quality during the refactoring phase (when tests are green) using linters like ESLint or Statix.
When issues are detected, the coding agent will be prompted to fix them.

## Why Use Refactoring Support?
Expand All @@ -14,27 +14,61 @@ During the TDD green phase, the coding agent may:

The refactoring support helps by:

- Running ESLint automatically after file modifications
- Running your configured linter automatically after file modifications
- Detecting code quality issues
- Prompting the coding agent to fix any issues found

## Setup

### For JavaScript/TypeScript Projects (ESLint)

1. **Install ESLint** in your project:

```bash
npm install --save-dev eslint@latest
```

2. **Enable linting** by setting the environment variable:
2. **Enable ESLint** by setting the environment variable:

```bash
LINTER_TYPE=eslint
```

Note: Currently only ESLint is supported. Additional linters may be added in the future.
### For Nix Projects (Statix)

1. **Install Statix** using Nix:

```bash
# Install globally
nix profile install nixpkgs#statix

# Or run directly
nix run nixpkgs#statix -- --help

# Or add to your project's flake.nix
buildInputs = [ pkgs.statix ];
```

2. **Enable Statix** by setting the environment variable:

3. **Configure the PostToolUse hook**
```bash
LINTER_TYPE=statix
```

3. **Optional: Configure Statix** by creating a `statix.toml` file in your project root:

```toml
# Customize which lints to enable/disable
disabled = []

# Files to ignore
ignore = [
"generated.nix",
"vendor/*.nix"
]
```

### Hook Configuration

You can configure this hook either through the interactive `/hooks` command or by manually editing your settings file. See [Settings File Locations](configuration.md#settings-file-locations) to choose the appropriate location. Use the same location as your PreToolUse hook.

Expand Down Expand Up @@ -74,17 +108,19 @@ The refactoring support helps by:
When enabled:

1. After any file modification (Edit, MultiEdit, Write)
2. TDD Guard runs ESLint on modified files
2. TDD Guard runs your configured linter on modified files
3. If issues are found, the coding agent receives a notification
4. The agent will then fix the identified issues

Without `LINTER_TYPE=eslint`, TDD Guard skips all linting operations.
Without setting `LINTER_TYPE`, TDD Guard skips all linting operations.

## Linter Configuration

### ESLint Configuration

**Tip**: Configure ESLint with complexity rules (e.g., `complexity`, `max-depth`) and the SonarJS plugin to encourage meaningful refactoring.
These rules help identify code that could benefit from simplification during the green phase.

## ESLint Configuration

For effective refactoring support, consider adding these rules to your `.eslintrc.js`:

```javascript
Expand All @@ -99,6 +135,36 @@ module.exports = {
}
```

### Statix Configuration

Statix comes with sensible defaults, but you can customize it with a `statix.toml` configuration file:

```toml
# Enable all lints by default, disable specific ones if needed
disabled = [
# "empty_let_in", # Allow empty let...in expressions
# "manual_inherit", # Allow manual inherit statements
]

# Files or patterns to ignore during linting
ignore = [
"shell.nix", # Generated files
"vendor/*.nix", # Third-party code
".direnv/**", # Build artifacts
]
```

**Available Statix Rules:**
- `bool_comparison` - Detects unnecessary boolean comparisons
- `empty_let_in` - Finds empty let...in expressions
- `manual_inherit` - Suggests automatic inheritance
- `legacy_let_syntax` - Modernizes let syntax
- `eta_reduction` - Suggests eta reduction opportunities
- `useless_parens` - Removes unnecessary parentheses
- `empty_pattern` - Detects empty patterns
- `unquoted_uri` - Suggests proper URI quoting
- And more...

## Troubleshooting

### ESLint Not Running
Expand All @@ -107,3 +173,18 @@ module.exports = {
2. Check that `LINTER_TYPE=eslint` is set in your `.env` file
3. Ensure the PostToolUse hook is configured
4. Restart your Claude session after making changes

### Statix Not Running

1. Verify Statix is installed: `statix --version`
2. Check that `LINTER_TYPE=statix` is set in your `.env` file
3. Ensure you have nix-unit available for JSON output (if required)
4. Verify your `.nix` files are syntactically correct
5. Restart your Claude session after making changes

### General Linting Issues

- **No linter output**: Ensure files you're editing match the linter's file patterns
- **Permission errors**: Make sure the linter binary is executable
- **Configuration errors**: Check your linter config file syntax
- **Path issues**: Verify the linter is available in your `$PATH`
Loading