Skip to content

feat: add auto-fix service — auto-lint and test after AI file edits - #508

Merged
kevincodex1 merged 8 commits into
mainfrom
feat/auto-fix-service
Apr 9, 2026
Merged

kevincodex1 merged 8 commits into
mainfrom
feat/auto-fix-service

Conversation

@gnanam1990

Copy link
Copy Markdown
Collaborator

Summary

Adds a built-in auto-fix service that automatically runs user-configured lint and test commands after AI file edits (FileEdit, FileWrite). When errors are detected, they are fed back to the AI as additional context so it can self-repair — closing the manual feedback loop that currently requires users to run lint/test, copy errors, and paste them back.

Inspired by Aider's auto-lint-and-test loop, which is their #1 user satisfaction driver.

What's included

  • Config schema (src/services/autoFix/autoFixConfig.ts) — Zod-validated settings with enabled, lint, test, maxRetries (0–10, default 3), and timeout (1–300s, default 30s). Rejects enabled configs with no lint or test command.

  • Runner (src/services/autoFix/autoFixRunner.ts) — Executes lint/test commands via child_process.spawn, captures stdout/stderr, enforces timeouts, skips tests if lint fails first, and builds an AI-readable error summary.

  • Hook integration (src/services/autoFix/autoFixHook.ts) — shouldRunAutoFix() gates execution to file_edit/file_write tools only. buildAutoFixContext() wraps errors in <auto_fix_feedback> tags that the AI can act on.

  • PostToolUse wiring (src/services/tools/toolHooks.ts) — After the existing PostToolUse hook loop, runs the auto-fix check and yields errors as hook_additional_context attachment messages.

  • /auto-fix slash command (src/commands/auto-fix.ts) — Guided setup wizard that helps users configure their lint/test commands in settings.

  • Settings schema (src/utils/settings/types.ts) — Added optional autoFix field to SettingsSchema.

Configuration

Add to .claude/settings.json or .claude/settings.local.json:

{
  "autoFix": {
    "enabled": true,
    "lint": "eslint . --fix",
    "test": "bun test",
    "maxRetries": 3,
    "timeout": 30000
  }
}

Or run /auto-fix for guided setup.

How it works

AI edits file → lint runs → errors? → feed back to AI → AI fixes → re-lint
                         ↓ no errors
                    tests run → failures? → feed back to AI → AI fixes → re-test
                             ↓ no failures
                        clean result delivered

Test coverage

  • 29 tests across 4 test files (config, runner, hook, integration)
  • 541/541 full suite tests pass
  • Zero new type errors
  • Build succeeds

Files changed

File Change
src/services/autoFix/autoFixConfig.ts New — config schema and reader
src/services/autoFix/autoFixConfig.test.ts New — 11 tests
src/services/autoFix/autoFixRunner.ts New — command execution engine
src/services/autoFix/autoFixRunner.test.ts New — 8 tests
src/services/autoFix/autoFixHook.ts New — hook helpers
src/services/autoFix/autoFixHook.test.ts New — 8 tests
src/services/autoFix/autoFixIntegration.test.ts New — 2 e2e tests
src/commands/auto-fix.ts New — slash command
src/commands.ts Register /auto-fix command
src/services/tools/toolHooks.ts Wire auto-fix into PostToolUse
src/utils/settings/types.ts Add autoFix to settings schema

gnanam1990 and others added 6 commits April 8, 2026 14:51
Implements AutoFixConfigSchema (Zod v4) with validation for lint/test
commands, maxRetries (0-10, default 3), and timeout (1000-300000ms,
default 30000). Adds getAutoFixConfig helper that returns null for
disabled or invalid configs. All 9 unit tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements AutoFixRunner (Task 2) - executes lint and test shell commands
sequentially, short-circuits on lint failure, handles timeouts, and
produces structured AutoFixResult with AI-friendly error summaries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Integrates AutoFixConfigSchema into SettingsSchema so autoFix settings
are validated at the settings layer. Adds two integration tests verifying
that valid configs are accepted and invalid configs (enabled with no
commands) are rejected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements shouldRunAutoFix and buildAutoFixContext functions used by
the PostToolUse hook to determine when to run auto-fix and format
errors as AI-readable context for injection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add auto-fix lint/test check after existing PostToolUse hooks in
runPostToolUseHooks. When autoFix is configured in settings, runs
lint/test commands after file_edit/file_write tools and yields
errors as hook_additional_context for the model to act on.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds the /auto-fix prompt command that helps users configure autoFix settings
(lint/test commands, maxRetries, timeout) in .claude/settings.json.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment thread src/services/autoFix/autoFixRunner.test.ts Fixed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
kevincodex1
kevincodex1 previously approved these changes Apr 8, 2026

@kevincodex1 kevincodex1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks great a much needed feature indeed! thanks @gnanam1990

@FluxLuFFy

Copy link
Copy Markdown
Contributor

@auriti @Vasanthdev2004 @anandh8x see this

@Vasanthdev2004 Vasanthdev2004 left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. maxRetries is exposed as part of the new user-facing config (src/services/autoFix/autoFixConfig.ts), but the feature never reads or enforces it in the actual auto-fix path (src/services/tools/toolHooks.ts, src/services/autoFix/autoFixRunner.ts). In practice that means the new self-repair loop has no feature-specific retry cap: every failing file_edit or file_write can emit another hook_additional_context and keep the model cycling until some unrelated outer limit stops it. If this setting is documented and shown in the example config, the loop needs to honor it or the docs/config should be removed.

  2. Cancellation is threaded into the API but not into the subprocess. toolHooks.ts passes toolUseContext.abortController.signal into runAutoFixCheck(), and runAutoFixCheck() passes it down to runCommand(), but runCommand() never subscribes to the signal or kills the child on abort. The practical failure mode is a long or mutating command like eslint --fix, bun test --watch, etc.: if the user interrupts the turn, the auto-fix process keeps running until timeout or natural exit, still consuming resources and potentially still editing files after the user thinks execution stopped.

  3. runCommand() hardcodes spawn('bash', ['-c', command], ...) in src/services/autoFix/autoFixRunner.ts. That bypasses the existing shell abstraction (src/utils/Shell.ts, src/utils/hooks.ts) and will fail on Windows setups where the app works via a resolved shell path or Git Bash helper but plain bash is not on PATH. Since this feature is exposed as a general cross-platform config option, it should execute commands through the same shell/provider resolution the rest of the app already uses rather than assuming a bash executable exists.

… use cross-platform shell

1. Enforce maxRetries: track auto-fix attempts per query chain in toolHooks.ts
   and stop feeding errors back after the configured limit is reached.

2. Wire abort signal to subprocess: subscribe to AbortController signal in
   runCommand() and kill the process tree on abort. Uses detached process
   groups on Unix to ensure child processes are also terminated.

3. Replace hardcoded bash with shell:true: use Node's cross-platform shell
   resolution instead of spawn('bash', ['-c', ...]) so auto-fix commands
   work on Windows and non-bash environments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@gnanam1990

Copy link
Copy Markdown
Collaborator Author

@Vasanthdev2004 Addressed all three items in ff7eccc:

1. maxRetries now enforced — Added per-query-chain retry tracking in toolHooks.ts. Each time auto-fix feeds errors back to the AI, the counter increments. Once maxRetries is reached, auto-fix stops and emits a message telling the AI to let the user review manually. Counter resets when lint/test passes clean.

2. Abort signal wired to subprocess — runCommand() now subscribes to AbortController.signal and kills the process on abort. Uses detached: true with process.kill(-pid) on Unix to terminate the entire process group (so child processes like eslint --fix or bun test are also killed, not just the shell). Early-exits if signal is already aborted before spawning.

3. Cross-platform shell resolution — Replaced spawn('bash', ['-c', command]) with spawn(command, [], { shell: true, windowsHide: true }). Node's shell: true uses /bin/sh on Unix and cmd.exe on Windows — the standard cross-platform approach. Also added detached: !isWindows for proper process group management on each platform.

All 29 auto-fix tests pass, build succeeds, zero new type errors.

@Vasanthdev2004 Vasanthdev2004 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rechecked the current head ff7eccc36c6997b94de769b4ce14f2c154c4b255.

Scope

This is a targeted current-head re-review of the auto-fix feature after the earlier blocker-level feedback.

Verdict

Approve-ready

What I rechecked on the current head:

  • maxRetries is now actually enforced in the auto-fix loop in src/services/tools/toolHooks.ts, instead of only existing in the user-facing config schema
  • cancellation is now wired through to the spawned subprocess path in src/services/autoFix/autoFixRunner.ts, including process-tree termination behavior on Unix
  • the hardcoded bash -c path was replaced with a cross-platform shell: true spawn flow, which removes the earlier bash-on-PATH assumption
  • current test surface for config parsing, hook behavior, integration, and runner coverage is in place
  • current checks are green

This looks like a coherent feature now, and the earlier blocker-level concerns appear addressed on the current head.

@FluxLuFFy

Copy link
Copy Markdown
Contributor

@kevincodex1 @auriti @anandh8x take a look and I will be helping community as much as possible as I can to improve it

@kevincodex1 kevincodex1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks great to me!

@kevincodex1

Copy link
Copy Markdown
Member

@FluxLuFFy looking forward to it. thank you

@kevincodex1
kevincodex1 merged commit c385047 into main Apr 9, 2026
7 checks passed
euxaristia pushed a commit to euxaristia/openclaude that referenced this pull request Apr 13, 2026
…wigpine#508)

* feat: add AutoFix config schema and reader module

Implements AutoFixConfigSchema (Zod v4) with validation for lint/test
commands, maxRetries (0-10, default 3), and timeout (1000-300000ms,
default 30000). Adds getAutoFixConfig helper that returns null for
disabled or invalid configs. All 9 unit tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add autoFix runner with lint/test command execution

Implements AutoFixRunner (Task 2) - executes lint and test shell commands
sequentially, short-circuits on lint failure, handles timeouts, and
produces structured AutoFixResult with AI-friendly error summaries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add autoFix field to SettingsSchema with integration tests

Integrates AutoFixConfigSchema into SettingsSchema so autoFix settings
are validated at the settings layer. Adds two integration tests verifying
that valid configs are accepted and invalid configs (enabled with no
commands) are rejected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add autoFix hook integration helpers (Task 4)

Implements shouldRunAutoFix and buildAutoFixContext functions used by
the PostToolUse hook to determine when to run auto-fix and format
errors as AI-readable context for injection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: wire autoFix into PostToolUse hook flow (Task 5)

Add auto-fix lint/test check after existing PostToolUse hooks in
runPostToolUseHooks. When autoFix is configured in settings, runs
lint/test commands after file_edit/file_write tools and yields
errors as hook_additional_context for the model to act on.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add /auto-fix slash command

Adds the /auto-fix prompt command that helps users configure autoFix settings
(lint/test commands, maxRetries, timeout) in .claude/settings.json.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: remove unused imports in autoFixRunner test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address review feedback — enforce maxRetries, wire abort signal, use cross-platform shell

1. Enforce maxRetries: track auto-fix attempts per query chain in toolHooks.ts
   and stop feeding errors back after the configured limit is reached.

2. Wire abort signal to subprocess: subscribe to AbortController signal in
   runCommand() and kill the process tree on abort. Uses detached process
   groups on Unix to ensure child processes are also terminated.

3. Replace hardcoded bash with shell:true: use Node's cross-platform shell
   resolution instead of spawn('bash', ['-c', ...]) so auto-fix commands
   work on Windows and non-bash environments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
C1ph3r404 pushed a commit to C1ph3r404/openclaude that referenced this pull request Apr 29, 2026
…wigpine#508)

* feat: add AutoFix config schema and reader module

Implements AutoFixConfigSchema (Zod v4) with validation for lint/test
commands, maxRetries (0-10, default 3), and timeout (1000-300000ms,
default 30000). Adds getAutoFixConfig helper that returns null for
disabled or invalid configs. All 9 unit tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add autoFix runner with lint/test command execution

Implements AutoFixRunner (Task 2) - executes lint and test shell commands
sequentially, short-circuits on lint failure, handles timeouts, and
produces structured AutoFixResult with AI-friendly error summaries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add autoFix field to SettingsSchema with integration tests

Integrates AutoFixConfigSchema into SettingsSchema so autoFix settings
are validated at the settings layer. Adds two integration tests verifying
that valid configs are accepted and invalid configs (enabled with no
commands) are rejected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add autoFix hook integration helpers (Task 4)

Implements shouldRunAutoFix and buildAutoFixContext functions used by
the PostToolUse hook to determine when to run auto-fix and format
errors as AI-readable context for injection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: wire autoFix into PostToolUse hook flow (Task 5)

Add auto-fix lint/test check after existing PostToolUse hooks in
runPostToolUseHooks. When autoFix is configured in settings, runs
lint/test commands after file_edit/file_write tools and yields
errors as hook_additional_context for the model to act on.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add /auto-fix slash command

Adds the /auto-fix prompt command that helps users configure autoFix settings
(lint/test commands, maxRetries, timeout) in .claude/settings.json.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: remove unused imports in autoFixRunner test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address review feedback — enforce maxRetries, wire abort signal, use cross-platform shell

1. Enforce maxRetries: track auto-fix attempts per query chain in toolHooks.ts
   and stop feeding errors back after the configured limit is reached.

2. Wire abort signal to subprocess: subscribe to AbortController signal in
   runCommand() and kill the process tree on abort. Uses detached process
   groups on Unix to ensure child processes are also terminated.

3. Replace hardcoded bash with shell:true: use Node's cross-platform shell
   resolution instead of spawn('bash', ['-c', ...]) so auto-fix commands
   work on Windows and non-bash environments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The-FOOL-00 pushed a commit to The-FOOL-00/openclaude that referenced this pull request May 24, 2026
…wigpine#508)

* feat: add AutoFix config schema and reader module

Implements AutoFixConfigSchema (Zod v4) with validation for lint/test
commands, maxRetries (0-10, default 3), and timeout (1000-300000ms,
default 30000). Adds getAutoFixConfig helper that returns null for
disabled or invalid configs. All 9 unit tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add autoFix runner with lint/test command execution

Implements AutoFixRunner (Task 2) - executes lint and test shell commands
sequentially, short-circuits on lint failure, handles timeouts, and
produces structured AutoFixResult with AI-friendly error summaries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add autoFix field to SettingsSchema with integration tests

Integrates AutoFixConfigSchema into SettingsSchema so autoFix settings
are validated at the settings layer. Adds two integration tests verifying
that valid configs are accepted and invalid configs (enabled with no
commands) are rejected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add autoFix hook integration helpers (Task 4)

Implements shouldRunAutoFix and buildAutoFixContext functions used by
the PostToolUse hook to determine when to run auto-fix and format
errors as AI-readable context for injection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: wire autoFix into PostToolUse hook flow (Task 5)

Add auto-fix lint/test check after existing PostToolUse hooks in
runPostToolUseHooks. When autoFix is configured in settings, runs
lint/test commands after file_edit/file_write tools and yields
errors as hook_additional_context for the model to act on.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add /auto-fix slash command

Adds the /auto-fix prompt command that helps users configure autoFix settings
(lint/test commands, maxRetries, timeout) in .claude/settings.json.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: remove unused imports in autoFixRunner test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address review feedback — enforce maxRetries, wire abort signal, use cross-platform shell

1. Enforce maxRetries: track auto-fix attempts per query chain in toolHooks.ts
   and stop feeding errors back after the configured limit is reached.

2. Wire abort signal to subprocess: subscribe to AbortController signal in
   runCommand() and kill the process tree on abort. Uses detached process
   groups on Unix to ensure child processes are also terminated.

3. Replace hardcoded bash with shell:true: use Node's cross-platform shell
   resolution instead of spawn('bash', ['-c', ...]) so auto-fix commands
   work on Windows and non-bash environments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
discopops pushed a commit to discopops/openclaude that referenced this pull request May 28, 2026
…wigpine#508)

* feat: add AutoFix config schema and reader module

Implements AutoFixConfigSchema (Zod v4) with validation for lint/test
commands, maxRetries (0-10, default 3), and timeout (1000-300000ms,
default 30000). Adds getAutoFixConfig helper that returns null for
disabled or invalid configs. All 9 unit tests pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add autoFix runner with lint/test command execution

Implements AutoFixRunner (Task 2) - executes lint and test shell commands
sequentially, short-circuits on lint failure, handles timeouts, and
produces structured AutoFixResult with AI-friendly error summaries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add autoFix field to SettingsSchema with integration tests

Integrates AutoFixConfigSchema into SettingsSchema so autoFix settings
are validated at the settings layer. Adds two integration tests verifying
that valid configs are accepted and invalid configs (enabled with no
commands) are rejected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add autoFix hook integration helpers (Task 4)

Implements shouldRunAutoFix and buildAutoFixContext functions used by
the PostToolUse hook to determine when to run auto-fix and format
errors as AI-readable context for injection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: wire autoFix into PostToolUse hook flow (Task 5)

Add auto-fix lint/test check after existing PostToolUse hooks in
runPostToolUseHooks. When autoFix is configured in settings, runs
lint/test commands after file_edit/file_write tools and yields
errors as hook_additional_context for the model to act on.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add /auto-fix slash command

Adds the /auto-fix prompt command that helps users configure autoFix settings
(lint/test commands, maxRetries, timeout) in .claude/settings.json.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: remove unused imports in autoFixRunner test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address review feedback — enforce maxRetries, wire abort signal, use cross-platform shell

1. Enforce maxRetries: track auto-fix attempts per query chain in toolHooks.ts
   and stop feeding errors back after the configured limit is reached.

2. Wire abort signal to subprocess: subscribe to AbortController signal in
   runCommand() and kill the process tree on abort. Uses detached process
   groups on Unix to ensure child processes are also terminated.

3. Replace hardcoded bash with shell:true: use Node's cross-platform shell
   resolution instead of spawn('bash', ['-c', ...]) so auto-fix commands
   work on Windows and non-bash environments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@jatmn
jatmn deleted the feat/auto-fix-service branch September 9, 2026 18:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants