pilotignore 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,79 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project follows [Semantic Versioning](https://semver.org/).
4
+
5
+ ## [0.2.0] - 2026-10-10
6
+
7
+ A rewrite of the rule engine and hook, plus a `verify` command and a test setup for trying pilotignore with a real Copilot agent.
8
+
9
+ ### Upgrading from 0.1.x
10
+
11
+ 1. Update the package and **re-run `npx pilotignore init`**. The hook script in `.github/hooks/` is a copy and won't update otherwise. Your `.pilotignore` is left untouched.
12
+ 2. **Check rules that contain a `/`.** These are now anchored to the project root, as in `.gitignore` (see *Changed*). To keep matching at any depth, prefix them with `**/`, e.g. `config/secrets.json` → `**/config/secrets.json`.
13
+ 3. **Add the new self-protection rules** to your existing `.pilotignore`. New installs get them by default, but `init` never edits an existing file:
14
+ ```text
15
+ .pilotignore
16
+ .github/hooks/pilotignore.cjs
17
+ .github/hooks/pilotignore.json
18
+ ```
19
+ 4. Run `npx pilotignore verify` to confirm everything works.
20
+
21
+ ### Changed
22
+
23
+ - **Rules follow `.gitignore` semantics.** Previously a rule matched by plain path comparison (exact path, path prefix, or path suffix). Now:
24
+ - A rule with a `/` anywhere in it is **anchored to the project root**. `config/secrets.json` no longer matches `nested/config/secrets.json`; use `**/config/secrets.json` for that. **This can change what an existing rule blocks.**
25
+ - A rule without a `/` matches that name at any depth, as before.
26
+ - The last matching rule wins, so `!` negations can re-allow paths.
27
+ - **Allowed tool calls produce no output.** 0.1.x printed an explicit `allow` decision, which could auto-approve tool calls and skip Copilot's own approval prompts. The hook now stays silent unless it denies, so Copilot's normal permission flow applies. pilotignore only ever takes permissions away.
28
+ - **Errors fail closed.** If the hook can't evaluate a call (malformed or empty payload, unreadable `.pilotignore`, unexpected error), the call is now denied instead of allowed. This matches how Copilot treats a failing `preToolUse` hook.
29
+ - **Shell commands are scanned.** Paths inside shell commands are now checked as well, so `cat .env` is denied like a file read. A command that only *mentions* a blocked name (e.g. `git commit -m "fix .env"`) is denied too.
30
+ - **Deny reasons name the path and rule**, e.g. `Access to '.env' is blocked by .pilotignore rule '.env'.` Previously the reason was a generic message.
31
+ - **The default `.pilotignore` protects pilotignore itself.** New installs block reading or changing `.pilotignore` and the two hook files, and include a commented pattern-syntax reference.
32
+ - **Package layout:** the hook moved from `templates/pilotignore.cjs` to `src/pilotignore.cjs`, and the templates to `src/templates/`. Installed files in your project keep their names and locations.
33
+ - **Node.js >= 20** is now declared in `engines`. CI tests Node 20, 22 and 24 on Linux, macOS and Windows.
34
+ - The `main` field was removed from `package.json`. pilotignore is a CLI, not a library, and importing it used to run the CLI. The `pilotignore` command is unaffected.
35
+ - The package description and README now describe pilotignore as a tool-call filter rather than a complete secrets boundary.
36
+
37
+ ### Added
38
+
39
+ - **`.gitignore`-style patterns:** `*`, `**`, `?`, `[abc]` / `[!abc]` character classes, `!` negation, leading `/` anchoring, trailing `/` directory-only rules, `\` escapes. Matching stays case-insensitive.
40
+ - **Shell glob expansion:** a token like `shop*`, `*.tx?` or `[s]ecret.json` is expanded against the filesystem, so `cat shop*` is denied when it would match a blocked file.
41
+ - **Directory protection:** commands on a directory that contains a blocked path are denied, e.g. `rm -rf .github` or `ls private`. Anchored rules protect their parent directories even before the file exists. The project root is exempt so ordinary commands keep working. Scans stop after 5,000 entries to stay well within the hook timeout.
42
+ - **More path sources:** `~/` home paths, Windows-style `\` separators, paths outside the project (`../…`), `tool_input_as_string` payloads, and command-style fields (`command`, `args`, `script`, …) in any payload shape.
43
+ - **Both hook output formats:** deny decisions are emitted as flat fields for Copilot CLI and inside `hookSpecificOutput` for VS Code. Copilot CLI now shows the deny reason; in 0.1.x it reported that no reason was given.
44
+ - **Cloud-agent-ready hook config:** the cross-platform `command` field was added next to `bash` / `powershell` in `.github/hooks/pilotignore.json`. Cloud agent support is untested.
45
+ - **`pilotignore verify`:** checks the hook config, hook script and rules, then fires real hook calls using your own rules. A read and a `cat` of a blocked path must be denied, and an unrelated path must be allowed.
46
+ - **`pilotignore help`** and usage output for unknown commands.
47
+ - **Clearer logs:** the log records each matched path and rule, and silent allows.
48
+ - **Docs:** pattern-syntax reference, per-surface support table, *Good to know* section on what tool-call filtering can't cover (content search, workspace index, open files, indirect reads) and how to cover it, design decisions, troubleshooting, uninstall, and a [testing guide](tests/README.md).
49
+ - **Development tooling:**
50
+ - `npm run smoke` packs the package, installs the tarball into a scratch project and exercises `init`, the hook and `verify`.
51
+ - `npm run sandbox` creates *recipe-box*, a realistic demo project for hands-on testing with Copilot Chat and Copilot CLI.
52
+ - The automated test suite grew from 10 to 28 tests.
53
+
54
+ ### Fixed
55
+
56
+ - Rules with a leading `/` (e.g. `/config.json`) never matched in 0.1.x. They now match at the project root.
57
+ - `npm test` failed on Node.js 22 because `tests/` was passed as a module path.
58
+ - The repository's `.gitignore` referenced a non-existent `pilotignore.js` instead of `pilotignore.cjs`.
59
+ - `package-lock.json` still listed version 0.1.0.
60
+
61
+ ### Removed
62
+
63
+ - Screenshots in the README, replaced with text examples.
64
+
65
+ ### Known limitations
66
+
67
+ These are documented in the README under *Good to know*:
68
+
69
+ - Content searches such as `grep -r term .` can return lines from blocked files.
70
+ - The VS Code workspace index, open editor files and inline suggestions don't go through tool calls.
71
+ - Paths built at runtime by scripts or interpreters aren't recognized.
72
+ - Copilot skips hooks that time out (fail-open). This is Copilot's behavior.
73
+
74
+ ## [0.1.2] and earlier
75
+
76
+ Initial releases: `pilotignore init`, a `preToolUse` hook with exact-path and folder matching, logging to `.copilot/logs/`, and `.gitignore` setup.
77
+
78
+ [0.2.0]: https://github.com/vkerttula/pilotignore/compare/9c335f9...v0.2.0
79
+ [0.1.2]: https://github.com/vkerttula/pilotignore/commit/9c335f9
package/LICENSE CHANGED
@@ -1,7 +1,7 @@
1
- Copyright (c) 2026 Valtteri Kerttula
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
-
5
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
-
7
- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright (c) 2026 Valtteri Kerttula
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,152 +1,155 @@
1
- <p align="center">
2
- <img src="https://raw.githubusercontent.com/vkerttula/pilotignore/main/assets/logo.svg" alt="pilotignore logo" width="120" height="156">
3
- </p>
4
-
5
- </p>
6
-
7
- <h1 align="center">
8
-
9
- `.pilotignore` — keep your secrets secret
10
-
11
- </h1>
12
-
13
- <p align="center">
14
- <strong>like <code>.gitignore</code>, but for github copilot agents</strong>
15
- </p>
16
-
17
- > [!WARNING]
18
- >
19
- > **EARLY DEVELOPMENT/EXPERIMENTAL PHASE. USE AT YOUR OWN RISK.**
20
- >
21
- > This project is currently in active development and still contain bugs or unhandled edge cases.
22
- >
23
- > AI technologies and their capabilities are evolving rapidly and continuously, meaning new bypass methods could emerge. Use this tool strictly at your own risk. It is a supplementary security layer, not a silver bullet. Always follow best practices for secret management: use secure environment vaults, never commit hardcoded secrets to your repository, and **never expose data to an AI agent that you absolutely cannot afford to leak.** Be the boss of your agent, not the other way around.
24
-
25
- > [!TIP]
26
- > **Fun fact:** Some other AI coding assistants already have native, built-in features to prevent the AI from reading specific files. Until GitHub Copilot introduces an official, first-class `.copilotignore` feature, `pilotignore` is here to bridge the gap!
27
-
28
- GitHub Copilot Cloud Agent and CLI are powerful tools that can navigate your codebase, read files, and execute commands. But sometimes, they shouldn't see everything. `pilotignore` is a lightweight CLI that sets up a programmatic firewall — actively blocking AI agents from reading `.env` files, API keys, or private configs.
29
-
30
- One tool. One philosophy: **Agent boundaries should be simple.**
31
-
32
- <p align="center">
33
- <a href="https://www.npmjs.com/package/pilotignore"><img src="https://img.shields.io/npm/v/pilotignore?style=flat&color=000000" alt="NPM Version"></a>
34
- <a href="https://www.npmjs.com/package/pilotignore"><img src="https://img.shields.io/npm/dt/pilotignore?style=flat&color=000000" alt="Downloads"></a>
35
- <a href="LICENSE"><img src="https://img.shields.io/github/license/vkerttula/pilotignore?style=flat&color=000000" alt="License"></a>
36
- </p>
37
-
38
- ## Table of Contents
39
-
40
- <p align="center">
41
- <a href="#before--after">Before/After</a> •
42
- <a href="#install">Install</a> •
43
- <a href="#what-you-get">What You Get</a> •
44
- <a href="#how-it-works">How It Works</a> •
45
- <a href="#roadmap">Roadmap</a>
46
- </p>
47
-
48
- ---
49
-
50
- ## Before / After
51
-
52
- ### 🔓 Normal Copilot Agent
53
-
54
- > **You:** "What is the database password inside config/secrets.json?"
55
- > **Copilot:** "Looking at your `config/secrets.json` file, the database password is `super_secret_p4ssw0rd`. I can help you rotate this if you need!"
56
-
57
- ### 🛡️ Copilot + pilotignore
58
-
59
- > **You:** "What is the database password inside config/secrets.json?"
60
- > **Copilot:** "I'm sorry, I cannot access `config/secrets.json` because my file-reading tool was denied by your `.pilotignore` rules."
61
-
62
- <p align="center">
63
- <img src="https://raw.githubusercontent.com/vkerttula/pilotignore/main/assets/copilot-vscode.png" alt="Copilot VS Code Chat blocked" width="49%">
64
- &nbsp;
65
- <img src="https://raw.githubusercontent.com/vkerttula/pilotignore/main/assets/copilot-cli.png" alt="Copilot CLI blocked" width="49%">
66
- </p>
67
-
68
- **Same agent. 0% leaked secrets. Peace of mind.**
69
-
70
- ## Install
71
-
72
- Install `pilotignore` as a development dependency. This ensures your project is locked to a specific version and makes updates seamless.
73
-
74
- ```bash
75
- # 1. Install the package
76
- npm install -D pilotignore
77
-
78
- # 2. Initialize the hooks and .pilotignore file
79
- npx pilotignore init
80
-
81
- ```
82
-
83
- ## What You Get
84
-
85
- After initialization, your project will have the following structure:
86
-
87
- ```text
88
- project-root/
89
- ├── .github/
90
- │ └── hooks/
91
- │ └── pilotignore.json <-- Tells Copilot to run the firewall from node_modules
92
- ├── .copilot/
93
- │ └── logs/
94
- │ └── pilotignore.log <-- Action logs accumulate here (add this to your .gitignore!)
95
- ├── .pilotignore <-- Add your sensitive files/folders to this blocklist
96
- └── package.json <-- pilotignore is installed as a devDependency
97
-
98
- ```
99
-
100
- Simply add your sensitive files to the generated `.pilotignore` file at the root of your project:
101
-
102
- ```text
103
- # Add files here to hide them from GitHub Copilot
104
- # Examples:
105
- # secrets.json
106
- # .env
107
- # Block from reading this file
108
- .pilotignore
109
-
110
- ```
111
-
112
- Commit the `.pilotignore` file and the generated `.github/hooks/` directory configuration to Git. That's it.
113
-
114
- | Target | Status | Note |
115
- | -------------------- | -------------- | --------------------------------------------------------------------------------------------------- |
116
- | **Copilot CLI** | 🛡️ Blocked | Local commands (`view`, `read_file`) are intercepted. |
117
- | **IDE Chat** | 🛡️ Blocked | Agentic workspace reads are stopped at the tool level. |
118
- | **Cloud Agent** | ⏳ Coming soon | Support for GitHub's secure cloud sandbox (see V2 roadmap). |
119
- | **IDE Autocomplete** | ⏳ Coming soon | Ghost-text autocomplete does not use tools (see V3 roadmap). Already possible with vscode settings. |
120
-
121
- ## How It Works
122
-
123
- 1. You install the package and run `npx pilotignore init`.
124
- 2. The tool drops an official Copilot Hooks API configuration script into `.github/hooks/pilotignore.json` that points to the local `node_modules` package.
125
- 3. When a Copilot Agent tries to run a tool (like `view` to read a file), the `preToolUse` hook fires.
126
- 4. If the target file matches an entry in your `.pilotignore`, the hook forcefully returns a `{"permissionDecision": "deny"}` JSON payload and a non-zero exit code.
127
- 5. The Agent gracefully backs off. No files read.
128
-
129
- > [!IMPORTANT]
130
- > While `pilotignore` blocks native file-reading tools, an extremely determined AI could theoretically write a custom script to read a file and execute it via `bash`. **We block the front door, but complex workarounds are always a possibility with AI.** Use at your own risk, and ensure you understand the limitations of agentic boundaries. This is the closest to native, code-level blocking we've achieved so far — be the boss of your agent, not the other way around.
131
-
132
- ## Roadmap
133
-
134
- - [x] Block Copilot Cloud Agent & CLI tools via `preToolUse` hooks.
135
- - [x] Basic exact-path and glob matching.
136
- - [ ] **V1.1:** Add global installation support (`pilotignore init --global`) for user-level protection across all local repositories.
137
- - [ ] **V2:** Cloud Agent support (syncing hooks to GitHub's secure cloud sandbox).
138
- - [ ] **V2:** Inject `.pilotignore` rules into Copilot Chat's `custom instructions` for double redundancy.
139
- - [ ] **V3:** Sync `.pilotignore` rules to `.vscode/settings.json` to automatically disable IDE ghost-text autocomplete for sensitive files.
140
-
141
- ## Links
142
-
143
- - [GitHub Copilot Hooks Reference](https://docs.github.com/en/copilot/reference/hooks-reference) — the underlying API
144
- - [Issues](https://github.com/vkerttula/pilotignore/issues) — bug, feature, weird behavior
145
-
146
- ## Star This Repo
147
-
148
- `.pilotignore` keeps your secrets secret. Star cost zero. Fair trade. ⭐
149
-
150
- ## License
151
-
152
- MIT
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/vkerttula/pilotignore/main/assets/logo.svg" alt="pilotignore logo" width="120" height="156">
3
+ </p>
4
+
5
+ <h1 align="center">
6
+
7
+ `.pilotignore`
8
+
9
+ </h1>
10
+
11
+ <p align="center">
12
+ <strong>like <code>.gitignore</code>, but for GitHub Copilot agents</strong>
13
+ </p>
14
+
15
+ <p align="center">
16
+ <a href="https://www.npmjs.com/package/pilotignore"><img src="https://img.shields.io/npm/v/pilotignore?style=flat&color=000000" alt="NPM Version"></a>
17
+ <a href="https://www.npmjs.com/package/pilotignore"><img src="https://img.shields.io/npm/dt/pilotignore?style=flat&color=000000" alt="Downloads"></a>
18
+ <a href="LICENSE"><img src="https://img.shields.io/github/license/vkerttula/pilotignore?style=flat&color=000000" alt="License"></a>
19
+ </p>
20
+
21
+ Copilot agents read files and run commands in your project. `pilotignore` lets you list the files they should leave alone. It installs a Copilot `preToolUse` hook that checks every tool call before it runs and denies the ones that touch a path in your `.pilotignore`. Everything else works exactly as before.
22
+
23
+ It's a small, zero-dependency tool for keeping an agent out of files it has no business opening: personal notes, local configs, drafts, generated data. It filters tool calls; it doesn't control everything Copilot can see (see [Good to know](#good-to-know)).
24
+
25
+ ## Quick start
26
+
27
+ ```bash
28
+ npm install -D pilotignore
29
+ npx pilotignore init # adds the hook and a .pilotignore file
30
+ npx pilotignore verify # checks that blocking actually works
31
+ ```
32
+
33
+ Add paths to `.pilotignore`, then commit it together with `.github/hooks/`.
34
+
35
+ ## Try it first
36
+
37
+ Want to see it block a real agent before adding it to your project?
38
+
39
+ ```bash
40
+ git clone https://github.com/vkerttula/pilotignore && cd pilotignore
41
+ npm run sandbox
42
+ ```
43
+
44
+ This creates a small demo project with pilotignore installed. Open it in VS Code or Copilot CLI and follow the test prompts in [`tests/README.md`](tests/README.md#test-prompts).
45
+
46
+ ## Writing rules
47
+
48
+ `.pilotignore` uses `.gitignore` syntax:
49
+
50
+ ```text
51
+ .env # this name, at any depth
52
+ *.pem # any file ending in .pem
53
+ .env* # .env, .env.local, .env.production, ...
54
+ /config.json # only at the project root
55
+ private/ # everything under any private/ directory
56
+ notes/** # everything under the root notes/
57
+ !notes/public.md # ...except this file
58
+ ```
59
+
60
+ Matching is case-insensitive. The default `.pilotignore` also lists itself and the hook files, so the agent can't read the rules, change them, or remove the hook.
61
+
62
+ ## What it looks like
63
+
64
+ When the agent tries to open a blocked file, the hook denies the tool call and tells the agent why. In Copilot CLI (abbreviated):
65
+
66
+ ```text
67
+ ● Read shopping-list.txt
68
+ Denied by preToolUse hook: Access to 'shopping-list.txt' is blocked by
69
+ .pilotignore rule 'shopping-list.txt'.
70
+ ```
71
+
72
+ Shell commands are checked too, including globs and directories:
73
+
74
+ ```text
75
+ $ cat shop* → denied (shopping-list.txt)
76
+ $ rm -rf .github → denied (contains .github/hooks/pilotignore.cjs)
77
+ $ npm start → allowed, Copilot asks for approval as usual
78
+ ```
79
+
80
+ Every decision is logged to `.copilot/logs/pilotignore.log`, which `init` adds to your `.gitignore`:
81
+
82
+ ```text
83
+ [2026-10-10T14:02:11.482Z] Candidate paths: ["shopping-list.txt"]
84
+ [2026-10-10T14:02:11.483Z] DECISION: DENY (Blocked) - shopping-list.txt matched rule 'shopping-list.txt'.
85
+ ```
86
+
87
+ ## Where it works
88
+
89
+ | Copilot surface | Status |
90
+ | --- | --- |
91
+ | **Copilot CLI** | ✅ Supported and tested |
92
+ | **VS Code Copilot Chat, agent mode** | ✅ Tested. VS Code agent hooks are in Preview. |
93
+ | **Copilot cloud agent** | Should work (it runs `.github/hooks`), not yet tested |
94
+ | **Inline suggestions, workspace index, open editor files** | ❌ Not covered. These don't go through tool calls. |
95
+
96
+ ## Good to know
97
+
98
+ pilotignore only sees **tool calls**. Some ways content reaches Copilot don't involve a tool call it can filter:
99
+
100
+ - **Content searches.** `grep -r milk .` or the agent's search tool can return matching lines from blocked files without opening them, because the search command itself names no blocked path.
101
+ - **Workspace index and open files.** VS Code indexes your workspace for semantic search, and the file open in your editor is sent as context. Neither goes through a hook.
102
+ - **Indirect reads.** A script or interpreter that builds the path at runtime, for example `python3 -c "open('se'+'crets.json').read()"`, isn't recognized.
103
+
104
+ To cover these as well, also add sensitive paths to `.gitignore` or VS Code's `files.exclude` / `search.exclude` settings. Those keep them out of the index and search results. Organizations on Copilot Business or Enterprise can additionally use GitHub's [content exclusion](https://docs.github.com/en/copilot/concepts/context/content-exclusion). And as always, real credentials belong in a secret manager, not in a workspace an agent works in.
105
+
106
+ ## How it works
107
+
108
+ `init` writes two files: `.github/hooks/pilotignore.json` registers the hook with Copilot, and `.github/hooks/pilotignore.cjs` is the hook itself. Before each tool call, Copilot passes the call's arguments to the hook. The hook collects every path in them, including paths inside shell commands, and checks them against `.pilotignore`.
109
+
110
+ A few deliberate design choices:
111
+
112
+ - **Silent allow.** If nothing matches, the hook prints nothing. Copilot's normal approval prompts and tool rules apply as if pilotignore weren't there. It only ever takes permissions away.
113
+ - **Fail-closed.** If the hook can't evaluate a call (malformed input, unreadable rules), the call is denied. This matches how Copilot treats a failing `preToolUse` hook. One exception comes from Copilot itself: a hook that times out is skipped, so the hook is built to finish well within its 5-second limit.
114
+ - **Shell-aware.** Commands are split into tokens. Globs like `cat shop*` are expanded against the filesystem, and operations on a directory that contains blocked paths (`rm -rf .github`) are denied. The project root is exempt, so `ls .` keeps working.
115
+ - **Explains itself.** A deny always names the rule that matched, so you can tell exactly why a call was blocked.
116
+ - **Errs on the side of blocking.** A command that only *mentions* a blocked name, like `git add .pilotignore`, is denied too. Commit changes to your ruleset yourself.
117
+
118
+ ## Troubleshooting
119
+
120
+ - **Run `npx pilotignore verify`.** It checks the setup and fires test calls at the installed hook using your own rules.
121
+ - **Nothing in the log** means Copilot didn't run the hook. Check that `.github/hooks/pilotignore.json` exists and that hooks aren't disabled in your Copilot settings.
122
+ - **A blocked file shows `ALLOW` in the log** means the path wasn't found in the tool call. Please [open an issue](https://github.com/vkerttula/pilotignore/issues) with the log lines.
123
+ - **After upgrading pilotignore**, run `npx pilotignore init` again to update the hook script. Your `.pilotignore` is never overwritten. Check the [changelog](CHANGELOG.md) for rule changes.
124
+
125
+ ## Uninstall
126
+
127
+ ```bash
128
+ npm uninstall pilotignore
129
+ rm .pilotignore .github/hooks/pilotignore.json .github/hooks/pilotignore.cjs
130
+ ```
131
+
132
+ Optionally remove `.copilot/logs/pilotignore.log` and the `# pilotignore logs` entry from your `.gitignore`.
133
+
134
+ ## Roadmap
135
+
136
+ - [x] Block Copilot CLI and VS Code agent tool calls via `preToolUse` hooks
137
+ - [x] `.gitignore`-style rules, shell scanning, directory protection, `verify` (v0.2.0)
138
+ - [ ] Test and document Copilot cloud agent
139
+ - [ ] Optionally sync rules to VS Code `search.exclude` / `files.exclude` to cover search and indexing
140
+ - [ ] Explore filtering blocked files out of search results with a `postToolUse` hook
141
+
142
+ ## Development
143
+
144
+ ```text
145
+ bin/cli.js CLI: init and verify
146
+ src/pilotignore.cjs the hook (copied into projects by init)
147
+ src/templates/ hook config and default .pilotignore
148
+ tests/ automated tests, smoke test and a sandbox demo project
149
+ ```
150
+
151
+ `npm test` runs the test suite. [`tests/README.md`](tests/README.md) covers the smoke test and hands-on testing with Copilot in a ready-made demo project.
152
+
153
+ ## License
154
+
155
+ [MIT](LICENSE). The software is provided "as is", without warranty of any kind, and the authors aren't liable for any damages arising from its use. See the license for the full terms.