Docs

Quickstart

This quickstart deploys a first stack, the code and cloud resources you describe in alien.ts, to an environment you don't host. You can have a coding agent add Alien to your own repository, or build a small example by hand.

With your coding agent

Paste this into your coding agent, from your repository:

Prompt
Help me add Alien (https://alien.dev/docs) to this product so it meets an enterprise customer's data requirements. 1. Install the Alien skills: npx skills add alienplatform/skills 2. Use the alien-architecture skill. Inspect this repository, including its services, Dockerfiles, Helm charts or Docker Compose files, and Terraform. Ask me what the customer requires, then propose the smallest option that meets it: customer-managed keys, local AI models, or a deployment in their cloud or on their servers. 3. Wait for my choice before editing. 4. Use the alien-integration skill to build it and verify one request end to end. Treat the installed packages and `alien --help` as the API source of truth. Don't publish a release or create a customer deployment without asking.

The agent installs the Alien skills, reads your code, Dockerfiles, and Helm charts, and proposes what runs in customer environments. It stops for your choice before editing, and asks before it publishes a release or creates a customer deployment. See Build with an AI agent.

By hand

This path builds a worker, a serverless function, that reads and writes files in the customer's own storage. Your backend calls it with commands: named functions in your code that run inside the customer's environment.

Architecture diagram. Customer's cloud (worker, files) connects outbound to the Your cloud (Your backend, alien CLI), via commands, outbound only.

The worker and its storage run in the customer's account. Commands reach it without inbound networking.

You run it locally first, with no cloud account, then deploy the same code to an AWS, Google Cloud, or Azure account you control.

Prerequisites

  • macOS, Linux, or Windows
  • Node.js 20 or later
  • Bun (Alien builds TypeScript with it)
  • Docker, running (alien dev uses it to run your code locally)

Install the CLI

curl -fsSL https://alien.dev/install | sh

Check the install with alien --version.

The install script puts alien in /usr/local/bin if that directory is writable, otherwise in ~/.local/bin, and adds it to your shell profile. If your shell can't find alien, open a new terminal or run the export PATH=... line the script prints.

Create the project

alien init remote-worker-ts my-worker
cd my-worker

alien.ts describes what each customer gets:

alien.ts
import * as alien from "@alienplatform/core"

// Private file storage in each customer's environment.
// S3 on AWS, Cloud Storage on Google Cloud, Blob Storage on Azure.
const files = new alien.Storage("files").build()

// Your code. Lambda on AWS, Cloud Run on Google Cloud,
// Container Apps on Azure.
const worker = new alien.Worker("worker")
  .code({ type: "source", src: "./", toolchain: { type: "typescript" } })
  .commandsEnabled(true)
  .link(files)
  .permissions("execution")
  .build()

export default new alien.Stack("remote-worker")
  .platforms(["aws", "gcp", "azure"])
  .add(files, "frozen")
  .add(worker, "live")
  .permissions({
    profiles: {
      execution: { "*": ["storage/data-read", "storage/data-write"] },
    },
  })
  .build()
  • .link(files) gives the worker access to the bucket at runtime. Credentials come from the environment; there is no connection string.
  • files is frozen: it's created once, at initial setup (the one-time step the customer's admin runs in their account), and Alien can't change or delete it afterwards.
  • worker is live: Alien updates it on every release. See Frozen and live resources.
  • .commandsEnabled(true) lets your backend send the worker commands.

src/index.ts is the code that runs there. It registers commands with command() and reads the customer's files with storage():

src/index.ts
import { command, storage } from "@alienplatform/sdk"
import { z } from "zod"

const tools = {
  "read-file": async ({ path }: { path: string }) => {
    const object = await storage("files").get(path)
    return { content: new TextDecoder().decode(object.data) }
  },
  "write-file": async ({ path, content }: { path: string; content: string }) => {
    await storage("files").put(path, new TextEncoder().encode(content))
    return { written: true, path }
  },
}

command(
  "execute-tool",
  z.object({ tool: z.enum(["read-file", "write-file"]), params: z.any() }),
  async ({ tool, params }) => tools[tool](params),
)

The template's version also has list-tools and where-am-i commands.

Run it locally

alien dev

alien dev starts a local manager (the Alien server that stores releases and rolls them out), builds and releases the worker, and deploys it. Storage is a local directory. Keep it running.

Building... done
Starting... done
default: Running
  execution-sa: running (private)
  files: local filesystem
  secrets: running (private)
  worker: running (private)

A deployment is one running copy of your stack. default stands in for your first customer.

Deployments belong to a deployment group, usually one per customer. The local group is local-dev, so the full name is local-dev/default.

Call the worker

In a second terminal, from my-worker, write a file into the customer's storage and read it back:

alien dev commands invoke \
  --deployment local-dev/default \
  --command execute-tool \
  --params '{"tool": "write-file", "params": {"path": "hello.txt", "content": "Hello!"}}'
{ "path": "hello.txt", "written": true }
alien dev commands invoke \
  --deployment local-dev/default \
  --command execute-tool \
  --params '{"tool": "read-file", "params": {"path": "hello.txt"}}'
{ "content": "Hello!" }

Add a second customer

alien dev deploy --name customer-2 --platform local

customer-2 gets its own worker and its own storage. Reading hello.txt from local-dev/customer-2 fails with Storage object not found: the file only exists in default's storage. In production, the two would be separate cloud accounts.

Change the code

Add a command to the end of src/index.ts:

src/index.ts
command("hello", async () => ({ message: "Hello from the new release" }))

Stop alien dev with Ctrl+C and start it again. It rebuilds the worker, creates a new local release, and updates both deployments:

alien dev commands invoke --deployment local-dev/customer-2 --command hello
{ "message": "Hello from the new release" }

Deploy to a cloud account

Run the same worker in a real cloud account. You play two roles: the developer who releases, and the customer's admin who runs initial setup once.

alien login
alien link

alien login opens your browser to sign in to alien.dev. A new account has no workspace yet: create one with alien workspaces create <name>. The name is permanent and appears in dashboard URLs (4 to 100 lowercase letters, numbers, and hyphens).

alien link creates a project for this directory, or links it to an existing one, and saves the link in .alien/project.json.

Release

alien release

This builds the worker for each platform the stack declares and uploads the images. It also moves the production channel, the pointer deployments follow by default, to the new release. Nothing runs in a customer environment yet.

Onboard a customer

alien onboard customer-1

The output is a setup link, a URL the customer's admin opens to run initial setup:

Share this link with the customer's admin:
  https://alien.dev/deploy/#<token>

The link opens the deployment portal, a setup page branded with your project's name. Onboard a customer in the dashboard creates the same link. Your backend can create links through the API, for example behind a Deploy button.

Run initial setup as the customer's admin

Open the link, pick a cloud, and pick a setup method: CloudFormation, Terraform, Helm, Google login, or a CLI named after your project.

For this guide, choose CLI. Follow the portal's commands in a terminal that has credentials for your cloud account (for example AWS_PROFILE):

  1. An install command for the setup CLI. Its default name is the project name plus -ctl (my-worker-ctl), or plus ctl when the name has no hyphen. You can rename it under project Settings → Artifacts.
  2. A deployment.toml with the deployment's name, platform, and settings. Save it in the current directory.
  3. The deploy command. It passes the setup token in an environment variable named after the CLI, so the token stays out of the command line:
export MY_WORKER_CTL_DEPLOYMENT_TOKEN='<token-from-the-portal>'
my-worker-ctl deploy --config deployment.toml

Initial setup uses your credentials once, and doesn't store them. It creates the bucket and a management identity: a scoped cloud role Alien uses to manage the deployment afterwards. Alien then creates the worker with that identity.

Watch the deployment come up in the dashboard under Deployments, or from the CLI:

alien deployments ls

Call the worker in the cloud

A deployment is addressed as <group>/<name>. alien onboard customer-1 created a deployment group and a deployment both named customer-1:

alien commands invoke \
  --deployment customer-1/customer-1 \
  --command execute-tool \
  --params '{"tool": "write-file", "params": {"path": "hello.txt", "content": "Hello from the cloud"}}'

The same handler now runs in Lambda, Cloud Run, or Container Apps, and writes to a bucket in that account.

Ship an update

Change the code and release again:

alien release
alien deployments wait customer-1/customer-1 --for ready

This is ongoing management: Alien updates the deployment, and the admin doesn't run anything. The release reaches every deployment on the production channel.

In the dashboard, the release page under Releases shows each deployment's rollout state.

Clean up

Remove the deployment with the same method the admin used for initial setup:

Setup methodHow to remove it
CLISet the token variable again and run my-worker-ctl destroy --name customer-1.
CloudFormationDelete the stack. The portal shows the stack's name and region, with a link to it in the AWS console.
TerraformIn the workspace that applied the module, set TF_VAR_token to the setup token and, on AWS, TF_VAR_management_external_id to the ExternalId used at initial setup. Then run terraform destroy. If the stack defines a Key, first run the module's detach-retained-keys.sh, as its README describes. It removes the keys from Terraform state and leaves them in the account.
HelmRun helm list --all-namespaces to find the release and namespace, then helm uninstall <release> --namespace <namespace>.

Removal keeps storage buckets so no data is lost. Delete them yourself when you're done.

On Azure, the Terraform module requires the azurerm provider at version 4.75 or later, below 5.0. In a workspace locked to an older version, run terraform init -upgrade first.

The Azure module won't delete a resource group that still contains resources, such as a retained Key Vault. terraform destroy stops with an error and the group stays.

Next

  • How Alien works: initial setup, ongoing management, and how releases reach each environment.
  • Architecture design: decide which part of your product runs in each customer's environment.
  • Stacks: resources, commands, and releases in depth.

On this page