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

# Filesystem

> Trigger jobs when files or directories change on disk.

Filesystem signals fire when files or directories change under a watched path. Friday uses the OS-native file watcher (inotify on Linux, FSEvents on macOS) — no external dependency, no credentials.

## Config

| Field       | Type    | Required | Default | Description                                     |
| ----------- | ------- | -------- | ------- | ----------------------------------------------- |
| `path`      | string  | Yes      | —       | Absolute or workspace-relative path to watch    |
| `recursive` | boolean | No       | `true`  | Watch subdirectories when `path` is a directory |

## Example

```yaml workspace.yml theme={null}
signals:
  artifacts-changed:
    title: "Artifacts changed"
    description: "Fires when any file under the artifacts/ directory is modified"
    provider: fs-watch
    config:
      path: "./artifacts"
      recursive: true
```

## Path semantics

* **Absolute paths** — e.g. `/var/log/app` — are watched as-is.
* **Relative paths** — e.g. `./artifacts` or `data/` — are resolved against the space's working directory.
* If the path is a **file**, `recursive` is ignored and only that file is watched.
* If the path is a **directory**, the default `recursive: true` means every nested file counts; set `recursive: false` to watch only direct children.

<Warning>
  The watched path must exist when Friday starts. If it's missing, the signal fails to initialize and the space logs a warning — Friday won't create directories for you.
</Warning>

## What triggers the signal

The signal fires on any change event the OS surfaces — create, modify, rename, delete. Each event produces one invocation; if you edit three files in quick succession, the job runs three times.

<Tip>
  OS-level watchers are sensitive to editor temp files (`.swp`, `.tmp`, `~`) and atomic-save patterns that rename a temp file over the target. If your job is noisy, narrow the watched path to a subdirectory that only contains final output.
</Tip>

## Payload

The signal payload includes the changed file's path and the event type. If your job needs to read the file, the path is right there:

```yaml workspace.yml theme={null}
signals:
  new-upload:
    title: "New upload"
    description: "Process files dropped into the uploads directory"
    provider: fs-watch
    config:
      path: "./uploads"
      recursive: false
    schema:
      type: object
      properties:
        path: { type: string }
        event: { type: string }
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="Signal doesn't fire on changes">
    * Confirm the path exists on disk (`ls <path>`) when Friday starts.
    * Check OS limits — on Linux, `inotify` has a per-user watcher limit (`/proc/sys/fs/inotify/max_user_watches`). Large recursive watches can exhaust it.
    * Some network filesystems (NFS, SMB) don't surface OS-level events. Watch a local path instead.
  </Accordion>

  <Accordion title="Signal fires multiple times per save">
    Editors often save via "write temp → rename over target", producing two or three events per logical save (create temp, rename, delete temp). Debounce in the job if this causes duplicate work.
  </Accordion>

  <Accordion title="Friday startup fails with permission errors">
    Friday needs read access to the watched path. For workspace-relative paths, Friday's process owner must own (or have ACL access to) the directory.
  </Accordion>
</AccordionGroup>
