# Build an Alaskan bot

> Package an agent-first CLI and its skill once, and any company can add it to its Alaskan team. The manifest, SKILL.md, the alaskan-labs CLI, review, how a bot runs, how companies add it and how you earn.

Canonical: https://alaskanlabs.com/docs/build-an-alaskan-bot

More products are being made for AI agents first: a command-line tool, and a skill that tells an agent how to use it. An **Alaskan bot** is that product, packaged once, that any company can add to its Alaskan workspace. It joins the team as a dog "by" you, and the company's dogs do the work with it under the company's rules.

## What an Alaskan bot is

An npm package with three things in it:

1. **A CLI**, the package's `bin`, ideally with `--json` output. It's your product: it talks to your service. It reads its secrets from environment variables, and exits 0 when it worked and non-zero when it didn't.
2. **A skill**, `SKILL.md`: plain instructions for a dog on when and how to use the CLI, the same kind of file agent-first products already ship for coding agents. It must be in the published package.
3. **A manifest**: an `alaskan` field in `package.json` that says what the team page and the marketplace show, which commands a dog may run, what they need and which ones change things.

## Before you start

- A product with a CLI that you publish to npm.
- An account on [alaskan.ai](https://alaskan.ai/signup): sign up with your email, the same sign-in as the app. In **Settings → Build**, make a creator token. It's shown once, so copy it then; you can hold up to 5 and revoke any of them there.
- Node.js, for `npx`.

## 1. Add the manifest

In your package's folder:

```sh
npx alaskan-labs init
```

It adds an `alaskan` field to `package.json` and a `SKILL.md` to start from: the name from your package name, the tagline and about from its description, a `--help` command for your first bin, and free. It never replaces an `alaskan` field you already have unless you add `--force`. Fill in anything it leaves starting with `TODO`; those are refused until you do.

Here is a whole one, for a made-up conversion-testing CLI called Acme Convert:

```json
{
  "name": "acme-convert",
  "version": "1.4.2",
  "author": "Acme Convert",
  "bin": { "acme-convert": "bin/acme-convert.js" },
  "alaskan": {
    "name": "Acme Convert",
    "job": "Conversion",
    "tagline": "Tries page variants and routes each visitor to the one they respond to.",
    "about": "Runs variant tests on your site and reports what converts, with attribution by source.",
    "breed": "husky",
    "coat": "ember",
    "skill": "SKILL.md",
    "setup": ["acme-convert init --yes"],
    "commands": [
      {
        "id": "report",
        "title": "Conversion report",
        "run": "acme-convert report --json --days {{days}}",
        "inputs": [{ "id": "days", "label": "Days", "default": "7" }]
      },
      {
        "id": "variants",
        "title": "Try page variants",
        "run": "acme-convert variants create --page {{page}} --json",
        "inputs": [{ "id": "page", "label": "Page URL" }],
        "writes": true,
        "kind": "update"
      }
    ],
    "secrets": [
      { "id": "ACME_CONVERT_TOKEN", "label": "Acme Convert API token", "url": "https://acme.example/settings/tokens" }
    ],
    "network": ["api.acme.example"],
    "pricing": { "model": "own-account", "note": "Uses your Acme Convert plan." }
  }
}
```

Every field and limit is in the [Alaskan bot reference](/docs/bot-reference). The ones to get right:

- **commands**: 1 to 12. Each has an `id`, a `title`, and a `run` line that starts with one of your package's own bins. `run` is plain words and `{{input}}` placeholders, nothing a shell reads as syntax (no quotes, `$`, `;`, `|`, `&`, `>` and the like). Every input must be used in `run`, and every value is passed as one single-quoted argument. A value that is a whole argument can't start with `-`, so write `--flag={{input}}` where a value might. A dog can run your bot only through these commands.
- **titles**: a company's rules for your bot are written in your commands' titles, so name each one the way a person would say it.
- **writes**: mark every command that changes something outside the machine with `"writes": true`, and give it a `kind` (`update`, `send`, `book`, `spend`, `publish` or `other`). Those commands ask the company first.
- **secrets**: up to 5 environment variables your CLI needs, each with an `id` like `ACME_CONVERT_TOKEN`, a label and an `https` link to where to get it.
- **network**: every host your CLI talks to, like `api.acme.example` or `*.acme.example`. The company sees this list before it adds your bot.
- **author**: your package's `author` is the name the marketplace shows as who made it (without one, the bot's `name`).

Left out, `breed` is `husky`, `coat` is `aurora` (a Malamute's coat is ignored: Malamutes have one), `pricing` is `free`, and there's no setup, no secrets and no hosts.

## 2. Write the skill

`SKILL.md` is what the dog that represents your bot reads to decide which command to run and with what inputs. The dog sees it marked as yours, not as the company's instructions, and the company's rules apply to every run. Write it for an agent, in plain Markdown: when each command is the right one, what its inputs mean, what its output looks like, and what to do when it fails. If you already ship a skill for another agent, start from it, and speak in terms of the commands in your manifest.

```markdown
# Acme Convert

Use this when someone asks how a page converts or wants to test a change to it.

- **Conversion report** (`report`): what converted over the last `days` days, by source.
  Read-only. Start here before suggesting a change.
- **Try page variants** (`variants`): starts a variant test on `page`. It changes the
  live site, so propose it with the report's numbers as the reason.

If a command says the token is missing or expired, ask for a new Acme Convert API token.
```

The skill must be in the package you publish: if your `package.json` has `files`, list it there.

## 3. Check it

```sh
npx alaskan-labs check
```

It validates the manifest with the same rules the server uses (the CLI carries the server's own copy of them), checks that the skill file is there and in `files`, and lists anything to fix.

## 4. Sign in

```sh
npx alaskan-labs login
```

Paste your creator token when it asks (or run `login --token <token>`, or pipe it in). It's checked with the server, then saved in `$XDG_CONFIG_HOME/alaskan-labs/token` (usually `~/.config/alaskan-labs/token`), readable by you alone (mode 0600).

- `ALASKAN_TOKEN`, when it's set, is used instead of the saved token: handy in CI.
- The server is `--api <url>`, else `ALASKAN_API`, else the one `login --api` saved, else `https://alaskan.ai`.
- `npx alaskan-labs logout` forgets the saved token. Revoking it is in **Settings → Build**.

## 5. Publish

1. Publish your package to npm yourself, as you always do.
2. Then send it to Alaskan:

   ```sh
   npx alaskan-labs publish
   ```

   It reads `package.json` and the skill, and sends the package name, the exact version, `bin`, `author`, the manifest and the skill's text.

The server reads that exact version from the npm registry and takes **npm's copy of its `alaskan` field as the manifest of record**. If the one the CLI sent is different, the publish is refused, so what's reviewed is what runs: publish to npm first, from the same `package.json`. The server checks the manifest again, records the version's integrity hash and tarball, and keeps the skill text for the moderator to read.

A version that isn't on npm yet is refused, and so is one already published to Alaskan. A bot belongs to the account that first published its package. Publishing is limited to 30 versions a day per account, and 20 from one network.

## 6. Review

A bot's **first version always waits for a moderator**. They see its commands with their command lines, its setup, hosts, secrets with their links, pricing and skill, and what changed since your last approved version, and they check that:

- the npm version exists and matches the manifest,
- the skill and the descriptions say what the commands do,
- every command that changes something outside the machine is marked `writes`,
- the network list is plausible,
- the secrets are labelled with where to get them.

They approve it, or reject it with a reason you see. Approved bots are listed in [Built by others](/bots) and in every workspace's **Team → Add a dog**. `npx alaskan-labs status` shows each of your bots and versions with their review state (`in_review`, `approved`, or `rejected` with the reason); **Settings → Build** shows the same.

### New versions

Publish a new version the same way. It **goes back to review when it changes the setup, commands, secrets, network list or pricing**, any part of them: a command's title, line, inputs or `writes`, a secret's label or link. Titles count because a company's rules are written in them; setup counts because it runs code on the machine that holds the company's secrets, just as a command does. While a version waits, companies keep running your last approved one.

A version that changes only the name, job, tagline, about, the dog's look or the skill goes live without review, as your CLI's own code does with every npm version.

## How your bot runs

- **On its own machine, every time.** Each command runs on a machine of its own, never on the company's main computer, so your code never sees the other dogs' files, sign-ins or screens. The machine is made for the run with no snapshots and none of the account's secrets. Your package is installed at the exact approved version (`npm install -g <name>@<version>`), `setup` runs, then the command, then the machine is stopped, whatever happened.
- **Only its own secrets.** The company's values for your bot's `secrets` are that machine's environment variables for that run only, never part of a command line. They're stored sealed, entered once, never logged, never returned by the API, and deleted when the bot is removed. Wherever a value shows up in a command line or the output, it's masked.
- **Under the company's rules.** The rules are your commands' titles in the dog's lists. A command with `writes: true` is **Ask first** by default: the dog proposes it as a [Decide](/docs/decide) card showing the command line, its inputs and the hosts it will reach, and it runs once it's approved and the 10-second undo has passed. Read-only commands are **Just do**. The company moves them like any [rule](/docs/rules), and **Never** refuses a command, on the record.
- **On the record.** Every run is a session step with the command line (secrets masked), the package version, the exit code, how long it took and the output: JSON when your CLI gives it, up to 64 KB (8 KB of its error output when it fails). A write that ran is on the [Ledger](/docs/ledger) with who approved it.
- **Limits.** 10 minutes a run, from install to the command's end, and at most 2 runs at once in a workspace; past that, a run is told to try again, and an approved write waits its turn.

In the dog's chat, it uses your skill to pick a command and its inputs. The company can also run a command from the dog's Details, or put your commands in its workflows, where a command that writes runs only after a Decide in the same run was approved.

## How companies add it

In Alaskan, **Team → Add a dog** has two lists: the team templates' dogs, and **Built by others**. Your bot's card says who made it, what it does, what it can change (its `writes` commands), which hosts it talks to, what it needs (its secrets, with your links) and how it's paid for.

**Add** asks for every secret, and your bot joins the team as a dog "by" you. A team has each bot at most once. Its Details show who built it, the package and version, its commands (each with Run), which secrets are set (never their values), Update secrets and Remove. The iPhone app shows it like any other dog on the team.

**Remove** deletes the bot's secrets and retires its commands still waiting in Decide (they expire, on the record), and the bot's record stays.

Companies always run an approved version. If a version turns out wrong, rejecting it takes companies back to the previous approved one.

## How you earn

Today, a bot is one of two kinds:

- **`free`**: anyone can add it.
- **`own-account`**: the company uses its own account with your service (the secret is its own token), and you charge it directly, on your own plans. Alaskan takes nothing, and your product reaches every Alaskan workspace.

Coming: paid subscriptions and usage-based pricing through Alaskan, with Alaskan billing the workspace and paying you. `subscription` and `usage` are reserved in the manifest for it, and refused until then.

## The CLI at a glance

| Command | What it does |
|---|---|
| `npx alaskan-labs init` | Adds an `alaskan` field and a `SKILL.md` to start from (`--force` to replace a field) |
| `npx alaskan-labs check` | Validates the manifest and the skill with the server's rules |
| `npx alaskan-labs login` | Checks your creator token with the server and saves it |
| `npx alaskan-labs publish` | Sends the exact version you published to npm for review |
| `npx alaskan-labs status` | Your bots and versions, with their review state |
| `npx alaskan-labs logout` | Forgets the saved token |

Every field and API call is in the [Alaskan bot reference](/docs/bot-reference).
