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

# Air-Gapped Devin On-Disk Formats

> Stable file locations for the air-gapped Devin Desktop and CLI on macOS, Linux, and Windows, plus the audit-log JSONL schema and examples for SIEM ingestion.

> [!NOTE]
>
> This documentation is for the federal deployments of Devin. [Back to Devin Docs](/get-started/devin-intro)

The air-gapped CLI and Desktop keep all of their state in a small set of files with documented, stable formats. This page lists where each file lives, which ones you author, and the exact schema of the audit log so you can forward it to your SIEM.

***

## File locations

### Files you author

These are the machine-wide inputs. Each has a default path and an environment variable that overrides it; the variable must be set in the environment the agent starts from (see [API key environment variables](/federal/air-gapped/models-file#api-key-environment-variables) for how to do that for Desktop).

| File | Default path | Override | Format | Documented on |
| - | - | - | - | - |
| License | `/etc/devin/license.devin-onprem-license` | `DEVIN_LICENSE_FILE` | Signed token, single line | [License](/federal/air-gapped/license) |
| Models file | `/etc/devin/models.json` | `DEVIN_MODELS_FILE` | JSON, `"version": 0` | [Models file](/federal/air-gapped/models-file) |
| Auth file (optional, enables SSO) | `/etc/devin/auth.json` | `DEVIN_AUTH_FILE` | JSON, `"version": 0` | [SSO](/federal/air-gapped/sso) |
| CA bundle (optional) | none | `DEVIN_CA_BUNDLE` | PEM | [Network and certificates](/federal/air-gapped/network-and-certificates) |
| Machine-wide policy (optional) | Linux `/etc/devin/system.json`, macOS `/Library/Application Support/Devin/system.json` | none | JSON | [CLI system configuration](/cli/enterprise/system-config) |

The defaults are the same on macOS and Linux. On Windows the license, models file, and auth file default to `C:\ProgramData\Devin\` (`license.devin-onprem-license`, `models.json`, `auth.json`), the machine-wide policy file is `C:\ProgramData\Devin\system.json`, and the override variables are the same; [lock the folder down](/federal/air-gapped/install#windows-lock-down-the-configuration-folder) before placing files in it. The CLI reads these files and never writes to them, so you can manage them with your configuration-management tooling and make them read-only.

### Per-user state written by the CLI

The CLI follows the XDG base-directory layout on **both** macOS and Linux (it does not use `~/Library` for its own state). `XDG_CONFIG_HOME` and `XDG_DATA_HOME` are honored when set.

| Path | Contents |
| - | - |
| `~/.config/devin/config.json` | User configuration shared with the standard Devin CLI (permissions, `proxy`, and so on). Never contains credentials. See the [CLI config file reference](/cli/reference/configuration/config-file). |
| `~/.config/devin/mcp_config.json` | Locally configured MCP servers. |
| `~/.local/share/devin/sso_tokens.toml` | SSO token cache written by `devin auth login`, owner-only permissions (`0600`). Deleted by `devin auth logout`. |
| `~/.local/share/devin/cli-federal/sessions.db` | Session history (SQLite). Contains conversation content; treat it as sensitive. |
| `~/.local/share/devin/cli-federal/audit/` | Audit log directory: `audit.jsonl` plus rotated `audit-<timestamp>.jsonl` files and the `.audit.lock` advisory lock. Schema below. |

`cli-federal` is the product subdirectory used by the air-gapped build; it keeps this state separate from any standard Devin CLI install on the same machine, which uses `cli`.

On Windows the CLI does not read `XDG_*` variables. It keeps the same files under `%APPDATA%\devin\`, and its cache under `%LOCALAPPDATA%\devin\`:

| Path (Windows) | Contents |
| - | - |
| `%APPDATA%\devin\config.json` | User configuration, as above. |
| `%APPDATA%\devin\mcp_config.json` | Locally configured MCP servers. |
| `%APPDATA%\devin\sso_tokens.toml` | SSO token cache. |
| `%APPDATA%\devin\cli-federal\sessions.db` | Session history (SQLite). |
| `%APPDATA%\devin\cli-federal\audit\` | Audit log directory. |

### Desktop-specific state

The Desktop application is isolated from any other Devin Desktop or Windsurf install on the same machine:

| Path | Contents |
| - | - |
| `~/.devin-airgap-config/` | An isolated `XDG_CONFIG_HOME` that Desktop passes to the bundled agent. Inside it, `devin/config.json` is a symlink to the real `~/.config/devin/config.json`, so the CLI and the bundled agent share one user config. Nothing else from `~/.config/devin/` (notably `mcp_config.json`) is visible to the agent inside Desktop. |
| `~/.devin-airgap/` | Desktop extensions directory. |
| `~/.codeium/windsurf-airgap/` | Language-server state. |
| Linux `~/.config/Devin - Airgap/`, macOS `~/Library/Application Support/Devin - Airgap/` | Desktop user data: `User/settings.json` (including `devin.acp.agentEnv`), window state. |

The symlink is created at Desktop startup only if nothing exists at `~/.devin-airgap-config/devin/config.json`. If a regular file is already there, Desktop leaves it alone and the bundled agent uses that file instead of the shared one; the **Devin ACP** output channel logs a `WARNING: … is a regular file, not a symlink` line. Delete the file and restart Desktop to restore the link.

On Windows there is no symlink. Desktop's bundled agent and the CLI share `%APPDATA%\devin\config.json` directly, and Desktop does not load the user's `%APPDATA%\devin\mcp_config.json`. Desktop user data is in `%APPDATA%\Devin - Airgap\`.

Only `~/.devin-airgap-config/` and `~/.devin-airgap/` are safe to delete for a clean-slate reinstall. `~/.config/devin/` and `~/.local/share/devin/` also belong to the standalone CLI.

## Audit log

The air-gapped CLI writes a local, append-only, structured audit log. It is always on (there is no toggle), does not exist in any other Devin build, and is written to the workstation for your own review and SIEM ingestion.

### Location and rotation

| Property | Value |
| - | - |
| Active file | `~/.local/share/devin/cli-federal/audit/audit.jsonl` (Windows: `%APPDATA%\devin\cli-federal\audit\audit.jsonl`) |
| Format | JSON Lines: one self-contained JSON object per line, UTF-8 |
| Permissions | Directory and files are created owner-only (`0600`) |
| Rotation | When `audit.jsonl` reaches 10 MiB it is renamed to `audit-<UTC timestamp>.jsonl` (for example `audit-20260127T234500123Z.jsonl`) and a fresh file is started |
| Retention | At most 10 rotated files are kept; the oldest are deleted first |
| Concurrency | Rotation is guarded by the `.audit.lock` advisory lock, so concurrent CLI processes never double-rotate |

Ship rotated files to your SIEM before they age out if you need unbounded retention. Because the CLI only ever appends and never rewrites existing lines, a standard file-tailing collector (for example a Splunk universal forwarder or Filebeat input on `audit*.jsonl`) is sufficient.

### Redaction guarantees

Events carry paths and metadata only. The log never contains prompts, model responses, code, file contents, secret values, API keys, or full shell command lines: for shell tools only the program name (the first token) is recorded.

### Envelope (schema version 1)

Every line carries this envelope; per-event fields are flattened alongside it.

| Field | Type | Description |
| - | - | - |
| `schema_version` | number | Currently `1`. Bumped only on breaking changes. |
| `ts` | string | RFC 3339 UTC timestamp with milliseconds. |
| `pid` | number | Process ID of the emitting CLI process. |
| `event` | string | Event type; determines the remaining fields. |

Configure your parser to ignore unknown fields and unknown `event` values: new fields and event types may be added without a `schema_version` bump.

### Event types

#### `session_start`

Emitted when an agent session begins (new or resumed root session).

| Field | Type | Description |
| - | - | - |
| `session_id` | string | CLI session ID. Use it to join every other event of the session. |
| `source` | string | How the session started (for example `startup`). |
| `cli_version` | string | Released CLI version, as printed by `devin --version`. |
| `actor` | object | Identity attribution; see [`actor` object](#actor-object). |

```json theme={null}
{"schema_version":1,"ts":"2026-01-27T23:45:00.123Z","pid":4242,"event":"session_start","session_id":"a1b2","source":"startup","cli_version":"1.2.3","actor":{"os_user":"jsmith","git_user_name":"J. Smith","git_user_email":"jsmith@example.com","sso_issuer":"https://sso.example.com/realms/corp","sso_subject":"6f1c…","sso_user":"jsmith","sso_groups":["/devin-users"]}}
```

#### `session_end`

Emitted when the session ends or the agent shuts down.

| Field | Type | Description |
| - | - | - |
| `session_id` | string | CLI session ID. |
| `reason` | string | `prompt_input_exit`, `clear`, `resume`, `logout`, or `other`. |

```json theme={null}
{"schema_version":1,"ts":"2026-01-27T23:59:59.000Z","pid":4242,"event":"session_end","session_id":"a1b2","reason":"prompt_input_exit"}
```

Every `session_start` is paired with exactly one `session_end` for the same `session_id` on clean exit. The CLI runs the agent in a child process that it terminates on teardown, so the parent process records the child session's `session_end` (reason `other`) when the session finishes. A session killed by `SIGKILL` or power loss cannot write a final event; treat a `session_start` with no matching `session_end` as an abnormal termination.

#### `tool_call`

Emitted after each tool the agent executes.

| Field | Type | Description |
| - | - | - |
| `session_id` | string | CLI session ID. |
| `tool_name` | string | Tool name (for example `read`, `write`, `exec`). |
| `tool_id` | string | Unique ID of this tool invocation. |
| `success` | boolean | Whether the tool reported success. |
| `program` | string, optional | For shell tools: the program name only, never arguments. |
| `paths` | string\[], optional | Filesystem paths the tool was scoped to. Omitted when empty. |

```json theme={null}
{"schema_version":1,"ts":"2026-01-27T23:45:07.001Z","pid":4242,"event":"tool_call","session_id":"a1b2","tool_name":"exec","tool_id":"t_01","success":true,"program":"cargo"}
```

#### `file_read` and `file_write`

Emitted in addition to `tool_call`, once per path in the tool's resolved permission scope. They describe the access the tool was *scoped to*, not verified I/O: a tool approved with read scope over several paths emits a `file_read` per path even if it touched only some of them, and the events are emitted whether or not the tool call succeeded.

| Field | Type | Description |
| - | - | - |
| `session_id` | string | CLI session ID. |
| `path` | string | Filesystem path. |

```json theme={null}
{"schema_version":1,"ts":"2026-01-27T23:45:09.410Z","pid":4242,"event":"file_write","session_id":"a1b2","path":"/home/jsmith/repo/src/main.rs"}
```

#### `model_call`

Emitted after each inference request to a model endpoint from your models file.

| Field | Type | Description |
| - | - | - |
| `session_id` | string | CLI session ID. |
| `model` | string | Model name from the models file. |
| `endpoint` | string, optional | Base URL of the configured endpoint. |
| `input_tokens` | number, optional | Total input tokens, including cache reads. |
| `output_tokens` | number, optional | Output tokens. |
| `cache_read_tokens` | number, optional | Cache-read tokens, when the endpoint reports them. |
| `cache_creation_tokens` | number, optional | Cache-write tokens, when reported. |

Token fields are omitted when the endpoint does not report usage.

```json theme={null}
{"schema_version":1,"ts":"2026-01-27T23:45:12.900Z","pid":4242,"event":"model_call","session_id":"a1b2","model":"llama-3-70b","endpoint":"https://models.internal:8000/v1","input_tokens":5120,"output_tokens":384}
```

#### `auth`

| Field | Type | Description |
| - | - | - |
| `action` | string | One of the actions below. |
| `actor` | object | Identity attribution; see [`actor` object](#actor-object). |
| `error_code` | string, optional | On `sso_login_denied` and `sso_revalidation_failed`: the `IDPnnn` code the user was shown. Omitted on successful actions. |

| `action` | Description |
| - | - |
| `identity_resolved` | Identity attribution at session start and after each `devin auth` command (so `status` names the login it validated and `logout` names none). |
| `license_validated` | The license file validated successfully at startup. |
| `license_installed` | A license file was written through Desktop's Settings page. Carries no path or file contents. |
| `sso_login` | SSO login completed (`devin auth login` or the Desktop sign-in). |
| `sso_login_denied` | SSO login refused after the IdP answered: the required group is missing (`IDP004`), or the returned ID token failed validation or was absent (`IDP005`). `actor` carries the identity the IdP vouched for when the token validated; nothing is cached. |
| `sso_refresh` | SSO tokens refreshed against the IdP. |
| `sso_logout` | SSO logout (`devin auth logout` or the Desktop sign-out). |
| `sso_revalidation_failed` | A running agent lost its SSO login and is shutting down; see [Revalidation in running sessions](/federal/air-gapped/sso#revalidation-in-running-sessions). |

```json theme={null}
{"schema_version":1,"ts":"2026-01-27T23:44:58.000Z","pid":4241,"event":"auth","action":"sso_login","actor":{"os_user":"jsmith","git_user_name":"J. Smith","git_user_email":"jsmith@example.com","sso_issuer":"https://sso.example.com/realms/corp","sso_subject":"6f1c…","sso_user":"jsmith","sso_groups":["/devin-users"]}}
{"schema_version":1,"ts":"2026-01-28T08:10:02.512Z","pid":5150,"event":"auth","action":"sso_login_denied","error_code":"IDP004","actor":{"os_user":"rjones","sso_issuer":"https://sso.example.com/realms/corp","sso_subject":"a90d…","sso_user":"rjones","sso_groups":["/contractors"]}}
{"schema_version":1,"ts":"2026-01-28T09:00:00.000Z","pid":4242,"event":"auth","action":"sso_revalidation_failed","error_code":"IDP003","actor":{"os_user":"jsmith","sso_issuer":"https://sso.example.com/realms/corp","sso_subject":"6f1c…","sso_user":"jsmith","sso_groups":["/devin-users"]}}
```

### `actor` object

Identity attribution is the OS user, the local git identity, and (when SSO is configured) the identity from the validated ID token. Fields are omitted when unavailable.

| Field | Type | Description |
| - | - | - |
| `os_user` | string, optional | `$USER`. |
| `git_user_name` | string, optional | `git config user.name`. |
| `git_user_email` | string, optional | `git config user.email`. |
| `sso_issuer` | string, optional | The IdP issuer URL the token was validated against. |
| `sso_subject` | string, optional | The ID token's `sub` claim. |
| `sso_user` | string, optional | The identity `devin auth status` prints (`preferred_username`, `email`, or `sub`). |
| `sso_groups` | string\[], optional | The token's group claims (`groups` by default, or the configured `groups_claim`). |

The SSO fields are present on every `auth` event that has a validated token at hand (`sso_login`, `sso_refresh`, `sso_logout`, `sso_login_denied`), on `sso_revalidation_failed` for the login the process validated (or, when it validated none, the login still in the token cache), and on `session_start` and `identity_resolved` for the login the running process validated at startup. `tool_call`, `file_read`, `file_write`, and `model_call` carry no `actor`; attribute them through `session_id` to their `session_start`.

> [!NOTE]
>
> `sso_groups` records each user's IdP group memberships on the local machine. The audit directory and files are owner-only; include them in your data-handling review if group names are sensitive in your environment.

## Diagnostics report

`devin diagnostics` writes a redacted, plain-text report you can review before sending it to Cognition support. It contains only versions, configuration shape (whether each file exists and parses), model names, whether each API-key variable is set, and audit-log statistics; it never contains prompts, code, file contents, secret values, endpoint URLs, or environment-variable values.

```sh theme={null}
devin diagnostics
```

```text theme={null}
Diagnostics written to devin-diagnostics-20260127T234500Z.txt
The report is plain text and stays on this machine; review it before sharing.
```

Use `--output <path>` to choose the file name. The report is written owner-only (`0600`). See [Troubleshooting](/federal/air-gapped/troubleshooting) for what to include in a support request.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.