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

# Air-Gapped Devin License File

> Install, inspect, and renew the offline license file that air-gapped Devin Desktop and CLI validate at startup, with expected key IDs and LIC error codes.

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

Air-gapped builds of Devin Desktop and the Devin CLI have no cloud login. Access is controlled by a **signed license file** that the product validates fully offline every time it starts. Each license is issued to one seat holder from the portal and consumes one seat of your team's air-gapped entitlement.

## Where the license lives

| | |
| - | - |
| Default path | `/etc/devin/license.devin-onprem-license` |
| Default path (Windows) | `C:\ProgramData\Devin\license.devin-onprem-license` |
| Override | `DEVIN_LICENSE_FILE=<path>` |

The bundled Desktop agent and the standalone CLI read the same file. Install it before first launch; see [Install → Step 4](/federal/air-gapped/install#step-4-place-the-license-and-models-file). Desktop users can also install a license in Devin settings: the bundled agent validates the file offline, refuses to overwrite a file owned by another user, and records a `license_installed` audit event. On Windows, when the license file is owned by an administrator, a standard user cannot replace it from Desktop (the install is refused with `LIC001`); an administrator can. [Lock down `C:\ProgramData\Devin\`](/federal/air-gapped/install#windows-lock-down-the-configuration-folder) before placing the file.

## Issue a license from the portal

1. Sign in to the portal and open your **Team** page. The **Air-gapped licenses** section shows how many seats are used, the entitlement period, and the default license duration.
2. Click **Generate license**.
3. Enter a **label** (for example the hostname or the user's name), the **assignee email**, and the **duration in days**. The duration defaults to your entitlement's default and is capped both by your entitlement's maximum and by the end of the entitlement period; the review step shows the projected expiry date.
4. Confirm. The portal reports **License generated** and offers **Download license file**. The download is the signed `.devin-onprem-license` file; transfer it to the air-gapped host by your approved media process.

The **Issued licenses** table lists every license with its status (**Active**, **Expiring soon**, **Expired**, **Revoked**). You can re-download an active license from this table. Revoking or reissuing a license, and freeing a seat once all seats are in use, is done by your support team.

## What the file contains

The file is a single JSON Web Token in compact form (`header.payload.signature`), signed with EdDSA (Ed25519). The header's `kid` names the public key that signed it; the product ships every environment's public key, so nothing is fetched at validation time. Claims:

| Claim | Meaning |
| - | - |
| `license_id` | Unique ID of this license |
| `account_id` | Your account |
| `seat_label` | The seat holder, typically an email address |
| `iat` / `nbf` | Validity start (Unix seconds) |
| `exp` | Validity end (Unix seconds) |
| `product` | Always `devin-onprem` |
| `entitlements` | List of entitlement strings; may be empty |

Validation checks the signature against the embedded key selected by `kid`, the `nbf`/`exp` window with a 24-hour clock-skew allowance in each direction, and the `product` claim.

## Inspect a license

### Check the key ID

Decode the JWT header and read `kid`. This one-liner works on both Linux and macOS: it converts base64url to base64 and pads it, because the BSD `base64` shipped with macOS silently truncates unpadded input.

```sh theme={null}
h=$(cut -d. -f1 < /etc/devin/license.devin-onprem-license | tr '_-' '/+')
while [ $(( ${#h} % 4 )) -ne 0 ]; do h="$h="; done
printf '%s' "$h" | base64 -d | jq -r .kid
```

```text theme={null}
fedstart-key-1
```

Expected values:

| Portal environment | Expected `kid` |
| - | - |
| FedStart production (`windsurf.fedstart.com`) | `fedstart-key-1` |
| FedStart staging | `fedstart-staging-key-1` |

A different `kid`, or an empty result, means the file is not a license issued for this product, or it was corrupted in transfer.

### Check the seat, account, and expiry

`devin auth status` works even when the license is missing or invalid, so you can use it to diagnose:

```sh theme={null}
devin auth status
```

```text theme={null}
Air-gapped build: access is license-based.
  License file:  /etc/devin/license.devin-onprem-license
  Identity:      alice <alice@example.gov>
  Seat:          alice@example.gov
  Account:       acme
  Expires:       2027-03-01 (340 day(s) left)
```

`Identity` is the local attribution identity (OS user name plus `git config user.email`); it is recorded in the audit log and is independent of the license. If the file cannot be validated, the last line is instead `License:       INVALID — LIC00X: <reason>`.

The `license` check in `devin airgap doctor` reports the same seat, account, and expiry, and turns to `warn` within 30 days of expiry.

## Startup and revalidation behavior

* On every start, the CLI validates the license and prints one line to stderr:

  ```text theme={null}
  Devin on-prem license: seat alice@example.gov (account acme), expires 2027-03-01. Local user: alice <alice@example.gov>.
  ```

  If the license expires within 30 days, a `Warning: license expires in N day(s)` line follows.
* Long-running processes (Desktop's bundled agent, the CLI REPL) re-verify the file at most once an hour, **before starting a new session or turn**. In-flight work is never interrupted.
* A license expired for more than 24 hours blocks new sessions and turns. In Desktop, the chat panel shows ACP error `-32019 license_invalid`; the specific `LIC00X` cause is in **View → Output → Devin ACP**.
* Failures are not cached: installing a renewed file takes effect on the next turn without restarting.
* A few commands run without a valid license so you can repair a host: `devin auth status`, `devin airgap doctor`, `devin doctor`, `devin diagnostics`, `devin models validate`, and `devin version`.

## Renew or replace a license

1. Generate a new license for the same seat holder from the portal (see above). If the seat is already in use, ask your support team to revoke the old license first.
2. Copy the new file over the existing one at `/etc/devin/license.devin-onprem-license` (or the path in `DEVIN_LICENSE_FILE`). Keep the file owned by the account that runs Devin, or by root with read access for that account. On Windows the default path is `C:\ProgramData\Devin\license.devin-onprem-license`; replace the file from an elevated session.
3. Confirm:

   ```sh theme={null}
   devin auth status | grep Expires
   ```

   ```text theme={null}
     Expires:       2028-03-01 (705 day(s) left)
   ```

No restart is required; the next session or turn picks up the new file.

## Error codes

All license failures are printed as `LIC00X: <message>`, followed by the path that was checked and how to override it.

| Code | Meaning | What to do |
| - | - | - |
| `LIC001` | License file missing or unreadable | Install the file at the default path or set `DEVIN_LICENSE_FILE`; check file permissions for the user running Devin |
| `LIC002` | Malformed file: not a valid EdDSA JWT, or no `kid` in the header | Re-download the license from the portal; make sure the file was transferred as-is (no added newline, wrapping, or encoding change) |
| `LIC003` | Signature verification failed | The payload was altered after signing. Re-download the license |
| `LIC004` | Unknown `kid` (no matching embedded public key) | Check the `kid` as shown above. The license was issued by a different environment, or your build predates a key rotation; install the current release |
| `LIC005` | Expired beyond the 24-hour grace period | Renew the license |
| `LIC006` | Not yet valid (issued more than 24 hours in the future) | Check the host clock; if it is correct, contact your support team |
| `LIC007` | Wrong `product` claim (not `devin-onprem`) | The file is not an air-gapped Devin license. Re-download from the portal |

The complete catalog across all namespaces is in [Error codes](/federal/air-gapped/error-codes).


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