# Extensions

An extension is a typed shell command that you declare. The agent's shell finds it by name, like a program, and its handler runs in your own process, outside the computer. Agents use your application through the shell they already work in, and your keys stay in your code.

## Declare a command

You declare an extension with types and doc comments. `#[derive(ext::Command)]` builds its arguments and subcommands, and `#[ext::extension]` joins the declaration to its handler:

```rust
#[derive(ext::Command)]
enum Orders {
    /// Show order details
    Show { id: i64 },
    /// Track a shipment
    Track { id: i64 },
}

/// Read orders and shipment tracking
#[ext::extension(timeout = "30s")]
async fn orders(cx: Cx, State(db): State<Db>, cmd: Orders) -> Result<Output, Fail> {
    let user = cx.label("user").ok_or(Fail::new(77, "orders: no user"))?;
    let (Orders::Show { id } | Orders::Track { id }) = cmd;
    let order = db.order(id).await?;
    if order.owner != user {
        return Err(Fail::new(77, "orders: access denied"));
    }
    Ok(Output::line(match cmd {
        Orders::Show { .. } => order.details(),
        Orders::Track { .. } => order.tracking(),
    }))
}
```

The first line of each doc comment is the summary that `--help` shows. Here `db.order`, `details` and `tracking` are your application's own code.

| Part        | What you can declare                                                       |
| ----------- | -------------------------------------------------------------------------- |
| Subcommands | One level, each with its own help and arguments.                           |
| Arguments   | Flags, options and positional arguments, required or optional, repeatable. |
| Types       | `String`, `Integer`, `Number`, `Boolean`, `Date` or `Json`, with choices.  |
| Environment | The names of guest variables the handler receives.                         |
| Timeout     | Up to one hour.                                                            |

Every extension can read standard input and write standard output and standard error of any size, as a program can.

## Who a call is for

Each computer carries labels that identify the person its agent acts for. Elios signs those labels into every call, and nothing on the computer can change them. Read them with `cx.label`.

The shell checks every call against the declaration before it leaves the computer, so a wrong type or a missing argument never reaches your code. A valid call can still name something the person may not see, so check every argument against the labels in your handler.

## Serve it

A server extension is stored in your organization. Its calls reach your endpoint as webhooks, and `handle` routes each one to its handler:

```rust
client.extensions().create(orders()).await?;

let handler = client.extensions().handle([orders()]).with_state(db.clone());
let app = axum::Router::new().route_service("/elios/extensions", handler.service());
```

A client extension is served from your process over a connection, to one command or to every command on a computer while the connection lasts:

```rust
client.computer(id).exec("orders track 1042").serve([orders()]).output().await?;

let connection = client.computer(id).extensions().connect([orders()]).with_state(db).await?;
```

Elios never repeats a call. Key side effects on `cx.invocation()`, the call's own id.

## Turn it off

`update` sets `enabled` on a server extension. While it is off, the shell does not find it, so every call exits with 127. A computer's `server_exts` policy decides which server extensions it can see; a policy only filters, it never grants.

## Exit codes

| Code  | Meaning                                               |
| ----- | ----------------------------------------------------- |
| `2`   | The call does not match the declaration.              |
| `69`  | The handler failed, refused or lost its connection.   |
| `75`  | Your endpoint or Elios is busy or unreachable; retry. |
| `124` | The call reached its deadline.                        |
| `127` | There is no such command, or the extension is off.    |
| `130` | The call was cancelled.                               |
| `141` | The command reading the output closed its end.        |

## Limits

An organization can have 256 server extensions, and each declaration can be up to 16 KiB.

## Next steps

* [Commands](/computer/concepts/commands): run shell commands on a computer
* [Templates](/computer/concepts/templates): prepare computers before an agent starts
