Skip to content
Ultracite
Esc
↑↓navigate↵open⌘Jpreview

CodeBuddy, where lint errors go back to the agent

ultracite init --editors codebuddy writes .vscode/settings.json, so CodeBuddy formats on save and applies safe fixes through the Oxc, Biome or ESLint extension from Open VSX. --hooks codebuddy adds a PostToolUse hook, and what ultracite fix leaves behind goes back to the agent. The agent reads AGENTS.md only when the project has no CODEBUDDY.md.

CodeBuddy by TencentChecked against CodeBuddy 4.12.1

{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnPaste": true,
  "editor.formatOnSave": true,Format on save
  "emmet.showExpandedAbbreviation": "never",
  "js/ts.tsdk.path": "node_modules/typescript/lib",The project’s TypeScript
  "js/ts.tsdk.promptToUseWorkspaceVersion": true,
  "[astro]": {
    "editor.defaultFormatter": "astro-build.astro-vscode"
  },
  "[css]": {
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "[graphql]": {
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "[handlebars]": {
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "[html]": {
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "[javascript]": {
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "[javascriptreact]": {
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "[json]": {
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "[jsonc]": {
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "[less]": {
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "[markdown]": {
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "[scss]": {
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "[typescript]": {Oxfmt formats it
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "[vue-html]": {
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "[vue]": {
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "[yaml]": {
    "editor.defaultFormatter": "oxc.oxc-vscode"
  },
  "editor.codeActionsOnSave": {
    "source.fixAll.oxc": "explicit"Oxlint’s safe fixes
  },
  "typescript.enablePromptUseWorkspaceTsdk": true,
  "typescript.tsdk": "node_modules/typescript/lib"
}
Oxlint + Oxfmt
What init does in CodeBuddy
  1. 1Writes .vscode/settings.jsonA new file, or merged into yours setting by setting, with your comments and other settings kept.
  2. 2Installs oxc.oxc-vscodeWith buddy --install-extension, when it creates the settings file.
  3. 3With --hooks codebuddy, writes .codebuddy/settings.jsonRuns npx ultracite fix --hook on each file CodeBuddy’s agent edits.
Then, in CodeBuddy
  1. 4If init couldn’t run buddy, install oxc.oxc-vscode from the Extensions view, or Biome’s if you picked Biome. CodeBuddy installs extensions from Open VSX.
  2. 5Start a new chat, so the agent loads the rules and, with --hooks codebuddy, the hook in .codebuddy/settings.json.
  3. 6Save a file: Oxfmt formats it and Oxlint’s safe fixes apply.

Three toolchains, one settings.json

init writes the settings for the toolchain you pick, so CodeBuddy formats with the same tool as ultracite fix and applies its fixes when you save.

  • Oxlint + OxfmtDefault

    Extension
    oxc.oxc-vscode
    Formats with
    oxc.oxc-vscode
    On save
    source.fixAll.oxc

    --linter oxlint

  • Biome

    Extension
    biomejs.biome
    Formats with
    biomejs.biome
    On save
    source.fixAll.biomesource.organizeImports.biome

    --linter biome

  • ESLint + Prettier + Stylelint

    Extensions
    dbaeumer.vscode-eslintesbenp.prettier-vscode
    Formats with
    esbenp.prettier-vscode
    On save
    source.fixAll.eslintsource.organizeImports

    --linter eslint

How CodeBuddy runs your linter

CodeBuddy is a VS Code build that installs extensions from Open VSX and applies the .vscode/settings.json that init writes. Its agent keeps its own settings, hooks included, under .codebuddy/.

Extension gallery
Open VSX. CodeBuddy’s build points its gallery at open-vsx.org, which has oxc.oxc-vscode, biomejs.biome, dbaeumer.vscode-eslint and esbenp.prettier-vscode.
Launcher
The IDE’s own launcher is buddy, built from VS Code’s command-line tool, and init installs the extension with buddy --install-extension. codebuddy on your PATH is CodeBuddy Code, the agent CLI.
VS Code base
CodeBuddy 4.12.1 is built on VS Code 1.106, which predates js/ts.tsdk.path, so for CodeBuddy init also writes typescript.tsdk.
Two settings files
.codebuddy/settings.json holds the agent’s hooks. Editor settings, including the ones init writes, stay in .vscode/settings.json.
New sessions
Rules are added when a chat session starts, so start a new chat after init or after editing a rule. CodeBuddy’s hook guide also starts a new session to test a hook.
Hook timeout
CodeBuddy stops a hook when its timeout, in seconds, runs out. The default is 60; the hook init writes sets 20.

The hook’s leftovers go back to the agent

CodeBuddy’s hooks follow Claude Code’s format: PostToolUse runs after a tool finishes, matcher is a regex on the tool name, and exit code 2 passes stderr to the agent. The hook from --hooks codebuddy uses all three, so whatever ultracite fix can’t fix goes back to the agent. Rules come from .codebuddy/rules/ and one root file: CODEBUDDY.md, or AGENTS.md when there isn’t one.

Where the agent looks for instructions
  1. 1User rulesYour own rules from the Rules tab in settings, applied in every project and kept out of version control.
  2. 2.codebuddy/rules/Project rules, one folder per rule with a RULE.mdc. Always rules load in full, Agent Requested rules when the agent finds them relevant, and Manual rules when you @-mention them.
  3. 3CODEBUDDY.md, .codebuddy/CODEBUDDY.mdThe root file CodeBuddy checks first, loaded in full. Its /init command writes CODEBUDDY.md, and while either file exists AGENTS.md isn’t loaded.
  4. 4AGENTS.mdUltraciteLoaded in full when the project has no CODEBUDDY.md. Where init writes Ultracite’s rules.
{
  "hooks": {
    "PostToolUse": [
      {
        "hooks": [
          {
            "command": "npx ultracite fix --hook",
            "timeout": 20,
            "type": "command"
          }
        ],
        "matcher": "Write|Edit"
      }
    ]
  }
}
init --hooks codebuddy
  1. 01The agent writes a file with write_to_file or replace_in_file, which the hook’s Write|Edit matcher covers.
  2. 02CodeBuddy runs npx ultracite fix --hook with the edit as JSON on stdin, and it fixes and formats that one file.
  3. 03If problems are left, the hook exits with 2 and CodeBuddy passes its stderr to the agent, which fixes them next.
  4. 04The agent can also call its read_lints tool to read the diagnostics the Oxc, Biome or ESLint extension reports.

Worth knowing about CodeBuddy

  • /init hides AGENTS.md

    CodeBuddy’s /init slash command generates a CODEBUDDY.md, and from then on the agent stops loading AGENTS.md. Move Ultracite’s rules into that file, or delete it.

  • Skills from .codebuddy/skills

    CodeBuddy loads skills from .codebuddy/skills/. --hooks codebuddy creates the .codebuddy folder, so when init installs the Ultracite skill, it puts a copy there as well as in .agents/skills/.

  • Hooks run in parallel

    When several hooks match a tool call, CodeBuddy runs them in parallel and drops identical commands, so a hook can’t count on another one finishing first.

CodeBuddy questions, answered

Does Ultracite work with CodeBuddy?
Yes. npx ultracite init --editors codebuddy writes .vscode/settings.json for Oxlint and Oxfmt, Biome, or ESLint and Prettier, and --hooks codebuddy adds a PostToolUse hook to .codebuddy/settings.json that fixes each file the agent writes.
Does CodeBuddy read AGENTS.md?
Only when the project has no CODEBUDDY.md. CodeBuddy loads one root instruction file, and CODEBUDDY.md comes first, so running /init in CodeBuddy hides Ultracite’s AGENTS.md.
Why didn’t init install the Oxc extension in CodeBuddy?
init installs it with the IDE’s own command, buddy, only when it creates .vscode/settings.json and only if buddy is on your PATH. (codebuddy is CodeBuddy Code, the agent CLI.) Otherwise, install it from the Extensions view.
How does the CodeBuddy hook tell the agent about lint errors?
Through the exit code. ultracite fix --hook exits with 2 when problems remain, and CodeBuddy treats 2 as a blocking error: it passes the hook’s stderr to the agent. Any other non-zero code only shows a warning.
Where does CodeBuddy read hooks from?
From .codebuddy/settings.json in the project and ~/.codebuddy/settings.json in your home folder, and the project file takes priority. init --hooks codebuddy writes the project one.

Ship less slop

One command sets up your linter, formatter, editor and agents. Works with Oxlint, Biome and ESLint.