> ## Documentation Index
> Fetch the complete documentation index at: https://docs.embedder.com/llms.txt
> Use this file to discover all available pages before exploring further.

# .embedderignore

> Mark files and directories that Embedder can read but must not edit.

Use `.embedderignore` to mark files and directories that Embedder is allowed to read but not allowed to edit. The agent can still inspect matched files for context (for example, vendored SDKs, generated headers, or upstream HALs), but any tool call that tries to write to a matched path is blocked, and the agent is told to ask for your permission before continuing.

<Note>
  `.embedderignore` is an edit-restriction file, not a read- or visibility-restriction file. To hide a path from the agent entirely, keep it outside the project root.
</Note>

## Configuring `.embedderignore`

Create a `.embedderignore` file at the root of your project and list the paths and patterns you want to protect.

```text .embedderignore theme={"system"}
# Vendor SDKs and HALs (read-only)
vendor/
hal/

# Generated headers and build output
generated/
build/
*.bin

# Files we never want auto-edited
.platformio/
config/secrets.*
```

You can also drop `.embedderignore` files into subdirectories. Embedder loads every `.embedderignore` from the project root down to the target file's parent directory, with closer files overriding rules from shallower ones (the same precedence as `.gitignore`). This is useful for monorepos where each package declares its own protected paths.

## Pattern syntax

`.embedderignore` follows the same rules as `.gitignore`:

| Pattern       | Matches                                                       |
| ------------- | ------------------------------------------------------------- |
| `file.c`      | A file with that name at any depth                            |
| `dist/`       | A directory and everything inside it                          |
| `*.bin`       | Files matching the glob in any directory                      |
| `**/build`    | A directory named `build` at any depth                        |
| `src/**/*.h`  | All `.h` files anywhere under `src/`                          |
| `!app/main.c` | Re-includes a path that an earlier pattern would have matched |
| `# comment`   | A comment line, ignored                                       |

* `*` matches any sequence of characters except `/`.
* `**` matches across directory boundaries.
* `?` matches a single character.
* `!` negates an earlier pattern (re-includes the path).
* Trailing spaces are stripped unless escaped with `\`.
* Matching is case-insensitive on macOS and Windows by default (matching the typical filesystem behavior) and case-sensitive on Linux.

## Examples

<CodeGroup>
  ```text Firmware project theme={"system"}
  # Vendor code stays read-only
  vendor/
  hal/
  third_party/

  # Generated outputs
  build/
  generated/
  *.elf
  *.bin
  *.hex
  ```

  ```text Mixed project theme={"system"}
  # Vendored libraries
  node_modules/
  third_party/

  # Build artifacts
  dist/
  build/

  # Secrets
  config/secrets.*
  .env.local
  ```
</CodeGroup>

## What happens when a path is matched

When the agent calls `writeFile` or `editFile` on a path that matches a pattern in `.embedderignore`:

1. The tool call returns a failure (no confirmation dialog is shown).
2. The agent receives a message naming the matched path and instructing it to stop and ask you for explicit permission before making any further edits in that scope.
3. You decide whether to grant permission for a one-off edit or remove the entry from `.embedderignore`.

The agent-facing message looks like this:

```text theme={"system"}
Editing `vendor/foo.c` is blocked by `.embedderignore`. Stop and ask the user
for explicit permission before making any further edits to paths under this
match. The user can either grant permission or remove the entry from
`.embedderignore`.
```

### What is and isn't blocked

| Surface                                              | Blocked? |
| ---------------------------------------------------- | -------- |
| `writeFile`                                          | Yes      |
| `editFile`                                           | Yes      |
| Shell writes detected in `bash` commands (see below) | Yes      |
| `readFile`, `grep`, `listDirectory`, `glob`, etc.    | No       |

Read, search, and listing tools are intentionally unaffected so the agent can still use matched files for context.

#### Shell write detection

For `bash` commands, Embedder scans the command for known write patterns and gates each detected target against `.embedderignore`. Detected forms include:

* Output redirection: `>` and `>>` (any file descriptor).
* `tee <file>`.
* `sed -i <file>` (in-place edits).
* `cp`, `mv`, `ln` (the destination argument).
* `dd of=<file>`.
* `rm`, `rmdir`, `unlink`, `touch`, `mkdir`.

If any target in a single command matches `.embedderignore`, the entire command is blocked and the agent gets a single failure message listing every blocked path.

<Warning>
  Shell-write detection is best-effort. Writes performed indirectly (custom scripts, `make` targets, language-level file I/O like `python -c "open(...)"`, or utilities not in the list above) can still hit ignored paths. Treat `.embedderignore` as a strong default for direct edits, not a sandbox.
</Warning>

## Reloading rules

Embedder caches each parsed `.embedderignore` and reloads it automatically when the file's inode, size, or modification time changes. You don't need to restart the session after editing or adding `.embedderignore` files.

## Negation and overrides

`!` re-includes a path that an earlier pattern would have matched, but with the same caveat as gitignore: if a parent directory is excluded with a directory pattern (`dir/`), files inside it cannot be re-included with `!` from the same file.

Two reliable ways to selectively allow a child of an ignored directory:

1. **Use a glob parent pattern** so the directory itself isn't excluded:

   ```text theme={"system"}
   config/*
   !config/public.json
   ```

2. **Drop a nested `.embedderignore`** in the protected directory and negate from there. The closer file overrides the parent.

   ```text .embedderignore (root) theme={"system"}
   secrets/
   ```

   ```text secrets/.embedderignore theme={"system"}
   !public.json
   ```

   With both files, edits to `secrets/public.json` are allowed while `secrets/tokens.json` remains blocked.

## Troubleshooting

* **Edits still go through on a path I expected to block.** Confirm the file is at or below the project root and the pattern matches. `git check-ignore -v <path>` is a quick way to verify gitignore-style matching. If the write came from a shell command, check whether it used a form covered by [shell write detection](#shell-write-detection); indirect writes (scripts, `make`, language-level I/O) aren't intercepted.
* **A pattern inside an ignored directory has no effect.** Embedder doesn't descend into matched directories. Move the pattern to a parent location.
* **I want to allow a one-off edit.** When the agent surfaces the blocked-edit message in chat, reply with explicit permission to proceed, or remove the entry from `.embedderignore`.
