# CoworkRoutineContext

The context a routine's default export receives:
 `export default async (args, ctx: CoworkRoutineContext) => result`. A deployed routine
 (`cowork deploy`) gets [CoworkDeployedRoutineContext](/docs/reference/sdk/interfaces/coworkdeployedroutinecontext.md) instead.

## Properties

### auth

```ts
auth: object;
```

Who is signed into Cowork, and their short-lived Firebase ID token. Read on every call
 (the token rotates hourly — never keep one from the start of a long run).

#### getIdToken

```ts
getIdToken: () => Promise<string | null>;
```

The ID token to call an authenticated API with — null when signed out, or when the
 token is too close to expiring to be trusted.

##### Returns

`Promise`\<`string` \| `null`\>

#### getState

```ts
getState: () => Promise<{
  authenticated: boolean;
  user:   | {
     displayName: string | null;
     email: string | null;
     uid: string;
   }
     | null;
}>;
```

`authenticated` and the account (`user`), or `user: null` when nobody is signed in.

##### Returns

`Promise`\<\{
  `authenticated`: `boolean`;
  `user`:   \| \{
     `displayName`: `string` \| `null`;
     `email`: `string` \| `null`;
     `uid`: `string`;
   \}
     \| `null`;
\}\>

***

### badge

```ts
badge: (count) => Promise<void>;
```

This routine's app's count on the OS badge — as `cowork.badge`: latest wins,
 0 clears. Report it on every poll: `await ctx.badge(unread)`.

#### Parameters

| Parameter | Type |
| ------ | ------ |
| `count` | `number` |

#### Returns

`Promise`\<`void`\>

***

### browser

```ts
browser: object;
```

The desktop app's built-in browser, step by step: `snapshot()` lists the page's
 actionable elements with refs (`ref_3 button "Sign in"`), then `click` / `fill` / `type`
 / `waitFor` act on a ref or a CSS selector. Pages keep the user's own sign-ins, so
 `evaluate` can call a site's API with its cookies. Only in the desktop app: without it
 every call throws BrowserUnavailableError (`status()` is the cheap check); a failed
 action throws with the browser's message. Calls without a `tabIndex` act on the active
 tab.

#### back

```ts
back: () => Promise<{
  ok: boolean;
  url: string;
}>;
```

##### Returns

`Promise`\<\{
  `ok`: `boolean`;
  `url`: `string`;
\}\>

#### click

```ts
click: (refOrSelector) => Promise<{
  found: boolean;
  label?: string;
  role?: string;
}>;
```

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `refOrSelector` | `string` |

##### Returns

`Promise`\<\{
  `found`: `boolean`;
  `label?`: `string`;
  `role?`: `string`;
\}\>

#### evaluate

```ts
evaluate: <T>(js, opts?) => Promise<T>;
```

Run JS in a tab and get its FULL value back (any size; JSON-serializable). `js` is the
 body of an async function — use `return`. `fetch` inside it sends the page's cookies,
 so open the tab on the origin you mean to call first. `tabIndex` (from `tabs.list()`)
 runs in that tab WITHOUT activating it — resolve it each run, indices shift when tabs
 close. `world`: "isolated" (default — same DOM and cookies, separate globals, the page
 cannot see the script) or "main" (the site's own globals).

##### Type Parameters

| Type Parameter | Default type |
| ------ | ------ |
| `T` | `unknown` |

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `js` | `string` |
| `opts?` | \{ `tabIndex?`: `number`; `world?`: `"isolated"` \| `"main"`; \} |
| `opts.tabIndex?` | `number` |
| `opts.world?` | `"isolated"` \| `"main"` |

##### Returns

`Promise`\<`T`\>

#### fill

```ts
fill: (refOrSelector, value, submit?) => Promise<{
  found: boolean;
  ok?: boolean;
  value?: string;
}>;
```

Set a form field (text / select / checkbox / radio) the way a user would, so
 framework-controlled inputs keep the value; `submit` presses Enter after.

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `refOrSelector` | `string` |
| `value` | `string` |
| `submit?` | `boolean` |

##### Returns

`Promise`\<\{
  `found`: `boolean`;
  `ok?`: `boolean`;
  `value?`: `string`;
\}\>

#### find

```ts
find: (query, limit?) => Promise<{
  matches: object[];
  query: string;
}>;
```

Elements whose label matches `query`, with their refs (`limit`: default 10, at most 50).

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `query` | `string` |
| `limit?` | `number` |

##### Returns

`Promise`\<\{
  `matches`: `object`[];
  `query`: `string`;
\}\>

#### forward

```ts
forward: () => Promise<{
  ok: boolean;
  url: string;
}>;
```

##### Returns

`Promise`\<\{
  `ok`: `boolean`;
  `url`: `string`;
\}\>

#### hover

```ts
hover: (refOrSelector) => Promise<{
  found: boolean;
}>;
```

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `refOrSelector` | `string` |

##### Returns

`Promise`\<\{
  `found`: `boolean`;
\}\>

#### inject

```ts
inject: (spec) => Promise<{
  id: string;
  ok: boolean;
  persist: boolean;
  url: string;
  value: unknown;
  world: string;
}>;
```

Apply CSS and/or JS to the page. `world` as in `evaluate`; `persist` re-applies after
 every navigation (an app that re-renders on each click); the same `id` replaces an
 earlier injection. `value` is the script's completion value, cut at 4096 characters —
 use `evaluate` for anything long. `tabIndex` targets a tab without activating it.

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `spec` | \{ `css?`: `string`; `id?`: `string`; `js?`: `string`; `persist?`: `boolean`; `tabIndex?`: `number`; `world?`: `"isolated"` \| `"main"`; \} |
| `spec.css?` | `string` |
| `spec.id?` | `string` |
| `spec.js?` | `string` |
| `spec.persist?` | `boolean` |
| `spec.tabIndex?` | `number` |
| `spec.world?` | `"isolated"` \| `"main"` |

##### Returns

`Promise`\<\{
  `id`: `string`;
  `ok`: `boolean`;
  `persist`: `boolean`;
  `url`: `string`;
  `value`: `unknown`;
  `world`: `string`;
\}\>

#### injections

```ts
injections: () => Promise<{
  injections: object[];
}>;
```

##### Returns

`Promise`\<\{
  `injections`: `object`[];
\}\>

#### navigate

```ts
navigate: (url) => Promise<{
  ok: boolean;
  url: string;
}>;
```

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `url` | `string` |

##### Returns

`Promise`\<\{
  `ok`: `boolean`;
  `url`: `string`;
\}\>

#### open

```ts
open: (url?) => Promise<{
  ok: boolean;
  url: string;
}>;
```

A URL opens in a new tab; no URL shows the browser (its last-active tab, or a new one).

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `url?` | `string` |

##### Returns

`Promise`\<\{
  `ok`: `boolean`;
  `url`: `string`;
\}\>

#### press

```ts
press: (key) => Promise<{
  key: string;
  ok: boolean;
}>;
```

"Return", "Tab", "cmd+a", …

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `key` | `string` |

##### Returns

`Promise`\<\{
  `key`: `string`;
  `ok`: `boolean`;
\}\>

#### read

```ts
read: (maxChars?) => Promise<{
  text: string;
  title: string;
  url: string;
}>;
```

The page's visible text (`maxChars`: default 20000, at most 100000).

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `maxChars?` | `number` |

##### Returns

`Promise`\<\{
  `text`: `string`;
  `title`: `string`;
  `url`: `string`;
\}\>

#### reload

```ts
reload: () => Promise<{
  ok: boolean;
  url: string;
}>;
```

##### Returns

`Promise`\<\{
  `ok`: `boolean`;
  `url`: `string`;
\}\>

#### screenshot

```ts
screenshot: () => Promise<{
  height: number;
  path: string;
  width: number;
}>;
```

A JPEG of the page, written to a temporary file — its path.

##### Returns

`Promise`\<\{
  `height`: `number`;
  `path`: `string`;
  `width`: `number`;
\}\>

#### scroll

```ts
scroll: (opts?) => Promise<{
  scrolledTo?: string;
  scrollY?: number;
}>;
```

Scroll an element into view (`ref`), or the page by `dy` pixels (default 600).

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `opts?` | \{ `dy?`: `number`; `ref?`: `string`; \} |
| `opts.dy?` | `number` |
| `opts.ref?` | `string` |

##### Returns

`Promise`\<\{
  `scrolledTo?`: `string`;
  `scrollY?`: `number`;
\}\>

#### snapshot

```ts
snapshot: (maxNodes?) => Promise<{
  elements: string[];
  title: string;
  truncated: boolean;
  url: string;
}>;
```

One line per actionable element (`ref_3 button "Sign in"`) — the refs every other call
 targets. `truncated` when the page had more than `maxNodes`.

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `maxNodes?` | `number` |

##### Returns

`Promise`\<\{
  `elements`: `string`[];
  `title`: `string`;
  `truncated`: `boolean`;
  `url`: `string`;
\}\>

#### status

```ts
status: () => Promise<{
  host?: "pane" | "tabs";
  open: boolean;
  shell?: string;
  tabs: object[];
}>;
```

Whether the browser has tabs open, and which.

##### Returns

`Promise`\<\{
  `host?`: `"pane"` \| `"tabs"`;
  `open`: `boolean`;
  `shell?`: `string`;
  `tabs`: `object`[];
\}\>

#### tabs

```ts
tabs: object;
```

##### tabs.activate

```ts
activate: (index) => Promise<{
  active: number;
}>;
```

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `index` | `number` |

###### Returns

`Promise`\<\{
  `active`: `number`;
\}\>

##### tabs.close

```ts
close: (index) => Promise<{
  count: number;
}>;
```

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `index` | `number` |

###### Returns

`Promise`\<\{
  `count`: `number`;
\}\>

##### tabs.list

```ts
list: () => Promise<{
  tabs: object[];
}>;
```

###### Returns

`Promise`\<\{
  `tabs`: `object`[];
\}\>

##### tabs.new

```ts
new: (url?, opts?) => Promise<{
  count: number;
  existing?: boolean;
  id?: string;
  index: number;
}>;
```

A new tab (on `url`, if given). `opts.id` asks for that tab: when it is still open
 it is answered (`existing: true`) instead of opening a second one.

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `url?` | `string` |
| `opts?` | \{ `id?`: `string`; \} |
| `opts.id?` | `string` |

###### Returns

`Promise`\<\{
  `count`: `number`;
  `existing?`: `boolean`;
  `id?`: `string`;
  `index`: `number`;
\}\>

#### ~~toggle~~

```ts
toggle: (show?) => Promise<{
  open: boolean;
}>;
```

:::caution[Deprecated]
Use `open()`: the browser is never hidden. `toggle(true)` shows it like
 `open()`; `toggle(false)` does nothing.
:::

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `show?` | `boolean` |

##### Returns

`Promise`\<\{
  `open`: `boolean`;
\}\>

#### type

```ts
type: (text, refOrSelector?, submit?) => Promise<{
  found: boolean;
  ok: boolean;
}>;
```

Type text into the element (or the focused one); `submit` presses Enter after.

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `text` | `string` |
| `refOrSelector?` | `string` |
| `submit?` | `boolean` |

##### Returns

`Promise`\<\{
  `found`: `boolean`;
  `ok`: `boolean`;
\}\>

#### uninject

```ts
uninject: (id?) => Promise<{
  ok: boolean;
  removed: string[];
}>;
```

Remove one injection by id, or all of them. CSS goes; a script that already ran
 cannot be un-run — its effects last until the page reloads.

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `id?` | `string` |

##### Returns

`Promise`\<\{
  `ok`: `boolean`;
  `removed`: `string`[];
\}\>

#### waitFor

```ts
waitFor: (opts) => Promise<{
  error?: string;
  ok: boolean;
  waitedMs?: number;
}>;
```

Wait until `text` appears or an element (`ref`) exists — the deterministic gate after
 a click that loads something (`timeoutMs`: default 10000, at most 20000).

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `opts` | \{ `ref?`: `string`; `text?`: `string`; `timeoutMs?`: `number`; \} |
| `opts.ref?` | `string` |
| `opts.text?` | `string` |
| `opts.timeoutMs?` | `number` |

##### Returns

`Promise`\<\{
  `error?`: `string`;
  `ok`: `boolean`;
  `waitedMs?`: `number`;
\}\>

***

### command

```ts
command: object;
```

Run a terminal command, gated by a consent MODAL. Cowork
 asks the user to approve (a native modal: Allow once / Always allow
 in this workspace / Cancel), then runs `command` in the workspace
 folder through a LOGIN shell
 (PATH like a terminal, so `gcloud`/`brew` bins resolve and `gcloud auth
 login` opens the default browser itself) and resolves `{ code, stdout,
 stderr }`. The modal text is yours to set: `title` (heading) + `description`
 (one line framing the ask); the command is always shown under "Command:".
 Consent is keyed on `value` — a STABLE label, so a variable arg (e.g. a VM
 IP) won't defeat a prior "Always allow"; defaults to the command. Grants
 live in Cowork's per-workspace consent file, on this computer, NEVER in the
 workspace — every machine approves the first time. A Deny (or an unanswered prompt) rejects
 (ConsentRequired). For a long-lived interactive process use a stream instead.

#### run

```ts
run: (command, opts?) => Promise<{
  code: number;
  stderr: string;
  stdout: string;
}>;
```

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `command` | `string` |
| `opts?` | \{ `description?`: `string`; `timeoutMs?`: `number`; `title?`: `string`; `value?`: `string`; \} |
| `opts.description?` | `string` |
| `opts.timeoutMs?` | `number` |
| `opts.title?` | `string` |
| `opts.value?` | `string` |

##### Returns

`Promise`\<\{
  `code`: `number`;
  `stderr`: `string`;
  `stdout`: `string`;
\}\>

***

### consent

```ts
consent: object;
```

Consent-ONLY request — the same native modal as `command.run`, but nothing
 executes: the routine gets `{ granted, ticket? }` to attach to a
 consent-gated call (e.g. hand it to the widget for `stream.open`). `value`
 is the stable consent label ("Always allow" persists it to USER DATA);
 `command` is what the modal displays under "Command:". Deny or an
 unanswered prompt → `{ granted: false }` — never a throw. With no Cowork window
 open to ask, `reason` says so and names the `cowork consent allow` command that
 approves it instead.

#### request

```ts
request: (opts) => Promise<{
  granted: boolean;
  reason?: string;
  ticket?: string;
}>;
```

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `opts` | \{ `command?`: `string`; `description?`: `string`; `title?`: `string`; `value`: `string`; \} |
| `opts.command?` | `string` |
| `opts.description?` | `string` |
| `opts.title?` | `string` |
| `opts.value` | `string` |

##### Returns

`Promise`\<\{
  `granted`: `boolean`;
  `reason?`: `string`;
  `ticket?`: `string`;
\}\>

***

### credential

```ts
credential: object;
```

This capability's connection — the one its cowork.json `"credential"` declares: a sign-in,
 a pasted key, or either. A capability declaring none gets NotConnected saying so; an app's
 routine, NotGranted (it calls its capability's routines with ctx.routines.run). A call that
 needs it connected throws NotConnected naming where the person connects it.

#### disconnect

```ts
disconnect: () => Promise<{
  removed: string[];
  revoked: boolean;
}>;
```

Forget it, revoked at the service when it can be — for every capability that shares it.

##### Returns

`Promise`\<\{
  `removed`: `string`[];
  `revoked`: `boolean`;
\}\>

#### fetch

```ts
fetch: (url, init?) => Promise<Response>;
```

An authenticated fetch to the service. A sign-in sends its bearer — a 401 refreshes the
 token once and retries; only to the service's API hosts, https. A key sends nothing by
 itself: put its header in `init.headers`. A 429 or 5xx waits and retries `retries` times
 (0–4, default 2; 0 for a write that must never repeat); `json` is sent as the JSON body.
 Resolves with the Response whatever its status; throws NotConnected while it is not
 connected (or the service refused the saved sign-in) and BadRequest for a URL a sign-in
 may not be sent to.

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `url` | `string` \| `URL` |
| `init?` | `RequestInit` & `object` |

##### Returns

`Promise`\<`Response`\>

#### fields

```ts
fields: () => Record<string, string>;
```

A key's fields by name, e.g. `{ token }` — NotConnected naming the ones not pasted yet.

##### Returns

`Record`\<`string`, `string`\>

#### start

```ts
start: () => Promise<{
  authUrl: string;
}>;
```

Begin a sign-in: the consent URL to open in a browser. A key is pasted in Manage
 Workspace, never through a routine.

##### Returns

`Promise`\<\{
  `authUrl`: `string`;
\}\>

#### status

```ts
status: () => object;
```

Whether it is connected with everything this capability asks for, and as whom — never a
 token.

##### Returns

`object`

###### account?

```ts
account?: object;
```

###### account.email

```ts
email: string;
```

###### connected

```ts
connected: boolean;
```

#### token

```ts
token: (opts?) => Promise<string>;
```

A sign-in's access token, refreshed when needed (`{ force: true }` after the service
 answered 401); a key's first field. Prefer `fetch`.

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `opts?` | \{ `force?`: `boolean`; \} |
| `opts.force?` | `boolean` |

##### Returns

`Promise`\<`string`\>

***

### data

```ts
data: object;
```

The app's own data folder, `.cowork/data/<app name>/` (it travels with the
 workspace): names are paths inside it ("Gmail.json", "records/acme.json"). Keep user
 data here, not in the app folder, so the app stays clean and updates itself. A routine
 outside an app (`.cowork/apps/<name>/`) has no data folder: `dir` is "" and every call
 that touches a file throws (`fileName`, which only builds a name, still works).

#### dir

```ts
readonly dir: string;
```

Workspace-relative: `.cowork/data/<app>`.

#### fileName

```ts
fileName: (title, fallback) => string;
```

A title as a safe file name (≤ 60 characters), or `fallback`.

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `title` | `unknown` |
| `fallback` | `string` |

##### Returns

`string`

#### list

```ts
list: (subdir?) => string[];
```

The files in the folder or a subfolder, sorted (dot files left out).

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `subdir?` | `string` |

##### Returns

`string`[]

#### path

```ts
path: (name) => string;
```

A name's workspace-relative path — what `cowork.openFile` and fileRouting take.

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `name` | `string` |

##### Returns

`string`

#### read

```ts
read: <T>(name, fallback?) => T;
```

A JSON file's value; `fallback` when it is missing or not JSON.

##### Type Parameters

| Type Parameter | Default type |
| ------ | ------ |
| `T` | `unknown` |

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `name` | `string` |
| `fallback?` | `T` |

##### Returns

`T`

#### remove

```ts
remove: (name) => boolean;
```

Delete a file; false when there was none.

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `name` | `string` |

##### Returns

`boolean`

#### write

```ts
write: (name, value) => string;
```

Write a value as JSON (atomically) → its workspace-relative path.

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `name` | `string` |
| `value` | `unknown` |

##### Returns

`string`

***

### db

```ts
db: (path) => object;
```

Open a SQLite database file in the workspace (`path` workspace-relative; the file and
 its folder are created when missing) — directly in this routine's process, in WAL mode
 with a busy timeout, so it is safe beside Cowork's own readers. Handles close when the
 run ends.

#### Parameters

| Parameter | Type |
| ------ | ------ |
| `path` | `string` |

#### Returns

##### exec

```ts
exec: (sql, params?) => CoworkDbExecResult;
```

One write or DDL statement — a string holding a second statement throws.

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `sql` | `string` |
| `params?` | `unknown`[] |

###### Returns

[`CoworkDbExecResult`](/docs/reference/sdk/interfaces/coworkdbexecresult.md)

##### query

```ts
query: (sql, params?) => CoworkDbQueryResult;
```

One statement's rows. Meant for reads: it does not refuse a write, but `exec` is the
 call for writes.

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `sql` | `string` |
| `params?` | `unknown`[] |

###### Returns

[`CoworkDbQueryResult`](/docs/reference/sdk/interfaces/coworkdbqueryresult.md)

##### transaction

```ts
transaction: <T>(fn) => T;
```

Runs `fn` atomically: a throw rolls everything back. SYNC-ONLY — an async callback
 (or one returning a promise) throws, as an awaited gap would hold the transaction
 open across unrelated work.

###### Type Parameters

| Type Parameter |
| ------ |
| `T` |

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `fn` | () => `T` |

###### Returns

`T`

***

### error

```ts
error: (name, message) => Error;
```

An Error carrying `name`, to throw: `throw ctx.error("NotConnected", "Paste your token in
 the sidebar.")` — the widget's promise rejects with `e.name === "NotConnected"` instead of a
 message to match. `ctx.credential` throws `NotConnected` itself.

#### Parameters

| Parameter | Type |
| ------ | ------ |
| `name` | `string` |
| `message` | `string` |

#### Returns

`Error`

***

### identity

```ts
identity: CoworkIdentity;
```

Who this run is for — the signed-in user and their organization, as Cowork saw them
 when the run started (frozen). Use it to act on WHO (e.g. stamp an approver). Nobody
 signed in: `user` and `organization` null.

***

### journal

```ts
journal: object;
```

Leave a learning / error note for a skill in the skill journal
 (`source` defaults to "routine:<file>").

#### add

```ts
add: (entry) => CoworkJournalEntry;
```

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `entry` | \{ `kind?`: `"learning"` \| `"error"` \| `"note"`; `skill`: `string`; `source?`: `string`; `text`: `string`; \} |
| `entry.kind?` | `"learning"` \| `"error"` \| `"note"` |
| `entry.skill` | `string` |
| `entry.source?` | `string` |
| `entry.text` | `string` |

##### Returns

[`CoworkJournalEntry`](/docs/reference/sdk/interfaces/coworkjournalentry.md)

***

### log

```ts
log: (...parts) => void;
```

A line in the run's log — strings as written, anything else as JSON; `console.log`
 lands there too. It streams while the run is live, and a run that failed or changed
 something keeps its last lines in its record.

#### Parameters

| Parameter | Type |
| ------ | ------ |
| ...`parts` | `unknown`[] |

#### Returns

`void`

***

### notify

```ts
notify: (n) => Promise<void>;
```

An OS notification from this routine's app — what `cowork.notify` does in a
 widget, and the way to notify while no pane is open (a poll that found new
 mail): `await ctx.notify({ title: "New email", body: from, tag: "inbox" })`.
 The desktop app shows it even with its window closed; a browser tab on the
 workspace is best effort; only the ACTIVE workspace's show, and nobody showing
 it within a minute drops it (the next poll repeats it). Muted or past 6 a
 minute: dropped, still resolves. A capability's notifications go to the one
 app that uses it (a click opens that app; either one's switch mutes them). A
 routine outside an app (`.cowork/apps/<name>/`) gets BadRequest. One raised by a
 run that a notification started (or a routine it called) shows, but starts no routine.

#### Parameters

| Parameter | Type |
| ------ | ------ |
| `n` | \{ `body?`: `string`; `tag?`: `string`; `title`: `string`; `urgent?`: `boolean`; \} |
| `n.body?` | `string` |
| `n.tag?` | `string` |
| `n.title` | `string` |
| `n.urgent?` | `boolean` |

#### Returns

`Promise`\<`void`\>

***

### queue

```ts
queue: (name) => object;
```

A task queue in this workspace (.cowork/local/queues.db), direct; the same
 tasks as `cowork queue …` and the Tasks view. `send` creates it; `receive` takes the
 oldest task for `as` or for anyone (null = none); `ack`/`nack` need its `receipt` —
 `ack`'s result and files are the holder's entry (a `{path}` only from inside the
 workspace), `review` asks the owner, `to` hands it on. Files: `{path}`
 (workspace-relative or absolute, copied), `{name, text}` or `{name, base64}`.
 `list`'s `q`: every word, in what the Tasks view shows of a task.

#### Parameters

| Parameter | Type |
| ------ | ------ |
| `name` | `string` |

#### Returns

`object`

##### ack

```ts
ack: (id, receipt, opts?) => CoworkQueueTask;
```

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `id` | `number` |
| `receipt` | `string` |
| `opts?` | \{ `files?`: [`CoworkQueueFileInput`](/docs/reference/sdk/type-aliases/coworkqueuefileinput.md)[]; `result?`: `string`; `review?`: `boolean`; `to?`: `string`; \} |
| `opts.files?` | [`CoworkQueueFileInput`](/docs/reference/sdk/type-aliases/coworkqueuefileinput.md)[] |
| `opts.result?` | `string` |
| `opts.review?` | `boolean` |
| `opts.to?` | `string` |

###### Returns

[`CoworkQueueTask`](/docs/reference/sdk/interfaces/coworkqueuetask.md)

##### approve

```ts
approve: (id) => CoworkQueueTask;
```

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `id` | `number` |

###### Returns

[`CoworkQueueTask`](/docs/reference/sdk/interfaces/coworkqueuetask.md)

##### counts

```ts
counts: () => Record<CoworkTaskView, number>;
```

###### Returns

`Record`\<[`CoworkTaskView`](/docs/reference/sdk/type-aliases/coworktaskview.md), `number`\>

##### list

```ts
list: (opts?) => CoworkQueueTask[];
```

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `opts?` | \{ `agent?`: `string`; `before?`: `number`; `limit?`: `number`; `q?`: `string`; `view?`: [`CoworkTaskView`](/docs/reference/sdk/type-aliases/coworktaskview.md); \} |
| `opts.agent?` | `string` |
| `opts.before?` | `number` |
| `opts.limit?` | `number` |
| `opts.q?` | `string` |
| `opts.view?` | [`CoworkTaskView`](/docs/reference/sdk/type-aliases/coworktaskview.md) |

###### Returns

[`CoworkQueueTask`](/docs/reference/sdk/interfaces/coworkqueuetask.md)[]

##### nack

```ts
nack: (id, receipt, opts?) => CoworkQueueTask;
```

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `id` | `number` |
| `receipt` | `string` |
| `opts?` | \{ `delayS?`: `number`; `error?`: `string`; \} |
| `opts.delayS?` | `number` |
| `opts.error?` | `string` |

###### Returns

[`CoworkQueueTask`](/docs/reference/sdk/interfaces/coworkqueuetask.md)

##### peek

```ts
peek: (id) => 
  | CoworkQueueTask
  | null;
```

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `id` | `number` |

###### Returns

  \| [`CoworkQueueTask`](/docs/reference/sdk/interfaces/coworkqueuetask.md)
  \| `null`

##### receive

```ts
receive: (opts?) => 
  | CoworkQueueTask & object
  | null;
```

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `opts?` | \{ `as?`: `string`; `leaseS?`: `number`; `mine?`: `boolean`; \} |
| `opts.as?` | `string` |
| `opts.leaseS?` | `number` |
| `opts.mine?` | `boolean` |

###### Returns

  \| [`CoworkQueueTask`](/docs/reference/sdk/interfaces/coworkqueuetask.md) & `object`
  \| `null`

##### reject

```ts
reject: (id, comment) => CoworkQueueTask;
```

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `id` | `number` |
| `comment` | `string` |

###### Returns

[`CoworkQueueTask`](/docs/reference/sdk/interfaces/coworkqueuetask.md)

##### reply

```ts
reply: (id, body, opts?) => CoworkQueueTask;
```

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `id` | `number` |
| `body` | `string` |
| `opts?` | \{ `as?`: `string`; `files?`: [`CoworkQueueFileInput`](/docs/reference/sdk/type-aliases/coworkqueuefileinput.md)[]; `ref?`: `string`; `to?`: `string` \| `null`; \} |
| `opts.as?` | `string` |
| `opts.files?` | [`CoworkQueueFileInput`](/docs/reference/sdk/type-aliases/coworkqueuefileinput.md)[] |
| `opts.ref?` | `string` |
| `opts.to?` | `string` \| `null` |

###### Returns

[`CoworkQueueTask`](/docs/reference/sdk/interfaces/coworkqueuetask.md)

##### retry

```ts
retry: (id) => CoworkQueueTask;
```

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `id` | `number` |

###### Returns

[`CoworkQueueTask`](/docs/reference/sdk/interfaces/coworkqueuetask.md)

##### send

```ts
send: (body, opts?) => CoworkQueueTask;
```

###### Parameters

| Parameter | Type |
| ------ | ------ |
| `body` | `string` |
| `opts?` | \{ `as?`: `string`; `delayS?`: `number`; `files?`: [`CoworkQueueFileInput`](/docs/reference/sdk/type-aliases/coworkqueuefileinput.md)[]; `meta?`: `Record`\<`string`, `unknown`\>; `ref?`: `string`; `review?`: `boolean`; `subject?`: `string`; `to?`: `string`; \} |
| `opts.as?` | `string` |
| `opts.delayS?` | `number` |
| `opts.files?` | [`CoworkQueueFileInput`](/docs/reference/sdk/type-aliases/coworkqueuefileinput.md)[] |
| `opts.meta?` | `Record`\<`string`, `unknown`\> |
| `opts.ref?` | `string` |
| `opts.review?` | `boolean` |
| `opts.subject?` | `string` |
| `opts.to?` | `string` |

###### Returns

[`CoworkQueueTask`](/docs/reference/sdk/interfaces/coworkqueuetask.md)

***

### routines

```ts
routines: object;
```

Run another routine of this workspace and await its result — an ordinary run (off
 switch, a concurrency slot, its own audit record naming this run in
 `caller.chain`). An id your app declares is your app's own routine.
 · calls nest two deep: a → b → c runs, c calling another throws RoutineDepth;
   a routine already in the chain throws RoutineCycle;
 · the nested run never outlives this one (`timeoutMs` is capped by what is left);
 · resolves with its result; a routine that threw rejects with ITS `e.name` (and
   `e.runId`); a refusal rejects as NotFound, RoutineDisabled or
   TooManyRoutines — thrown at once, never waited out.

#### run

```ts
run: (id, args?, opts?) => Promise<unknown>;
```

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `id` | `string` |
| `args?` | `unknown` |
| `opts?` | \{ `timeoutMs?`: `number`; \} |
| `opts.timeoutMs?` | `number` |

##### Returns

`Promise`\<`unknown`\>

***

### secrets

```ts
secrets: object;
```

The signed-in Cowork account's secrets, kept encrypted on this computer (the key in the
 OS keychain) — one store for every workspace, never synced: get() returns undefined for an
 unset name; list() returns names only (never values).

 Reserved namespace: names under "cowork." are SYSTEM-managed —
 provisioned by signing in, not writable by apps/routines/the CLI.
 "cowork.openrouter" is a preprovisioned OpenRouter API key, present ONLY
 when signed in — base URL https://openrouter.ai/api/v1 (OpenAI-compatible),
 enough to call OpenRouter's free ":free" models out of the box. Read it
 like any secret: ctx.secrets.get("cowork.openrouter").

 A capability's routines touch only its own family (`<name>.*` — what they cache, like
 a user id) plus reading "cowork.openrouter"; the service it connects to is
 `ctx.credential`. Anything else — and every secret from an APP's routine — throws
 NotGranted (an app calls its capability's routines with ctx.routines.run). A package
 that declares neither `kind` nor `uses` predates capabilities and keeps unrestricted
 access until it declares one.

#### get

```ts
get: (name) => string | undefined;
```

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `name` | `string` |

##### Returns

`string` \| `undefined`

#### list

```ts
list: () => string[];
```

The names this routine may read (never values).

##### Returns

`string`[]

#### set

```ts
set: (name, value) => void;
```

Store a secret from inside a routine — a value it caches, a token it minted. THROWS on a
 reserved "cowork." name or an invalid name (grammar: /^[A-Za-z_][A-Za-z0-9_.-]*$/ — no
 colons). To forget the connection, ctx.credential.disconnect().

##### Parameters

| Parameter | Type |
| ------ | ------ |
| `name` | `string` |
| `value` | `string` |

##### Returns

`void`

***

### unchanged

```ts
unchanged: () => void;
```

This run changed nothing — a read, a poll that found nothing. It stays in the
 local audit but is not an execution: never reported to a team server, left out of the run
 lists (`cowork routine runs --unchanged` shows it). A run that then throws counts anyway.

#### Returns

`void`

***

### workspaceRoot

```ts
workspaceRoot: string;
```

The workspace folder's path. A routine does not run with it as its working directory:
 resolve workspace files against it.
