This is the full developer documentation for OpenFiles # OpenFiles > Your AI wrote it. Your linter never saw it. OpenFiles opens every file your agent touches, lets your linters run, and hands the problems back to the agent. ## The gap [Section titled “The gap”](#the-gap) Claude Code, Codex, Copilot, Gemini CLI and OpenCode write files directly to disk. Most of VS Code’s language servers, including TypeScript, ESLint, Pylance and C#, only report problems for files that are open. When an agent changes twenty files, nothing checks them. Opens what the agent touched A file watcher and agent hooks catch every write. Files open in background tabs, so your linters run. A review list, not a surprise The AI Edits sidebar gives every changed file a checkbox and a problem count. Changed again? It unchecks itself. Linters talk back Hooks wait a few seconds for diagnostics, then hand the errors to Claude Code, Codex, Copilot, Gemini CLI or Cursor in the same turn. Any agent, any VS Code Works in VS Code, Cursor, Windsurf, VSCodium, Antigravity and Kiro. Agents without hooks are covered by the watcher. ## For agents [Section titled “For agents”](#for-agents) This site publishes [`/llms.txt`](llms.txt) and [`/llms-full.txt`](llms-full.txt). Every page has a **Copy Markdown** button, so you can paste a page straight into your agent. # Getting started > Install OpenFiles, connect your agent and review your first AI edit in about two minutes. ## 1. Install [Section titled “1. Install”](#1-install) * **VS Code:** [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=devgiordane.openfiles), or run `code --install-extension devgiordane.openfiles` * **Cursor, Windsurf, VSCodium, Antigravity, Kiro:** [Open VSX](https://open-vsx.org/extension/devgiordane/openfiles). Search “OpenFiles” in the Extensions view. OpenFiles needs VS Code 1.93 or a fork based on it. ## 2. Open the walkthrough [Section titled “2. Open the walkthrough”](#2-open-the-walkthrough) Run **OpenFiles: Get Started** from the Command Palette. It walks through the steps below, and you can skip any of them. ## 3. Pick a mode [Section titled “3. Pick a mode”](#3-pick-a-mode) | `openfiles.mode` | What happens when an agent writes a file | | ---------------- | ---------------------------------------------------------------------------- | | `open` (default) | Opens it in a background tab. Your language servers check it right away. | | `queue` | Lists it in the sidebar only. Most linters won’t check it until you open it. | | `notify` | Shows a notification with an **Open** button. | ## 4. Connect your agent (optional, recommended) [Section titled “4. Connect your agent (optional, recommended)”](#4-connect-your-agent-optional-recommended) Run **OpenFiles: Install Agent Hooks…**, then pick the agents you use. OpenFiles shows a diff of each config file and writes nothing until you confirm. Hooks give you two things the watcher can’t: 1. **Attribution.** You know which agent changed which file. 2. **Feedback.** After each edit, the agent receives the errors your linters found. Hooks run `node`, so Node.js must be on your PATH. See the page for your agent: [Claude Code](../agents/claude-code/), [Codex CLI](../agents/codex/), [GitHub Copilot](../agents/copilot/), [Gemini CLI](../agents/gemini-cli/), [Cursor](../agents/cursor/), [other agents](../agents/other/). ## 5. Check your linters [Section titled “5. Check your linters”](#5-check-your-linters) Run **OpenFiles: Run Doctor**. It lists the languages in your repo that have no extension checking them, and links the ones to install. In Cursor, Windsurf and VSCodium it suggests Open VSX alternatives, because Pylance, C# Dev Kit and the Microsoft C/C++ extension aren’t published there. ## 6. Let the agent work [Section titled “6. Let the agent work”](#6-let-the-agent-work) Ask your agent to change something. You’ll see: * the changed files open without stealing focus; * an **AI** badge on those files in the Explorer; * the **AI Edits** view in the OpenFiles sidebar, with a checkbox and problem count per file; * the status bar item showing unreviewed files, errors and warnings. Run **OpenFiles: Review Next Changed File** to go through them. It marks the current file reviewed and opens the next one, with files that have errors first. # How it works > How OpenFiles detects agent edits, avoids false positives, and feeds diagnostics back to the agent. ## Why files need to be open [Section titled “Why files need to be open”](#why-files-need-to-be-open) VS Code’s language servers are fast because they mostly work on what you’re looking at. The defaults say so: | Language server | Setting | Default | | ----------------------- | ----------------------------------------------------------- | ------------------ | | TypeScript / JavaScript | `typescript.tsserver.experimental.enableProjectDiagnostics` | `false` | | ESLint | `eslint.run` / `eslint.lintTask.enable` | `onType` / `false` | | Pylance | `python.analysis.diagnosticMode` | `openFilesOnly` | | C# | `dotnet.backgroundAnalysis.analyzerDiagnosticsScope` | `openFiles` | | PHP Intelephense | `intelephense.diagnostics.run` | `onType` | | Ruby LSP | pull diagnostics per document | — | Some servers do analyze the whole workspace: gopls, the Dart analyzer, and Java (Red Hat). rust-analyzer runs `cargo check` only when you save inside the editor. For those languages OpenFiles still gives you the review list and puts the results where you and the agent can see them. See the [linter reference](../reference/linters/) for 50 languages. ## Detection [Section titled “Detection”](#detection) OpenFiles uses three sources: 1. **File watcher.** Picks up any file created or changed on disk inside the workspace. 2. **Agent hooks.** After an edit, the agent runs `node ~/.openfiles/hook.js --agent `. The script appends a line to `.openfiles/queue.jsonl` with the file paths, the agent and the tool name. 3. **Git.** Used to ignore branch switches, and on request (**Add Uncommitted Git Changes**) to pull in files changed before OpenFiles was running. ### What doesn’t count [Section titled “What doesn’t count”](#what-doesnt-count) * **Your own saves.** OpenFiles records saves and file operations done in the editor. A change within `openfiles.detection.editorSaveGraceMs` (1.5 s) of a save, where the disk still matches the buffer, is yours. Format-on-save is included. * **Git operations.** Changes around a HEAD move (checkout, pull, rebase), or while `.git/index.lock` exists, are ignored. * **Bursts.** More than `openfiles.detection.burstLimit` (200) files at once is probably an install or a build. OpenFiles asks before tracking them and never opens them. * **Ignored paths.** `openfiles.ignore`, `files.exclude`, `.git/` and `.openfiles/`. * **Sensitive files.** Anything matching `openfiles.sensitive` (`.env`, keys) is tracked but never opened automatically. A hook report and a watcher event for the same write within 2 seconds count as one change. The hook’s agent name wins. ## Opening [Section titled “Opening”](#opening) In `open` mode, files open with `preview: false` and without taking focus. OpenFiles waits while you’re typing (up to 15 s) and stops auto-opening after `openfiles.maxAutoOpen` files in a session. Files that are already open just reload from disk. ## Feedback to the agent [Section titled “Feedback to the agent”](#feedback-to-the-agent) ```text agent edits src/auth.ts └─ hook.js appends to .openfiles/queue.jsonl, notes the time T └─ extension opens src/auth.ts, language servers publish diagnostics └─ extension waits for diagnostics to go quiet (700 ms), sets checkedAt, writes .openfiles/diagnostics.json └─ hook.js sees checkedAt ≥ T (or times out after 4 s) └─ prints the errors in the agent's hook output format ``` The hook never blocks the agent: * If no VS Code window has this workspace open (no fresh `.openfiles/vscode/*.json`), it exits immediately. * On any error, it exits 0. * When time runs out, it returns whatever is known, or nothing. See [the diagnostics file](../reference/diagnostics-file/) for the formats. ## Files OpenFiles writes [Section titled “Files OpenFiles writes”](#files-openfiles-writes) | Path | What | When | | ----------------------------- | ------------------------------------------------ | --------------------------------------------- | | `.openfiles/.gitignore` | `*`, so the folder ignores itself | on activation | | `.openfiles/vscode/.json` | open tabs of each window, refreshed every 5 s | on activation | | `.openfiles/diagnostics.json` | problems in AI-edited files | when they change | | `.openfiles/queue.jsonl` | edits reported by hooks (truncated as it’s read) | by `hook.js` | | `~/.openfiles/hook.js` | the hook script | when you install hooks, and on update | | agent config files | the hook entry | only when you confirm **Install Agent Hooks** | Nothing is written in untrusted workspaces. There are no network calls and no telemetry. # Prompts for your agent > Copy-ready prompts that make agents read and fix the problems OpenFiles collects. Agents with feedback hooks get problems automatically. For everyone else, and for starting a task on the right foot, run **OpenFiles: Copy a Prompt for Your Agent…**. The prompts are below so you can copy them from here too. ## Instructions for AGENTS.md / CLAUDE.md [Section titled “Instructions for AGENTS.md / CLAUDE.md”](#instructions-for-agentsmd--claudemd) OpenFiles can insert this section for you. It goes between markers, so it can be updated or removed cleanly later. ```markdown ## Checking your edits This project uses OpenFiles in VS Code. Files you edit get opened in the editor, so the project's linters and type checkers run on them. - After editing files, read `.openfiles/diagnostics.json`. It lists errors and warnings for every file you touched, with line and column. - Each file has `checkedAt` (epoch ms). If it's older than your last edit, wait a moment and read it again. - Fix errors in files you changed before saying the task is done. Don't silence rules, add `any`, or add ignore comments to make them go away unless you're asked to. - If a hook already added an "OpenFiles opened the files you just edited" message after your edit, that's the same list. ``` ## Fix the problems in AI-edited files [Section titled “Fix the problems in AI-edited files”](#fix-the-problems-in-ai-edited-files) **Copy “Fix These Problems” Prompt** fills in the current problems: ```text OpenFiles opened the files you just edited in the editor. The language servers report 2 errors, 1 warning: - src/auth.ts:42:7 error 2322 (ts): Type 'string' is not assignable to type 'number'. - src/auth.ts:57:3 error 2554 (ts): Expected 2 arguments, but got 1. - src/api/user.ts:3:10 warning no-unused-vars (eslint): 'User' is defined but never used. Fix these before you report the task as done. Fix them one file at a time and keep each fix as small as the error allows. Don't change behavior the error doesn't require. When you're done, read `.openfiles/diagnostics.json` again and tell me what's left, if anything. ``` ## Work in small steps [Section titled “Work in small steps”](#work-in-small-steps) ```text Work in small steps. After each group of edits, read `.openfiles/diagnostics.json` and fix any errors in the files you touched before moving on. Don't change twenty files and hope the type checker agrees at the end. ``` ## Write a PR description [Section titled “Write a PR description”](#write-a-pr-description) ```text Write a pull request description for these changes: what changed, why, and what a reviewer should look at closely. Changed files: - src/auth.ts - src/api/user.ts The editor reports no problems in these files. ``` ## Ask your agent to set up OpenFiles [Section titled “Ask your agent to set up OpenFiles”](#ask-your-agent-to-set-up-openfiles) ```text Set up OpenFiles for this repository. The docs for agents are at https://devgiordane.github.io/openfiles/llms.txt. 1. Add the OpenFiles section to AGENTS.md (or CLAUDE.md / GEMINI.md, whichever this project uses). Keep it between the openfiles:start and openfiles:end markers. 2. Don't write hook configuration yourself; tell me to run "OpenFiles: Install Agent Hooks…" in VS Code, which shows a preview first. 3. Tell me what you changed. ``` # Diagnostics file and hook protocol > The formats of .openfiles/diagnostics.json, .openfiles/queue.jsonl and the hook script's arguments and output. These formats are how agents and scripts talk to OpenFiles. They are versioned; breaking changes bump `version`. ## `.openfiles/diagnostics.json` [Section titled “.openfiles/diagnostics.json”](#openfilesdiagnosticsjson) Written by the extension, in each workspace folder, whenever problems in AI-edited files change. ```jsonc { "version": 1, "updatedAt": 1789322228723, // epoch ms "hook": { "feedback": "errorsAndWarnings", // openfiles.hooks.feedback "timeoutMs": 4000 // openfiles.hooks.feedbackTimeoutMs }, "files": { "src/auth.ts": { // workspace-relative, forward slashes "path": "/home/me/app/src/auth.ts", "checkedAt": 1789322228700, // when diagnostics settled after the last edit; 0 = not yet "errors": 1, "warnings": 0, "items": [ { "line": 42, // 1-based "column": 7, // 1-based "severity": "error", // error | warning | info | hint "source": "ts", "code": "2322", "message": "Type 'string' is not assignable to type 'number'." } ] } } } ``` Reading it from an agent: * Only files changed in the current session are listed. * If `checkedAt` is older than your edit, the editor hasn’t finished checking yet. Wait and read again. * In `queue` mode files aren’t opened, so many language servers won’t have looked at them. An empty `items` there doesn’t mean clean. ## `.openfiles/queue.jsonl` [Section titled “.openfiles/queue.jsonl”](#openfilesqueuejsonl) Appended by `hook.js`, one JSON object per line. The extension reads new lines and truncates the file once it has read everything. ```json {"v":1,"ts":1789322228384,"agent":"claude","tool":"Edit","paths":["/home/me/app/src/auth.ts"]} ``` Anything can write here: a script, a Makefile, another tool. Use absolute paths. ## `hook.js` [Section titled “hook.js”](#hookjs) ```text node ~/.openfiles/hook.js --agent [--event ] [--no-feedback] ``` | Argument | | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | | `--agent` | `claude`, `codex`, `copilot`, `vscode`, `gemini`, `qwen`, `kimi`, `cursor`, `windsurf`, `kiro`, `cline`, `droid`, `goose`, `opencode`, `unknown` | | `--event` | the hook event, when an agent has several (`afterFileEdit`, `postToolUse`) | | `--no-feedback` | only report the edit; don’t wait for or print diagnostics | Behavior: 1. Reads the hook payload from stdin (3 s max). 2. Finds edited paths. Tools whose name doesn’t look like a write (`Read`, `Grep`, `Bash`) are ignored. 3. Walks up from the edited file to the nearest folder with a fresh `.openfiles/vscode/*.json` (less than 60 s old). If there isn’t one, it exits. 4. Appends to `queue.jsonl`. 5. Unless `--no-feedback` is set, it waits until every path has `checkedAt ≥` the time of step 4, or until `hook.timeoutMs` passes. 6. Prints feedback in the agent’s format, or nothing: | Agent | Output | | -------------------------------- | -------------------------------------------------------------------------------- | | claude, codex, qwen, kimi, droid | `{"hookSpecificOutput":{"hookEventName":"PostToolUse","additionalContext":"…"}}` | | gemini | `{"hookSpecificOutput":{"hookEventName":"AfterTool","additionalContext":"…"}}` | | copilot, vscode | `{"additionalContext":"…","hookSpecificOutput":{…}}` | | cursor (`postToolUse`) | `{"additional_context":"…"}` | | everyone else | nothing | It always exits `0`. ## `.openfiles/vscode/.json` [Section titled “.openfiles/vscode/\.json”](#openfilesvscodeidjson) One file per VS Code window, refreshed every `openfiles.heartbeatSeconds`. It’s useful if an agent wants to know what you’re looking at. ```json { "version": 1, "workspaceRoot": "/home/me/app", "sessionId": "…", "appName": "Visual Studio Code", "updatedAt": 1789322228.72, "files": ["/home/me/app/src/auth.ts"] } ``` `updatedAt` is in seconds, kept that way for compatibility with 0.1 clients. # Claude Code > Connect Claude Code to OpenFiles with a PostToolUse hook, so the problems in files it edits go straight back to Claude. **Support:** detection and feedback. Claude receives the errors in the same turn. ## Install [Section titled “Install”](#install) Run **OpenFiles: Install Agent Hooks…** and pick **Claude Code**. OpenFiles adds this to `.claude/settings.local.json`: ```json { "hooks": { "PostToolUse": [ { "matcher": "Edit|Write|MultiEdit|NotebookEdit", "hooks": [ { "type": "command", "command": "node \"/Users/you/.openfiles/hook.js\" --agent claude --tag openfiles-hook", "timeout": 15 } ] } ] } } ``` It uses the **local** settings file on purpose. The command points at your home directory, and Claude Code keeps `settings.local.json` out of Git. If you want the whole team on it, each person runs the install once. Restart any running `claude` session, then run `/hooks` to confirm it’s listed. ## What Claude sees [Section titled “What Claude sees”](#what-claude-sees) When the edited file has problems, the hook returns: ```json { "hookSpecificOutput": { "hookEventName": "PostToolUse", "additionalContext": "OpenFiles opened the files you just edited in the editor. The language servers report 1 error:\n- src/auth.ts:42:7 error 2322 (ts): Type 'string' is not assignable to type 'number'.\nFix these before you report the task as done." } } ``` ## Notes [Section titled “Notes”](#notes) * Claude Code’s own IDE integration (`/ide`) shows diffs and lets Claude ask for diagnostics. OpenFiles complements it: it works when Claude runs headless (`claude -p`), in another terminal or in a worktree, and it keeps a review list across sessions. * Settings reference: [Claude Code hooks](https://code.claude.com/docs/en/hooks). # Codex CLI > Connect OpenAI Codex CLI to OpenFiles with a PostToolUse hook on apply_patch. **Support:** detection and feedback. ## Install [Section titled “Install”](#install) Run **OpenFiles: Install Agent Hooks…** and pick **Codex CLI**. OpenFiles writes `.codex/hooks.json`: ```json { "hooks": { "PostToolUse": [ { "matcher": "apply_patch|Edit|Write", "hooks": [ { "type": "command", "command": "node \"/Users/you/.openfiles/hook.js\" --agent codex --tag openfiles-hook", "timeout": 15 } ] } ] } } ``` Codex edits files through `apply_patch`. The hook reads the patch in `tool_input.command` and takes every `*** Add File:`, `*** Update File:` and `*** Move to:` path. Deleted files are skipped. If the hook doesn’t fire, check that hooks are enabled in your Codex configuration: [Codex hooks documentation](https://learn.chatgpt.com/docs/hooks). ## What Codex sees [Section titled “What Codex sees”](#what-codex-sees) The problems come back as `hookSpecificOutput.additionalContext`, which Codex adds as developer context. # GitHub Copilot > Connect Copilot CLI and VS Code agent mode to OpenFiles with a postToolUse hook. **Support:** detection and feedback. ## Install [Section titled “Install”](#install) Run **OpenFiles: Install Agent Hooks…** and pick **GitHub Copilot**. OpenFiles creates its own file, `.github/hooks/openfiles.json`: ```json { "version": 1, "hooks": { "postToolUse": [ { "type": "command", "bash": "node \"/Users/you/.openfiles/hook.js\" --agent copilot --tag openfiles-hook", "powershell": "node \"/Users/you/.openfiles/hook.js\" --agent copilot --tag openfiles-hook", "timeoutSec": 15 } ] } } ``` There’s no matcher. The hook script checks the tool name itself and ignores tools that don’t write files. VS Code agent mode reads the same folder but doesn’t apply matchers, so doing the check in the script covers both. `.github/hooks/` is usually committed. Because the command points at your home directory, either keep this file out of Git or have each teammate run the install. ## What Copilot sees [Section titled “What Copilot sees”](#what-copilot-sees) Copilot CLI appends `additionalContext` to the tool result, so the model reads it in the same turn. Output is capped at 10 KB across hooks, and OpenFiles keeps its message under 9 KB. Reference: [Copilot hooks](https://docs.github.com/en/copilot/reference/hooks-reference). # Cursor > Connect Cursor's agent to OpenFiles with afterFileEdit and postToolUse hooks. **Support:** detection and feedback. Install OpenFiles in Cursor from [Open VSX](https://open-vsx.org/extension/devgiordane/openfiles). ## Install [Section titled “Install”](#install) Run **OpenFiles: Install Agent Hooks…** and pick **Cursor**. OpenFiles adds two entries to `.cursor/hooks.json`: ```json { "version": 1, "hooks": { "afterFileEdit": [ { "command": "node \"/Users/you/.openfiles/hook.js\" --agent cursor --event afterFileEdit --no-feedback --tag openfiles-hook" } ], "postToolUse": [ { "command": "node \"/Users/you/.openfiles/hook.js\" --agent cursor --event postToolUse --tag openfiles-hook" } ] } } ``` * `afterFileEdit` reports every file the agent edits. It can’t send anything back, so it runs with `--no-feedback`. * `postToolUse` can return `additional_context` to the conversation, so that’s where the problems go. The hook skips tools that don’t write files. Cursor also runs Claude Code hooks. If you installed both, the same edit gets reported twice; OpenFiles merges the two. ## A note on in-editor agents [Section titled “A note on in-editor agents”](#a-note-on-in-editor-agents) Cursor’s agent edits files through the editor, so many of those files are already open and checked. What OpenFiles adds here is the review list, the badges, and the problems handed back to the agent. Reference: [Cursor hooks](https://cursor.com/docs/hooks). # Gemini CLI > Connect Gemini CLI to OpenFiles with an AfterTool hook. **Support:** detection and feedback. ## Install [Section titled “Install”](#install) Run **OpenFiles: Install Agent Hooks…** and pick **Gemini CLI**. OpenFiles adds this to `.gemini/settings.json`: ```json { "hooks": { "AfterTool": [ { "matcher": "write_file|replace", "hooks": [ { "type": "command", "name": "OpenFiles", "command": "node \"/Users/you/.openfiles/hook.js\" --agent gemini --tag openfiles-hook", "timeout": 15000 } ] } ] } } ``` Gemini CLI timeouts are in milliseconds. Gemini expects a hook’s stdout to be pure JSON, and OpenFiles prints either one JSON object or nothing. ## What Gemini sees [Section titled “What Gemini sees”](#what-gemini-sees) `hookSpecificOutput.additionalContext` is appended to the tool result. Reference: [Gemini CLI hooks](https://geminicli.com/docs/hooks/reference/). # OpenCode > Connect OpenCode to OpenFiles with a small plugin (beta). **Support:** detection (beta). ## Install [Section titled “Install”](#install) Run **OpenFiles: Install Agent Hooks…** and pick **OpenCode**. OpenFiles creates `.opencode/plugins/openfiles.js`. The plugin listens for `file.edited` events and passes each path to the hook script: ```js // openfiles-hook: added by the OpenFiles VS Code extension. Delete this file to remove it. import { spawn } from "node:child_process"; export const OpenFiles = async ({ directory }) => ({ event: async ({ event }) => { if (event.type !== "file.edited") return; const file = event.properties?.file; if (!file) return; const child = spawn("node", ["/Users/you/.openfiles/hook.js", "--agent", "opencode", "--no-feedback"], { stdio: ["pipe", "ignore", "ignore"], }); child.on("error", () => {}); child.stdin.end(JSON.stringify({ tool_name: "edit", file_path: file, cwd: directory })); }, }); ``` OpenCode plugins can’t add text to the model’s context from this event, so add the [AGENTS.md section](../../guides/prompts/) to have OpenCode read `.openfiles/diagnostics.json`. Reference: [OpenCode plugins](https://opencode.ai/docs/plugins/). # Other agents > Aider, Goose, Amp, Crush, Qwen Code, Kiro, Cline, Warp and anything else that writes files. Any tool that writes to disk is detected by the file watcher. You lose attribution (“changed outside the editor” instead of the agent’s name) and automatic feedback, but you keep the auto-open, badges, review list and `.openfiles/diagnostics.json`. To have those agents read the problems, add the [AGENTS.md section](../../guides/prompts/). | Agent | Today | Possible hook | | ------------- | ------------------------------------------------------------ | ------------------------------------------------- | | Aider | watcher + auto-commits (use **Add Uncommitted Git Changes**) | none | | Goose | watcher | `PostToolUse` via Open Plugins | | Amp | watcher | `tool:post-execute` (actions limited) | | Crush | watcher (it has its own LSP client) | none | | Qwen Code | watcher | `PostToolUse` in `.qwen/settings.json` | | Kimi CLI | watcher | `PostToolUse` (beta) | | Kiro | watcher | Post Tool Use / File Save hooks in `.kiro/hooks/` | | Cline | watcher | `PostToolUse` in `.clinerules/hooks/` | | Factory Droid | watcher | `PostToolUse`, matcher `Create\|Edit\|ApplyPatch` | | Warp | watcher | none | ## Wiring one up by hand [Section titled “Wiring one up by hand”](#wiring-one-up-by-hand) The hook script reads JSON on stdin and looks for a file path in the usual places (`tool_input.file_path`, `file_path`, `path`, `tool_info.file_path`, Codex patches, Copilot `toolArgs`). For most agents with a Claude-style hook, this works: ```sh node ~/.openfiles/hook.js --agent unknown ``` Add `--agent claude` if the agent accepts Claude Code’s `hookSpecificOutput.additionalContext` output, so the problems go back to it. If you get an agent working, please open an [agent support issue](https://github.com/devgiordane/openfiles/issues/new?template=agent_support.yml) with a sample payload, so it can become a one-click install. # Windsurf / Devin Desktop > Connect Windsurf's Cascade to OpenFiles with a post_write_code hook (beta). **Support:** detection (beta). The `post_write_code` hook can’t send context back to Cascade, so problems reach it through `.openfiles/diagnostics.json` and the [AGENTS.md prompt](../../guides/prompts/). ## Install [Section titled “Install”](#install) Install OpenFiles from [Open VSX](https://open-vsx.org/extension/devgiordane/openfiles), then run **OpenFiles: Install Agent Hooks…** and pick **Windsurf / Devin Desktop**. It adds this to `.windsurf/hooks.json`: ```json { "version": 1, "hooks": { "post_write_code": [ { "command": "node \"/Users/you/.openfiles/hook.js\" --agent windsurf --event post_write_code --no-feedback --tag openfiles-hook" } ] } } ``` This integration is marked beta until someone confirms it end to end. If you use Windsurf, please report how it went in an [agent support issue](https://github.com/devgiordane/openfiles/issues/new?template=agent_support.yml). Reference: [Cascade hooks](https://docs.devin.ai/desktop/cascade/hooks). # Reviewing AI edits > The sidebar, badges, status bar and commands for going through what an agent changed. ## The sidebar [Section titled “The sidebar”](#the-sidebar) Click the OpenFiles icon in the Activity Bar. * **AI Edits.** Every file changed in this session, grouped by agent when more than one was involved. Each row shows the folder and a problem count (`2✕ 1⚠`) and has a checkbox. Checking it marks the file reviewed. Inline buttons open the diff against HEAD and toggle reviewed. * **Problems in AI Edits.** Errors and warnings, but only for those files, with errors first. Click one to jump to it. * **Agents & Hooks.** Agents detected in this workspace and whether their hook is installed. * **Profiles.** Named sets of files from `.openfiles.json`, opened with one click. A file that changes again after you reviewed it becomes unreviewed again. ## Badges [Section titled “Badges”](#badges) Unreviewed files get an **AI** badge in the Explorer and on editor tabs. The color is `openfiles.unreviewedForeground`, and you can override it in `workbench.colorCustomizations`. ## A typical pass [Section titled “A typical pass”](#a-typical-pass) 1. The agent finishes. The status bar shows `👁 6 ⊗ 2 ⚠ 1`. 2. Run **Review Next Changed File**. It opens the file with the most errors. 3. Read it, or use **Open Diff vs HEAD** to see only what changed. 4. Run **Review Next Changed File** again. The current file is marked reviewed and the next one opens. 5. If problems remain, run **Copy “Fix These Problems” Prompt** and paste it to the agent. 6. When you commit, **Clear AI Edits** starts fresh. Reviewed files older than a day are also dropped automatically. ## Context menus [Section titled “Context menus”](#context-menus) Right-click a file in the Explorer, an editor tab, or the editor itself for **Mark as Reviewed**, **Open Diff vs HEAD** and **Add to Profile…**. Multi-select works in the Explorer and the AI Edits view. ## Pausing [Section titled “Pausing”](#pausing) Doing a big refactor yourself, or running a codegen step? **Pause / Resume Watching** (also in the status bar menu) stops detection until you resume. # Status bar > Choose what the OpenFiles status bar item shows and what clicking it does. Run **OpenFiles: Configure Status Bar…**, or click the item and choose **Configure Status Bar…**. There are two quick steps. ## What it shows [Section titled “What it shows”](#what-it-shows) `openfiles.statusBar.items` is a list, shown in this order: | Item | Looks like | Meaning | | ------------ | ---------------------- | ------------------------------------ | | `edited` | `$(files) 6` | files changed by agents this session | | `unreviewed` | `$(eye) 4` | files you haven’t checked off | | `errors` | `$(error) 2` | errors in those files | | `warnings` | `$(warning) 1` | warnings in those files | | `agent` | `$(hubot) Claude Code` | the agent that edited most recently | | `paused` | `$(debug-pause)` | shown only while watching is paused | The default is `["unreviewed", "errors", "warnings"]`. With nothing to report, the item just reads **OpenFiles**. It turns yellow when unreviewed files have errors. ## What clicking does [Section titled “What clicking does”](#what-clicking-does) `openfiles.statusBar.clickAction`: | Value | Action | | ---------------- | ---------------------------------------- | | `menu` (default) | a quick menu with the most-used commands | | `reviewNext` | review the next changed file | | `openAiEdits` | open every unreviewed file | | `showProblems` | focus Problems in AI Edits | | `focusSidebar` | focus the AI Edits view | The tooltip also has links for review next, problems, pause and configure. ## Other settings [Section titled “Other settings”](#other-settings) ```jsonc { "openfiles.statusBar.enabled": true, "openfiles.statusBar.alignment": "left" // or "right" } ``` # Commands > Every OpenFiles command in the Command Palette. Open the Command Palette (`Ctrl+Shift+P` / `Cmd+Shift+P`) and type `OpenFiles`. | Command | ID | | -------------------------------------------------- | ------------------------------ | | OpenFiles: Open AI-Edited Files | `openfiles.openAiEdits` | | OpenFiles: Review Next Changed File | `openfiles.reviewNext` | | OpenFiles: Mark as Reviewed | `openfiles.markReviewed` | | OpenFiles: Mark as Not Reviewed | `openfiles.markUnreviewed` | | OpenFiles: Mark All as Reviewed | `openfiles.markAllReviewed` | | OpenFiles: Open Diff vs HEAD | `openfiles.openDiff` | | OpenFiles: Show Problems in AI-Edited Files | `openfiles.showProblems` | | OpenFiles: Copy “Fix These Problems” Prompt | `openfiles.copyFixPrompt` | | OpenFiles: Copy a Prompt for Your Agent… | `openfiles.copyAgentPrompt` | | OpenFiles: Install Agent Hooks… | `openfiles.installHooks` | | OpenFiles: Remove Agent Hooks… | `openfiles.removeHooks` | | OpenFiles: Clear AI Edits | `openfiles.clearSession` | | OpenFiles: Pause / Resume Watching | `openfiles.togglePause` | | OpenFiles: Add Uncommitted Git Changes | `openfiles.scanGitChanges` | | OpenFiles: Configure Status Bar… | `openfiles.configureStatusBar` | | OpenFiles: Run Doctor | `openfiles.doctor` | | OpenFiles: Get Started | `openfiles.getStarted` | | OpenFiles: Open Profile… | `openfiles.openProfile` | | OpenFiles: Open Missing Files from Default Profile | `openfiles.sync` | | OpenFiles: Add to Profile… | `openfiles.addToProfile` | | OpenFiles: Open .openfiles.json | `openfiles.openConfig` | | OpenFiles: List Open Tabs | `openfiles.showOpenFiles` | | OpenFiles: Refresh | `openfiles.refresh` | Any command can be bound to a key: open **Preferences: Open Keyboard Shortcuts**, search for the ID, and assign one. A popular choice is `openfiles.reviewNext`. # Settings > Every OpenFiles setting with its default. | Setting | Default | Description | | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | | `openfiles.mode` | `"open"` | What to do when an agent edits a file. (`open`, `queue`, `notify`) | | `openfiles.openInBackground` | `true` | Open changed files without stealing focus from the terminal or the file you’re in. | | `openfiles.maxAutoOpen` | `15` | Stop auto-opening after this many files in a session; the rest are listed in AI Edits. `0` never auto-opens. | | `openfiles.closeReviewedTabs` | `false` | Close a file’s tab when you mark it as reviewed. | | `openfiles.ignore` | `["**/.git/**","**/.openfiles/**","**/node_modules/**","**/dist/**","**/build/**","**/out/**","**/coverage/**","**/.next/**","**/.dart_tool/**","**/target/**","**/bin/**","**/obj/**","**/__pycache__/**","**/.venv/**","**/*.log","**/package-lock.json","**/pnpm-lock.yaml","**/yarn.lock","**/bun.lock","**/Cargo.lock","**/poetry.lock","**/.claude/**","**/.codex/**","**/.gemini/**","**/.cursor/**"]` | Glob patterns that are never tracked. `files.exclude` and `.gitignore` are respected too. | | `openfiles.sensitive` | `["**/.env","**/.env.*","**/*.pem","**/*.key","**/*.pfx","**/*.p12","**/credentials.*","**/secrets/**"]` | Glob patterns that are tracked but never opened automatically (secrets, keys). | | `openfiles.detection.watcher` | `true` | Detect files changed on disk by anything other than this editor. | | `openfiles.detection.git` | `true` | Use the Git extension to find uncommitted changes and to ignore branch switches. | | `openfiles.detection.hooks` | `true` | Read edits reported by agent hooks (`.openfiles/queue.jsonl`). | | `openfiles.detection.burstLimit` | `200` | If more files than this change within 2 seconds (installs, builds, checkouts), list them instead of opening them. | | `openfiles.detection.editorSaveGraceMs` | `1500` | Changes within this many milliseconds of a save in the editor are treated as yours, not the agent’s. | | `openfiles.diagnostics.export` | `true` | Write problems for AI-edited files to `.openfiles/diagnostics.json` so agents can read them. | | `openfiles.hooks.feedback` | `"errorsAndWarnings"` | What agent hooks send back to the agent after an edit. (`errors`, `errorsAndWarnings`, `off`) | | `openfiles.hooks.feedbackTimeoutMs` | `4000` | How long a hook waits for language servers before letting the agent continue. | | `openfiles.statusBar.enabled` | `true` | Show OpenFiles in the status bar. | | `openfiles.statusBar.items` | `["unreviewed","errors","warnings"]` | What the status bar item shows, in order. | | `openfiles.statusBar.clickAction` | `"menu"` | What clicking the status bar item does. (`menu`, `reviewNext`, `openAiEdits`, `showProblems`, `focusSidebar`) | | `openfiles.statusBar.alignment` | `"left"` | Which side of the status bar to use. (`left`, `right`) | | `openfiles.configFile` | `".openfiles.json"` | Workspace-relative path of the profiles file. | | `openfiles.heartbeatSeconds` | `5` | How often the list of open tabs is published to `.openfiles/vscode/` for agents and hooks. | # Linter reference (50 languages) > The best VS Code extension for diagnostics in 50 languages, whether it's on Open VSX, and whether it only checks open files. OpenFiles doesn’t lint anything itself. It opens files so the extensions below can do their job. **Run Doctor** checks which of these your workspace needs. **Scope column:** * **Open**: diagnostics only for open files by default. * **Workspace**: analyzes the whole project. * **Verified** means we found the default in the extension’s own settings or docs (see [Evidence](#evidence)). * The rest is what we expect from how the tool works. | # | Language | Extension | Open VSX | Scope | | -- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------- | | 1 | TypeScript | built-in + [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) | ✅ | Open (verified) | | 2 | JavaScript | built-in + [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint), [Biome](https://marketplace.visualstudio.com/items?itemName=biomejs.biome), [Oxc](https://marketplace.visualstudio.com/items?itemName=oxc.oxc-vscode) | ✅ | Open (verified) | | 3 | Python | [Pylance](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance), [Ruff](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff), [Mypy](https://marketplace.visualstudio.com/items?itemName=ms-python.mypy-type-checker) | Pylance ❌ → [basedpyright](https://open-vsx.org/extension/detachhead/basedpyright) | Open (verified) | | 4 | Java | [Language Support for Java](https://marketplace.visualstudio.com/items?itemName=redhat.java) | ✅ | Workspace | | 5 | C# | [C#](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp) / [C# Dev Kit](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit) | ❌ → [muhammad-sammy.csharp](https://open-vsx.org/extension/muhammad-sammy/csharp) | Open (verified) | | 6 | C / C++ | [C/C++](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools), [clangd](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd) | cpptools ❌, clangd ✅ | Open | | 7 | HTML | built-in + [HTMLHint](https://marketplace.visualstudio.com/items?itemName=HTMLHint.vscode-htmlhint) | ✅ | Open | | 8 | CSS / SCSS / Less | built-in + [Stylelint](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint) | ✅ | Open | | 9 | SQL | [SQLFluff](https://marketplace.visualstudio.com/items?itemName=sqlfluff.vscode-sqlfluff), [MSSQL](https://marketplace.visualstudio.com/items?itemName=ms-mssql.mssql) | ✅ | Open | | 10 | Bash / Shell | [ShellCheck](https://marketplace.visualstudio.com/items?itemName=timonwong.shellcheck), [Bash IDE](https://marketplace.visualstudio.com/items?itemName=mads-hartmann.bash-ide-vscode) | ✅ | Open | | 11 | PowerShell | [PowerShell](https://marketplace.visualstudio.com/items?itemName=ms-vscode.powershell) | ✅ | Open | | 12 | PHP | [Intelephense](https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client), [PHPStan](https://marketplace.visualstudio.com/items?itemName=SanderRonde.phpstan-vscode), [PHP Tools](https://marketplace.visualstudio.com/items?itemName=DEVSENSE.phptools-vscode) | ✅ | Open (verified, Intelephense) | | 13 | Go | [Go](https://marketplace.visualstudio.com/items?itemName=golang.Go) | ✅ | Workspace (verified) | | 14 | Rust | [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) | ✅ | Workspace, on save in the editor (verified) | | 15 | Kotlin | [Kotlin LSP](https://marketplace.visualstudio.com/items?itemName=JetBrains.kotlin-server), [fwcd.kotlin](https://marketplace.visualstudio.com/items?itemName=fwcd.kotlin) | ✅ | ? | | 16 | Lua | [Lua](https://marketplace.visualstudio.com/items?itemName=sumneko.lua) | ✅ | Workspace after a delay | | 17 | Ruby | [Ruby LSP](https://marketplace.visualstudio.com/items?itemName=Shopify.ruby-lsp) | ✅ | Open (verified) | | 18 | Dart / Flutter | [Dart](https://marketplace.visualstudio.com/items?itemName=Dart-Code.dart-code) | ✅ | Workspace (verified) | | 19 | Swift | [Swift](https://marketplace.visualstudio.com/items?itemName=swiftlang.swift-vscode) | ✅ | Open | | 20 | JSON / JSONC | built-in (schemas) | built-in | Open | | 21 | YAML | [YAML](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml) | ✅ | Open | | 22 | Markdown | [markdownlint](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint) | ✅ | Open | | 23 | Dockerfile | [Docker DX](https://marketplace.visualstudio.com/items?itemName=docker.docker), [hadolint](https://marketplace.visualstudio.com/items?itemName=exiasr.hadolint) | ✅ | Open | | 24 | Terraform / HCL | [HashiCorp Terraform](https://marketplace.visualstudio.com/items?itemName=hashicorp.terraform) | ✅ | Open / module | | 25 | R | [R](https://marketplace.visualstudio.com/items?itemName=REditorSupport.r) | ✅ | Open | | 26 | Julia | [Julia](https://marketplace.visualstudio.com/items?itemName=julialang.language-julia) | ✅ | ? | | 27 | Scala | [Metals](https://marketplace.visualstudio.com/items?itemName=scalameta.metals) | ✅ | Workspace (compile) | | 28 | Haskell | [Haskell](https://marketplace.visualstudio.com/items?itemName=haskell.haskell) | ✅ | Open | | 29 | Elixir | [ElixirLS](https://marketplace.visualstudio.com/items?itemName=JakeBecker.elixir-ls), [Lexical](https://marketplace.visualstudio.com/items?itemName=lexical-lsp.lexical) | [elixir-lsp.elixir-ls](https://open-vsx.org/extension/elixir-lsp/elixir-ls) | Workspace (mix compile) | | 30 | Erlang | [Erlang LS](https://marketplace.visualstudio.com/items?itemName=erlang-ls.erlang-ls) | ✅ | ? | | 31 | Clojure | [Calva](https://marketplace.visualstudio.com/items?itemName=betterthantomorrow.calva) | ✅ | Workspace on startup | | 32 | F# | [Ionide](https://marketplace.visualstudio.com/items?itemName=Ionide.Ionide-fsharp) | ✅ | Open | | 33 | OCaml | [OCaml Platform](https://marketplace.visualstudio.com/items?itemName=ocamllabs.ocaml-platform) | ✅ | Open | | 34 | Zig | [Zig](https://marketplace.visualstudio.com/items?itemName=ziglang.vscode-zig) | ✅ | Open | | 35 | Perl | [Perl Navigator](https://marketplace.visualstudio.com/items?itemName=bscan.perlnavigator) | ✅ | Open | | 36 | Fortran | [Modern Fortran](https://marketplace.visualstudio.com/items?itemName=fortran-lang.linter-gfortran) | ✅ | Open | | 37 | MATLAB | [MATLAB](https://marketplace.visualstudio.com/items?itemName=MathWorks.language-matlab) | ✅ | Open | | 38 | Objective-C | [clangd](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd) | ✅ | Open | | 39 | Delphi / Object Pascal | [DelphiLSP](https://marketplace.visualstudio.com/items?itemName=embarcaderotechnologies.delphilsp) | ❌ | ? | | 40 | Ada | [Ada & SPARK](https://marketplace.visualstudio.com/items?itemName=AdaCore.ada) | ✅ | ? | | 41 | COBOL | [COBOL Language Support](https://marketplace.visualstudio.com/items?itemName=broadcomMFD.cobol-language-support) | ✅ | Open | | 42 | Solidity | [Hardhat Solidity](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity), [Solidity](https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity) | ✅ | Open | | 43 | Vue | [Vue - Official](https://marketplace.visualstudio.com/items?itemName=Vue.volar) | ✅ | Open | | 44 | Svelte | [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) | ✅ | Open | | 45 | Astro | [Astro](https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode) | ✅ | Open | | 46 | GraphQL | [GraphQL](https://marketplace.visualstudio.com/items?itemName=GraphQL.vscode-graphql) | ✅ | Open | | 47 | TOML | [Even Better TOML](https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml) | ✅ | Open | | 48 | XML | [XML](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-xml) | ✅ | Open | | 49 | Prisma | [Prisma](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) | ✅ | Open | | 50 | Protobuf | [Buf](https://marketplace.visualstudio.com/items?itemName=bufbuild.vscode-buf) | ✅ | Open | More languages with good extensions: LaTeX ([LaTeX Workshop](https://marketplace.visualstudio.com/items?itemName=James-Yu.latex-workshop)), Gleam, Nim, Elm, Crystal, V, Mojo, Groovy, Nix, Ansible, CMake, GitHub Actions, Tailwind CSS. Languages were chosen from the [Stack Overflow 2025 survey](https://survey.stackoverflow.co/2025/technology), [GitHub Octoverse 2025](https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/) and the [TIOBE index](https://www.tiobe.com/tiobe-index/), plus common config formats. Extension IDs were checked against both registries in September 2026. ## Evidence [Section titled “Evidence”](#evidence) **Open files only by default:** * **TypeScript:** `typescript.tsserver.experimental.enableProjectDiagnostics` is `false`, described as “Enables project wide error reporting”. [package.json](https://github.com/microsoft/vscode/blob/main/extensions/typescript-language-features/package.json) * **ESLint:** `eslint.run` is `onType`, and `eslint.lintTask.enable` (“a task for linting the whole workspace”) is `false`. [package.json](https://github.com/microsoft/vscode-eslint/blob/main/package.json) * **Pylance / Pyright:** `python.analysis.diagnosticMode` is `openFilesOnly`. “If this option is set to ‘openFilesOnly’, pyright analyzes only open files.” [Pyright settings](https://github.com/microsoft/pyright/blob/main/docs/settings.md) * **C#:** `dotnet.backgroundAnalysis.analyzerDiagnosticsScope` and `compilerDiagnosticsScope` are `openFiles`. [package.json](https://github.com/dotnet/vscode-csharp/blob/main/package.json) * **PHP Intelephense:** `intelephense.diagnostics.run` is `onType`, with no workspace mode ([#1467](https://github.com/bmewburn/vscode-intelephense/issues/1467)). [package.json](https://github.com/bmewburn/vscode-intelephense/blob/master/package.json) * **Ruby LSP:** pull diagnostics per document; the server registers `workspace_diagnostics: false`. [server.rb](https://github.com/Shopify/ruby-lsp/blob/main/lib/ruby_lsp/server.rb) **Whole workspace by default:** * **Dart:** `onlyAnalyzeProjectsWithOpenFiles` defaults to `false`. [LSP spec](https://github.com/dart-lang/sdk/blob/main/pkg/analysis_server/tool/lsp_spec/README.md) * **gopls:** workspace diagnostics are recomputed after about 1 s idle. [diagnostics.md](https://github.com/golang/tools/blob/master/gopls/doc/features/diagnostics.md) * **rust-analyzer:** `checkOnSave` and `check.workspace` are `true`, but the check only runs on save in the editor. [package.json](https://github.com/rust-lang/rust-analyzer/blob/master/editors/code/package.json) * **Java:** `java.autobuild.enabled` is `true`. [package.json](https://github.com/redhat-developer/vscode-java/blob/master/package.json) Found something out of date? [Open an issue](https://github.com/devgiordane/openfiles/issues/new?template=feature_request.yml), since defaults change. # FAQ > Common questions about OpenFiles, privacy, tabs, hooks and editors. ## Does OpenFiles send my code anywhere? [Section titled “Does OpenFiles send my code anywhere?”](#does-openfiles-send-my-code-anywhere) No. It makes no network requests and has no telemetry. It writes under `.openfiles/` in your workspace, and to `~/.openfiles/hook.js` once you install hooks. ## Will it flood me with tabs? [Section titled “Will it flood me with tabs?”](#will-it-flood-me-with-tabs) It tries hard not to: * files open in the background; * it waits while you’re typing; * it stops after 15 files per session; * bulk changes (installs, builds, checkouts) are listed, not opened. If you still prefer no tabs at all, set `openfiles.mode` to `queue`. ## My agent says it’s done, but the problems list is empty. Is the code clean? [Section titled “My agent says it’s done, but the problems list is empty. Is the code clean?”](#my-agent-says-its-done-but-the-problems-list-is-empty-is-the-code-clean) Maybe. Check three things: * Is there a linter for that language? **Run Doctor** tells you. * Are you in `queue` mode? Files that aren’t open usually aren’t checked. * Some language servers need a few seconds on first start. `checkedAt` in `diagnostics.json` tells you whether the editor has looked yet. ## Why Node.js for the hook? [Section titled “Why Node.js for the hook?”](#why-nodejs-for-the-hook) The hook has to parse each agent’s JSON, wait for diagnostics, and reply in that agent’s format. Doing that in both `sh` and PowerShell without extra tools was fragile. Most people running coding agents already have Node. **Run Doctor** checks it. ## Should I commit the hook config? [Section titled “Should I commit the hook config?”](#should-i-commit-the-hook-config) Usually not. The command contains your home directory path. For Claude Code, OpenFiles uses `.claude/settings.local.json`, which is already local. For other agents, either keep the file local or have each teammate run **Install Agent Hooks** (it’s idempotent). When VS Code isn’t running, a teammate’s hook simply does nothing. ## Does it work over Remote SSH, WSL or in Dev Containers? [Section titled “Does it work over Remote SSH, WSL or in Dev Containers?”](#does-it-work-over-remote-ssh-wsl-or-in-dev-containers) The extension runs on the remote side (`extensionKind: workspace`), next to the files and the agents, so it should. File watchers can be unreliable on some network drives; the hook queue is polled as a fallback. Please report issues with the Doctor output. ## Does it replace lint in CI? [Section titled “Does it replace lint in CI?”](#does-it-replace-lint-in-ci) No. Keep CI. OpenFiles moves the feedback earlier, to the moment the agent writes the file. ## What happened to profiles? [Section titled “What happened to profiles?”](#what-happened-to-profiles) They still work. `.openfiles.json` profiles open a named set of files. See **OpenFiles: Open Profile…** and the Profiles view. ## Can I use it without an AI agent? [Section titled “Can I use it without an AI agent?”](#can-i-use-it-without-an-ai-agent) Yes. It flags any file changed outside the editor: a code generator, a script, a teammate’s `git stash pop`. It’s just most useful with agents.