---
title: "Extensions · intentic sandbox API"
description: "Installed extensions: their settings, their readiness, their updates and their processes. Every route in the extensions group of the intentic sandbox API, with its input, its answer and a playground."
url: "https://intentic.dev/api/extensions/"
---

Agent setup

# Extensions

Installed extensions: their settings, their readiness, their updates and their processes

**On this page (15 sections)**

- [Installed extensions](#extensions-list)
- [Write a new extension in place](#extensions-create)
- [An extension's settings](#extensions-settings)
- [Change an extension's settings](#extensions-setSettings)
- [Turn an extension on or off](#extensions-setEnabled)
- [Record what an extension just used](#extensions-recordUsage)
- [Whether an extension is fit to share](#extensions-readiness)
- [Look for extension updates now](#extensions-checkUpdates)
- [What an update would change](#extensions-updatePreview)
- [Update an extension](#extensions-applyUpdate)
- [Go back to the previous version](#extensions-revert)
- [How an extension should handle its own updates](#extensions-setUpdatePolicy)
- [Whether an extension's background process is up](#extensions-processStatus)
- [Start an extension's background process](#extensions-processStart)
- [Stop an extension's background process](#extensions-processStop)

The runtime half of the extension format documented under Developers. These routes enumerate what is installed, read and write each one's settings, switch it on or off, check for updates and apply or undo one, and start or stop the long-running processes an extension declares.

15 calls. Pick one to open it, or use the list on the right.

**GET`/extensions` Installed extensions**

Every extension installed here, resolved to the manifest the owner approved, which is what the app boots its extension host from. The code itself is served separately, because raw script bytes are not a JSON answer.

### What you send

Nothing. Call it as it is.

### What comes back

| Field | Type |
| --- | --- |
| `extensions` What is installed | object[] |
| `id` The extension's id | string |
| `manifest` What it declares about itself: what… | object |
| `$schema` The authoring schema, for editor completion… | string |
| `publisher` | string |
| `name` | string |
| `version` Your own semver, display and identity… | string |
| `category` Which section of the Extensions tab… | string |
| `art` This extension's own mark, as a… | string |
| `logo` A simple-icons slug, fetched from a… | string |
| `icon` A name from the host's own… | string |
| `engines` A semver range over the host's… | object |
| `intentic` | string |
| `entry` Repo-relative path of your prebuilt single-file… | string |
| `server` Repo-relative path of your prebuilt single-file… | string |
| `permissions` How far this extension may reach… | object |
| `sandbox` Daemon routes your UI half may… | string[] |
| `daemon` Daemon routes your SERVER half may… | string[] |
| `contributes` | object |
| `views` Sidebar elements this extension may register… | object[] |
| `files` Which workspace files back your views,… | object[] |
| `viewers` File formats this extension can render | object[] |
| `documents` Per-directory documents this extension can offer | object[] |
| `commands` Commands this extension may register handlers… | object[] |
| `settings` Typed settings the host renders into… | object[] |
| `processes` Long-lived background processes the daemon runs… | object[] |
| `agent` Declare that this checkout is also… | object |
| `environment` A Dockerfile fragment baked into the… | object |
| `capabilities` Capability cards this pack adds to… | object[] |
| `listener` A realtime event source this extension… | object |
| `automationTemplates` Starting points this pack offers in… | object[] |
| `bin` A checkout-relative directory of executables the… | string |
| `commit` Exactly which commit is installed | string |
| `source` Where the code comes from: baked… | "builtin" | "installed" | "workspace" |
| `enabled` The owner's switch | boolean |
| `essential` Its switch is fixed on, because… | boolean |
| `usage` How much of the reach it… | object |
| `backend` Present only for an extension that… | object |
| `state` How its server half is doing | "running" | "error" | "absent" | "incompatible" … (6) |
| `detail` What went wrong, so a backend… | string |
| `update` A newer version waiting | object |
| `ref` The commit being offered | string |
| `version` What it calls itself | string |
| `url` Where it comes from | string |
| `path` Where inside that repository it lives | string |
| `trust` Whether anybody vouched for it, or… | "verified" | "listed" |
| `securityFix` This release fixes a security problem… | boolean |
| `registry` Which registry said so | string |
| `at` When it was published | string |
| `needsReview` Why this one was not taken… | string |
| `review` An agent has already read the… | object |
| `conversationId` Where to read what it found | string |
| `at` When it looked | string |
| `advisory` A security warning about the installed… | object |
| `reason` Why the registry pulled the listing,… | string |
| `registry` Which registry said so | string |
| `at` When | string |
| `autoDisabled` Whether the sandbox has already switched… | boolean |
| `health` How it has behaved since the… | object |
| `state` How it has behaved since the… | "watching" | "healthy" | "unhealthy" |
| `detail` What is going wrong, when something… | string |
| `fromRef` Which version it was updated from,… | string |
| `at` When the watching started | string |
| `autoReverted` The update was already rolled back… | boolean |
| `previous` The version kept one step back,… | object |
| `ref` The commit that was running before | string |
| `version` What it called itself | string |
| `updatePolicy` The owner's standing answer for this… | object |
| `updates` | "notify" | "agent" | "auto" |
| `advisories` | "auto-disable" | "notify" |
| `invalid` Extensions written here that could not… | object[] |
| `dir` Which folder | string |
| `error` Why it could not be read | string |
| `updatesCheckedAt` When updates were last looked for | string |

Try it answered in this tab

curl

```bash
curl "$SANDBOX/extensions" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.extensions.list();
```

**POST`/extensions/workspace` Write a new extension in place**

Scaffolds a working extension into this workspace and installs it. The only call here that creates one, and it exists because that folder is otherwise reachable only through an agent's file tools, which is a fine way to change an extension and a poor way to meet the idea of one.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `publisher` required Who it is by, which together… | string | body |
| `name` required What it is called | string | body |

### What comes back

| Field | Type |
| --- | --- |
| `id` The id it was given | string |
| `dir` Where its files are, so you… | string |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/extensions/workspace" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"publisher":"…","name":"nightly changelog"}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.extensions.create({
 "publisher": "…",
 "name": "nightly changelog"
});
```

**GET`/extensions/{id}/settings` An extension's settings**

The current values for the settings this extension declared it has.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required Which connection | string | address |

### What comes back

| Field | Type |
| --- | --- |
| `settings` The values, minus anything marked secret | object |
| `secretsSet` Which of its secret settings actually… | string[] |

Try it answered in this tab

curl

```bash
curl "$SANDBOX/extensions/a1b2c3d4/settings" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.extensions.settings({
 "id": "a1b2c3d4"
});
```

**POST`/extensions/{id}/settings` Change an extension's settings**

Writes new values. A key the extension never declared is refused rather than quietly stored, the same honesty rule that governs everything else an extension claims.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required Which extension | string | address |
| `settings` required The values to write | object | body |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/extensions/a1b2c3d4/settings" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"settings":{"src/app.ts":"…","README.md":"…"}}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.extensions.setSettings({
 "id": "a1b2c3d4",
 "settings": {
 "src/app.ts": "…",
 "README.md": "…"
 }
});
```

**POST`/extensions/{id}/enabled` Turn an extension on or off**

The owner's switch. Turning one off stops its background processes at once. What it contributes to an agent's tools is rebuilt at the start of the next turn, and anything it adds to the sandbox image only at the next rebuild.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required Which extension | string | address |
| `enabled` required On or off | boolean | body |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/extensions/a1b2c3d4/enabled" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"enabled":true}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.extensions.setEnabled({
 "id": "a1b2c3d4",
 "enabled": true
});
```

**POST`/extensions/{id}/usage` Record what an extension just used**

Written by the app rather than measured by the daemon, because the permission gate runs in the browser: from the sandbox's side an extension's traffic is indistinguishable from anyone else's. This is how the record of which powers an extension actually exercises gets kept.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required Which extension | string | address |
| `used` required Which of its declared powers it… | object | body |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/extensions/a1b2c3d4/usage" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"used":{"src/app.ts":9,"README.md":9}}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.extensions.recordUsage({
 "id": "a1b2c3d4",
 "used": {
 "src/app.ts": 9,
 "README.md": 9
 }
});
```

**GET`/extensions/{id}/readiness` Whether an extension is fit to share**

The checks that can be answered from an extension's own files, for an author about to publish. Read on demand rather than carried on the list, because it reads the code off disk each time.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required Which connection | string | address |

### What comes back

| Field | Type |
| --- | --- |
| `checks` Everything that can be checked from… | object[] |
| `id` Which check | string |
| `label` What it is called | string |
| `status` How it went | "pass" | "warn" | "fail" |
| `detail` What it found | string |

Try it answered in this tab

curl

```bash
curl "$SANDBOX/extensions/a1b2c3d4/readiness" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.extensions.readiness({
 "id": "a1b2c3d4"
});
```

**POST`/extensions/updates/check` Look for extension updates now**

Compares every installed extension against its source and reports what is newer, what carries an advisory and what looks unhealthy. This also happens on a schedule; call it to check on demand.

### What you send

Nothing. Call it as it is.

### What comes back

| Field | Type |
| --- | --- |
| `ok` The check ran | true |
| `checkedAt` When, so a screen can date… | string |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/extensions/updates/check" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.extensions.checkUpdates();
```

**POST`/extensions/{id}/update/preview` What an update would change**

The read before the click: which versions are involved and exactly which powers the new code asks for that the running one does not. Costs one throwaway copy of the source, the same as browsing a registry entry.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required Which extension | string | address |
| `ref` Which commit, in full | string | body |

### What comes back

| Field | Type |
| --- | --- |
| `ref` The commit this would install | string |
| `version` What that version calls itself | string |
| `installedVersion` What is running now | string |
| `engines` Which sandbox versions the new one… | string |
| `compatible` Whether this sandbox is one of… | boolean |
| `powers` Exactly what the new code asks… | object |
| `added` What the new version asks for… | string[] |
| `removed` What it no longer asks for | string[] |
| `unchanged` What stays the same | string[] |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/extensions/a1b2c3d4/update/preview" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"ref":"refs/heads/main"}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.extensions.updatePreview({
 "id": "a1b2c3d4",
 "ref": "refs/heads/main"
});
```

**POST`/extensions/{id}/update` Update an extension**

The whole swap as one transaction: fetch, check, quiet the running one, replace it while keeping the outgoing copy one step back, restart and watch it come up. The existing configuration is kept, so a token for a private source survives what removing and re-adding would lose. Owner only, because it changes what code runs.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required Which extension | string | address |
| `ref` Which commit, in full | string | body |

### What comes back

| Field | Type |
| --- | --- |
| `ok` It went through | true |
| `ref` Which commit is now running | string |
| `rebuildNeeded` The new version changes what the… | boolean |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/extensions/a1b2c3d4/update" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"ref":"refs/heads/main"}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.extensions.applyUpdate({
 "id": "a1b2c3d4",
 "ref": "refs/heads/main"
});
```

**POST`/extensions/{id}/revert` Go back to the previous version**

Swaps the copy kept from before the last update back into place. Owner only, for the same reason updating is.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required Which connection | string | address |

### What comes back

| Field | Type |
| --- | --- |
| `ok` It went through | true |
| `ref` Which commit is now running | string |
| `rebuildNeeded` The new version changes what the… | boolean |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/extensions/a1b2c3d4/revert" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.extensions.revert({
 "id": "a1b2c3d4"
});
```

**POST`/extensions/{id}/update-policy` How an extension should handle its own updates**

The owner's standing answer for one extension: tell me, have an agent look at it, or just do it. Security advisories can be opted out of separately.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required Which extension | string | address |
| `updates` What to do about a newer… | "notify" | "agent" | "auto" | body |
| `advisories` What to do about a security… | "auto-disable" | "notify" | body |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/extensions/a1b2c3d4/update-policy" \
 -H "x-intentic-control: $INTENTIC_TOKEN" \
 -H "content-type: application/json" \
 -d '{"updates":"notify","advisories":"auto-disable"}'
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.extensions.setUpdatePolicy({
 "id": "a1b2c3d4",
 "updates": "notify",
 "advisories": "auto-disable"
});
```

**GET`/extensions/{id}/processes/{name}` Whether an extension's background process is up**

The state of one process an extension declared, with the port it was given and its preview address if it has one.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required Which extension | string | address |
| `name` required Which of its declared processes | string | address |

### What comes back

| Field | Type |
| --- | --- |
| `name` Which process | string |
| `running` Whether it is up | boolean |
| `port` The port it was given | number |
| `previewUrl` Where to open it, when it… | string |

Try it answered in this tab

curl

```bash
curl "$SANDBOX/extensions/a1b2c3d4/processes/nightly%20changelog" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.extensions.processStatus({
 "id": "a1b2c3d4",
 "name": "nightly changelog"
});
```

**POST`/extensions/{id}/processes/{name}/start` Start an extension's background process**

Brings one of an extension's declared processes up in an attachable terminal.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required Which extension | string | address |
| `name` required Which of its declared processes | string | address |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/extensions/a1b2c3d4/processes/nightly%20changelog/start" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.extensions.processStart({
 "id": "a1b2c3d4",
 "name": "nightly changelog"
});
```

**POST`/extensions/{id}/processes/{name}/stop` Stop an extension's background process**

Shuts one of an extension's declared processes down and frees its port.

### What you send

| Field | Type | Where |
| --- | --- | --- |
| `id` required Which extension | string | address |
| `name` required Which of its declared processes | string | address |

### What comes back

| Field | Type |
| --- | --- |
| `ok` Always true | true |

Try it answered in this tab

curl

```bash
curl -X POST "$SANDBOX/extensions/a1b2c3d4/processes/nightly%20changelog/stop" \
 -H "x-intentic-control: $INTENTIC_TOKEN"
```

TypeScript

```typescript
import { sandbox } from "@intentic/sandbox-client";

const result = await sandbox.extensions.processStop({
 "id": "a1b2c3d4",
 "name": "nightly changelog"
});
```

More in Agent setup

[Previous ← Skills](https://intentic.dev/api/skills/)[Next Settings →](https://intentic.dev/api/settings/)
