# Install

`npx starwisp init` puts Starwisp into **your own** GitHub organization and Cloudflare account, using your own sign-ins. Only your signed license key is shown to our download service. Nothing you create passes through our servers.

Requirements: Node.js 20 or newer. The installer has no dependencies.

## Commands

| Command | What it does |
|---|---|
| `npx starwisp init` | Installs. Safe to run again: finished steps are skipped. |
| `npx starwisp doctor` | Re-checks prerequisites and the install. Exit code 1 if anything fails. Add `--fix` to repair workflow triggers GitHub missed. |
| `npx starwisp license <key>` | Checks a license key offline. |

Options for `init`:

| Option | Use |
|---|---|
| `--org <name>` | The GitHub organization to install into. |
| `--license <key>` | Your license key (or set `STARWISP_LICENSE`). |
| `--from <path>` | Install from a release folder or `.tar.gz` you already downloaded. |
| `--update-url <url>` | Use a different update service (or set `STARWISP_UPDATE_URL`). Default `https://api.getstarwisp.com`. Must be `https://`. |
| `--console-url <url>` | Use this address for the console instead of the `workers.dev` one. |
| `--restart` | Forget saved progress and start over. |
| `--dry-run` | Print every command and run nothing. No network, no files, no browser. |
| `--debug` | Show stack traces. Use it when you contact support. |

Progress is saved in `~/.starwisp/install.json` (private to you). It holds progress and non-secret facts only.

## Before you run it

Run these once:

```bash
gh auth login
gh auth refresh -s repo,workflow,read:org
npx wrangler login
```

**You should now see** `gh auth status` say you are logged in, and `npx wrangler whoami` show your account.

Want to preview first? `npx starwisp init --dry-run --org my-company` changes nothing.

## The ten steps

### 1. Check prerequisites

The installer checks Node 20+, `git`, `npm`, `gh` (signed in, with `repo`, `workflow` and `read:org`), `wrangler` (signed in), and that the organization exists, is an organization, and that you are an **owner** of it.

The installer prints a line for each check, for example:

```text
[1/10] Check prerequisites
  ✓ Node 20 or newer
  ✓ git, npm, gh, wrangler found
  ✓ gh is signed in with repo, workflow and read:org
  ✓ you own the organization my-company
```

**You should now see** a line with a check mark for each prerequisite.

### 2. Verify your license

Paste the key when asked. It is verified on your computer. You should see `Licensed to you@acme.com (standard), updates until <date>`. If your updates period has ended, the installer tells you and tries the newest release you are entitled to.

### 3. Get the release

The installer sends your license to the update service and receives a short-lived download link and a checksum. It prints the host your key goes to. The download is verified against the checksum **before** anything is unpacked. With `--from` this step uses your local file instead.

**You should now see** `Release <version> ready`.

### 4. Your domain (optional)

The installer asks `Your domain, like example.com (press Enter for none):`. A domain is optional. If you have one on Cloudflare, give it: it is checked for shape only here, saved as `house_domain` in `.factory/identity.json` in your new `factory` repo, and used as `<app name>.<your domain>` for every app. You can also pass `--domain acme.com`. Press Enter if you have none: apps then go live free at `<app name>.<your-subdomain>.workers.dev` and app email stays off (see [presets](presets.md#a-domain-is-optional)). In the console, save your workers.dev subdomain as the **Free web address** in **Settings → Identity** (the form fills it in for you), or add a domain there later. If your `factory` repo already exists, the installer leaves it alone, so set these in the console.

### 5. Create your repos

It creates two **private** repositories in your organization: `factory` and `app-template` (marked as a template). If a repo already exists it is left alone.

Each repo is uploaded in two pushes: the code, then the workflows. GitHub only switches on a workflow's automatic triggers (new issues, pushes, schedules) reliably when the workflow arrives after the first push. The installer then waits up to 2 minutes for GitHub to start a run. If none starts, it prints a warning and goes on; run `npx starwisp doctor --fix` afterwards.

**You should now see** `factory and app-template (private)`.

### 6. Wire up updates

It saves your license as the Actions secret `STARWISP_LICENSE` in `<org>/factory` (sent over stdin, never on a command line) and the update service address as the variable `STARWISP_UPDATE_URL`. The Update button needs both. See [updates](updates.md).

**You should now see** `STARWISP_LICENSE (secret) and STARWISP_UPDATE_URL (https://api.getstarwisp.com) saved in <org>/factory`.

### 7. Deploy the console

It runs `npm ci` and `npm run deploy` in `factory/console` and reads your console's `workers.dev` address.

On a brand-new Cloudflare account this step can stop with `Your Cloudflare account has no workers.dev address yet.` Open Workers & Pages in the Cloudflare dashboard once (that assigns `<name>.workers.dev`; you don't need to create anything), then run the installer again. It picks up here.

**You should now see** `Console at https://…workers.dev`.

### 8. Set the console's settings

It stores four settings in your Cloudflare Worker: `AUTH_SECRET` (random), `AUTH_URL`, `FACTORY_ORG`, `FACTORY_REPO`.

**You should now see** `AUTH_SECRET, AUTH_URL, FACTORY_ORG, FACTORY_REPO`.

Then it asks `Anthropic API key (sk-ant-api03-…, hidden), or press Enter to skip:`. This is optional. If you paste your key (typing is hidden), it is saved in two places at once: the Actions secret `ANTHROPIC_API_KEY` in `<org>/factory` (the Vault, which runs use) and a secret of the same name on the console Worker (the Idea Studio on Home, which talks to Claude from the console itself and can't read GitHub secrets back). It goes over stdin and is never written to disk. If you skip it, add the key in **Settings → Vault** later and follow the Setup row **Idea Studio: Anthropic key on the console**. You can also set `ANTHROPIC_API_KEY` in your shell before running the installer.

### 9. Create the GitHub App

Your browser opens to GitHub with a prefilled App. Click **Create GitHub App**, then on the next page click **Install** and choose **All repositories**.

> **If GitHub asks you to confirm it's you** (password, passkey or 2FA), it can lose the prefilled App and show an empty **Register new GitHub App** form for your personal account instead. Don't fill that in. Go back to the installer's local link (`http://127.0.0.1:<port>/`, printed in the terminal) and open it again: it re-sends the prefilled form for your organization.

> **Choose "All repositories", not "Only select repositories".** Each app you build gets its own new repository. A selected-repositories install cannot see it, so the run would fail at that point. If you chose wrong, change it at `https://github.com/organizations/<org>/settings/installations` (open the App, set *Repository access* to *All repositories*, Save). The Setup page also checks this and links straight to the setting. Then the installer waits (up to 10 minutes) until GitHub says the App is on your organization. If an earlier run already created the App and stopped, the installer instead shows the install link and asks `Press Enter after you chose "All repositories" and clicked Install:`. Finish the install on GitHub, then press Enter.

The installer then stores `APP_ID` (a variable), `APP_PRIVATE_KEY` and `APP_WEBHOOK_SECRET` (secrets) in `<org>/factory`, and the App's sign-in id and secret in your console. The private key goes straight from memory into GitHub over stdin. It is never written to disk. See [security](security.md).

**You should now see** `App installed`.

### 10. Finish

It prints your repo and console addresses and opens `<console>/setup`. Save keys on **Settings → Vault** and test them on the Setup page (see the [quickstart](quickstart.md)).

**You should now see** `Starwisp is installed.`

Check any time with `npx starwisp doctor`.

## Every error the installer prints

Every expected error prints four lines: what went wrong, why, the fix, and a link. Your progress is always saved, so after the fix, **run the same command again**. Errors are listed here in the order you could hit them.

### Options and commands

| Message | Fix |
|---|---|
| `Unknown option.` | Run `npx starwisp --help` and use a listed option. |
| `Unknown command "…".` | Commands are `init`, `doctor` and `license`. |

### Step 1: prerequisites

The error reads `Prerequisite not met: <name>`. The first failing check is shown.

| Check | Fix |
|---|---|
| `"<org>" is not a valid GitHub organization name.` | Names use letters, numbers and hyphens. Pass the exact name: `--org my-company`. |
| Node.js 20 or newer | Install the current LTS from <https://nodejs.org>, then run again. |
| git is installed | Install git from <https://git-scm.com/downloads>. |
| npm is installed | npm ships with Node.js. Reinstall Node.js. |
| GitHub CLI (gh) is installed | Install from <https://cli.github.com>, then `gh auth login`. |
| gh is signed in to github.com | `gh auth login` (GitHub.com, HTTPS, sign in with the browser). |
| gh token can create repos and workflows (shows `missing: …`) | `gh auth refresh -s repo,workflow,read:org` |
| wrangler is signed in to Cloudflare | `npx wrangler login`. With several Cloudflare accounts, also set `CLOUDFLARE_ACCOUNT_ID`. If wrangler cannot run at all: `npm install -g wrangler`, then `wrangler login`. |
| `<org>` exists on GitHub | Check the spelling and that `gh auth status` shows the right account. |
| `<org>` is a GitHub organization (it is a personal account) | Starwisp installs into an organization. Create a free one at <https://github.com/account/organizations/new?plan=free>, then `npx starwisp init --org <name>`. |
| You are an owner of `<org>` | Ask an owner of the org to make you an owner, or have them run the installer. |
| `<org>` is a GitHub organization you administer (gh is not available) | Fix the `gh` items first. |

### Step 2: license

| Message | Fix |
|---|---|
| `That license key did not check out.` | Copy the whole key from your purchase email: one line, no spaces. If it still fails, use <https://getstarwisp.com/retrieve-key>. The "Why" line says which problem it found, below. |

The "Why" line is one of:

| Why | Meaning |
|---|---|
| `A license key looks like LW1.xxxxx.yyyyy.` | It is cut off or not a key. |
| `License key has invalid characters.` | Stray characters, often from a line break. |
| `License signature is the wrong length.` | The key is cut off. |
| `The signature does not match. The key may be mistyped, cut off, or altered.` | Re-copy it. |
| `License payload is not valid JSON.` / `…not in canonical form.` / `Unsupported license version.` / `Payload is not an object.` | The key was altered or is not a Starwisp key. Re-copy it. |
| `The license says it was issued in the future. Check your computer clock.` | Fix your computer's clock (automatic time), then run again. |

An **expired updates date does not make the key invalid.** It only limits which releases you can download. See [updates](updates.md).

### Step 3: release

| Message | Fix |
|---|---|
| `--from path not found: <path>` | Pass a release folder or a `.tar.gz` that exists. |
| `The update service address must start with https://` | Use `--update-url https://<host>`, fix `STARWISP_UPDATE_URL`, or drop it. Your key is sent there, so plain `http` is refused. |
| `Could not reach the Starwisp update service.` | Check your connection. Or download the release with the manual link in your purchase email and run `npx starwisp init --from <path to the .tar.gz>`. |
| `The update service rejected your license.` (HTTP 401 or 403) | Paste the whole key. Ask for a re-send at <https://getstarwisp.com/retrieve-key> if it still fails. |
| `Your license has no updates left for the newest release.` | The newest release was published after your "updates until" date. Your installed copy keeps working. Renew at the link shown, or see [updates](updates.md). |
| `The update service could not give you a download.` | Try again in a few minutes. If it keeps failing, use the manual download link with `--from`. |
| `The update service gave a download link that is not safe to use.` | Try again later. If it repeats, send support the version you were installing. |
| `The update service did not include a checksum for the release.` | Run `npx starwisp@latest init` or try again later. The installer refuses to unpack a download it cannot verify. |
| `The release download failed.` | The link is short-lived. Run the command again for a fresh one. |
| `The downloaded release is damaged.` | The checksum did not match. Run again. If it repeats, contact support with the version number. |
| `Could not unpack the release file.` | Check the `.tar.gz` is complete (download it again) and you have disk space. |
| `The release does not look like a Starwisp release.` | The release needs `factory` and `app-template` folders at its top level. Download it again from your purchase email. |

### Step 4: repos

| Message | Fix |
|---|---|
| `GitHub would not let you create <org>/<name>.` | Ask an org owner to allow members to create private repositories, or run the installer as an owner. Also run `gh auth refresh -s repo,workflow`. |
| `Could not create <org>/<name>.` | Run the command again. It skips repos that exist and finishes the rest. Check <https://www.githubstatus.com>. |
| `Could not push the workflows to <org>/<name>.` | Run the command again; it adds the workflows to a repo that is missing them. Also run `gh auth refresh -s repo,workflow`. |
| `Could not mark <org>/<name> as a template repository.` | Open the repo's Settings on GitHub, tick **Template repository**, run again. Without it new apps cannot be created. |
| `Could not prepare <name> for upload.` | Check `git` is installed and you have disk space. |

Two warnings (not errors) can show here:

- `GitHub has not started any workflow for the push to <org>/<name> in 2 minutes`: finish the install, then run `npx starwisp doctor --fix`.
- `<org>/<name> has no .github/workflows, but this installer did not make its last commit`: the repo was there before the installer, so it is left alone. Run `npx starwisp doctor` to see what it needs.

### Step 5: deploy

| Message | Fix |
|---|---|
| `Installing the console's dependencies failed.` | Check your connection and that Node is 20 or newer, then run again. |
| `Cloudflare needs to know which account to use.` | Your login has several Cloudflare accounts. `export CLOUDFLARE_ACCOUNT_ID=<your account id>` then run again. |
| `Cloudflare rejected the deploy.` | Your `wrangler` login expired. Run `npx wrangler login`, then run again. |
| `Your Cloudflare account has no workers.dev address yet.` | New Cloudflare accounts get `<name>.workers.dev` the first time Workers & Pages is opened. Open <https://dash.cloudflare.com/?to=/:account/workers-and-pages> signed in to the same account, wait for it to load, then run again. (wrangler's own `…/workers/onboarding` link may not open.) |
| `Deploying the console to Cloudflare failed.` | Run again; the deploy is safe to repeat. Add `--debug` for full output. Check <https://www.cloudflarestatus.com>. |
| `The console deployed, but I could not read its address.` | Find the address in Cloudflare (Workers → `starwisp-console`), then run `npx starwisp init --console-url https://<that address>`. |

### Step 6: console settings

| Message | Fix |
|---|---|
| `Could not set the console secret <NAME>.` | Check you are signed in (`npx wrangler login`), then run again. |

### Step 7: GitHub App

| Message | Fix |
|---|---|
| `Timed out waiting for GitHub.` | Nobody finished creating the App within 10 minutes. Run again. Nothing was created. |
| `Could not reach GitHub to finish creating the App.` | Check your connection, run again. |
| `GitHub says that sign-in link expired.` | GitHub allows one hour and each link works once. Run again. If an App named `Starwisp <org>` was created, delete it first at your organization's GitHub Apps settings (`https://github.com/organizations/<org>/settings/apps`). |
| `GitHub could not finish creating the App.` (`HTTP <status>`) | Run again in a few minutes. |
| `GitHub returned an incomplete App.` | Delete the App at the link above and run again. |
| `Could not write the App's keys into <org>/factory.` | Delete the App `Starwisp <org>` in your org's GitHub Apps settings and run again. You need to be an admin of `<org>/factory`. |
| `No client secret given.` | A previous run stopped before the console's sign-in settings were saved. GitHub shows a client secret once, so open the App's settings, click **Generate a new client secret**, then run again and paste it. |
| `GitHub rejected the App's own credentials while checking the install.` | HTTP 401: the App id or key is not accepted, or your computer clock is off by more than a few minutes. HTTP 403: the org may block the App or be rate-limiting it. Check your clock and that the App exists and is allowed on the org, then run again. |
| `The App is not installed on <org> yet.` | No install appeared within 10 minutes. Open the install link, click **Install**, choose **All repositories**, then run again. |

A warning (not an error) says `The App is installed on selected repositories only`. New app repos need **All repositories**. Change it at `https://github.com/organizations/<org>/settings/installations`.

### Anything else

`Something unexpected went wrong: …` is a bug in the installer, not something you did. Run the same command with `--debug` and send the output to support (see [support](support.md)). Do not paste keys.

## If `doctor` fails

`npx starwisp doctor` re-runs the prerequisite checks and then checks your install. Each failure prints a fix.

| Failing check | Fix |
|---|---|
| `An install is in progress or finished` (no install state found) | Run `npx starwisp init`. |
| `Install step done: <step>` (not finished) | Run `npx starwisp init`; it continues where it stopped. |
| `<org>/factory has the APP_ID variable` | Run `npx starwisp init --restart --org <org>`. This creates the GitHub App again; first delete the old one in your org's GitHub Apps settings. |
| `<org>/factory has the APP_PRIVATE_KEY secret` | Same as above. |
| `GitHub runs <org>/<repo>'s workflows on events` (and `schedules` for the factory) | GitHub did not switch on the workflows' automatic triggers, so builds and scheduled resumes never start on their own (installs before 0.1.2 can have this). Run `npx starwisp doctor --fix`: it makes two commits on `main`, one that takes `.github/workflows` out and one that puts the same files back, which makes GitHub register every trigger. If it stops between the two (Ctrl-C, a lost connection, or someone pushing at that moment), `main` has no workflows until you run `npx starwisp doctor --fix` again, which only finishes the job. Doctor also reports when GitHub Actions or one of the factory's own workflows is turned off; turn it back on as it says. If `main` only takes pull requests, `--fix` can't push: on a branch, add a one-line comment to every file in `.github/workflows` and merge it. GitHub can take many hours to start a new repo's schedules, so the schedule check waits a day after the last change to `.github/workflows` before it fails. |
| `The console answers` | Open your console address in a browser. If it is down, check Cloudflare Workers → `starwisp-console` → Logs, or run the installer again to redeploy. |

## Start over

`npx starwisp init --restart` forgets saved progress. It does not delete your repos or Cloudflare Worker. Existing repos are left alone.
