# Adapto Install

> Bootstrap entry point for Adapto CMS. Ensures the `adapto` CLI is installed and at the supported baseline (consent-gated), then hands off to adapto:scaffold to create a new project. Run this first to get started or to install/upgrade the CLI.

- Skill: `adaptocms/adapto-install` (Agent Skill)
- Install (CLI): `npx skillmds@latest add adaptocms/adapto-install`
- Raw SKILL.md: https://api.skillmd.com/api/skills/adaptocms/adapto-install/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: adaptocms (https://skillmd.com/u/adaptocms)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/adaptocms/adapto-install

---


# adapto:install

The global bootstrap — like `npm create`. It makes the toolchain ready, then hands off to the right
setup skill. It writes **no CMS content** (`mutates: false`), but it does perform **host-level** changes
(installing/upgrading the CLI), which are gated by explicit consent.

## When to use
- First-time setup / **the front door**: "set up adapto", "get started", "adapto init". It preflights
  (`adapto:doctor`), ensures the CLI, then routes to `adapto:scaffold`. (No separate `adapto:init` — this is it.)
- The `adapto` CLI is missing or out of date (e.g. `adapto:doctor` flagged it).
- Starting a new Adapto project.

## When not to use
- Routine content/schema/translation work → the specific skill.
- Only checking whether things are OK → `adapto:doctor` (read-only; it never installs anything).

## Inputs
- New project vs existing repo (auto-detect from cwd; confirm with the user).
- New projects: framework (`next` | `astro` | `sveltekit`) and, optionally, a public API key.
- Optional: a specific CLI version to install (defaults to the supported baseline, `>=0.1.3`).

## Outputs
- `adapto` CLI installed and at/above the baseline, **verified** via `adapto version`.
- The user routed to `adapto:scaffold` to create a new project.
- (v1, spec-level) per-repo skill pack installed under `.claude/skills/` + `.adapto/skills.lock` pins.

## Preconditions
- A shell, network, and `curl` or `wget`. Node 20+ for the `create-adapto-app` path.
- **Does NOT require the CLI** — installing/upgrading it is this skill's job (same self-bootstrapping
  exception as `adapto:doctor` not requiring auth). The `requires.cli` range above is the target it
  ensures, not a gate that blocks the skill from running.

## Flow

### A. Ensure the CLI — consent-gated
1. **Check:** run `adapto version`. Three cases:
   - **Missing** (`adapto` not found on PATH) → propose install.
   - **Below baseline** (`< 0.1.3`) → propose upgrade.
   - **At/above baseline** → skip to (B).
2. **Inform + show the exact command + get explicit consent** before running anything, e.g.:
   > "Your Adapto CLI is `<missing | vX, below the supported v0.1.3>`. I'd like to install it by running:
   > `curl -sSL https://raw.githubusercontent.com/adaptocms/adapto-cms-cli/main/scripts/install.sh | bash`
   > This downloads the latest release binary to `/usr/local/bin/adapto` and may prompt for your password. Run it?"
3. **On consent:** run the command, then re-verify with `adapto version` and report the new version.
   **If declined:** stop, and print the command so the user can run it themselves.

⚠️ `install.sh` installs **latest**, which may be newer than the verified baseline (`v0.1.3`). If the
result is ahead of the baseline, say so and recommend re-running `adapto:doctor` and re-syncing
`shared/cli-cheatsheet.md` (the CLI is pre-1.0 — module names can change between releases). To install
the **exact** pinned version instead, download
`https://github.com/adaptocms/adapto-cms-cli/releases/download/v0.1.3/adapto-<os>-<arch>` and place it on
PATH (advanced; bypasses `install.sh`). Either way, the consent flow still applies.

### B. Authenticate — register or log in (the ONLY step until auth succeeds)
Probe auth with `adapto auth me --json 2>&1 || true`. **Append `|| true`** (or branch on the JSON) so the
expected "not logged in" result — which exits non-zero — doesn't surface as a red `Error: Exit code 1`; a
not-authenticated state is a normal branch here, not a failure. Don't chain it after `adapto version` in one
compound command: the compound takes the last command's exit code, so a clean `version` check looks failed.

If the probe shows **not authenticated**, present **exactly these two items and nothing else yet** — no
API-key step, no `npm run dev` (the API-key step comes *after* auth, because its URL needs the tenant id that
only auth provides):

**Say up front that this step is theirs to run:** auth needs a real terminal — the CLI prompts for each
field, and the agent has no TTY, **not even behind `!`** ([conventions.md](../../shared/conventions.md) §10a). So both options below are
**bare commands the user runs in a new terminal window** (any directory — auth is global). Never hand out
a flag-stuffed variant: the CLI asks for everything and masks the password, while `--password <pw>` on a
command line lands in shell history.

1. **Log in** — has an Adapto account already:
   ```
   adapto auth login
   ```
2. **Register** — new to Adapto. **Don't pick a signup route for them.** On this choice, ask a **second
   pickable question** — **`In the terminal`** / **`In the browser`** — and say up front that both send the
   same activation email and **both end in a terminal**, so the browser isn't a way to avoid one
   ([conventions.md](../../shared/conventions.md) §11).

   **2a. `In the terminal`** — the whole flow stays in the CLI. In a new terminal window:
   ```
   adapto auth register
   ```
   Prompts for email, password, and name, then sends an **activation email**. The **one human step** neither
   of us can automate is reading that inbox — with the token from the email, in the same terminal:
   ```
   adapto auth activate
   ```
   `activate` **logs you in and saves credentials** on success (no separate login step). It creates the
   **account only**, so this route lands on **zero tenants** and `onboard` below is the next move.

   **2b. `In the browser`** — sign up on the web and use the guided setup:
   ```
   https://app.adaptocms.com/auth/register
   ```
   Offer to open it (macOS `open <url>` / Linux `xdg-open <url>` / Windows `start <url>`). They register,
   click the activation link in the email, and the web app walks them through creating their
   **organization and first project**. Then, to connect the CLI, in a terminal:
   ```
   adapto auth login
   ```
   This route comes back **with a tenant already created**, so **skip `onboard`** and go straight to the
   tenant step below.

The **agent never fills in real values** and never runs these itself. Ask the user to come back when it's
done, then **re-run the probe** (`adapto auth me --json 2>&1 || true`) to confirm. Headless/CI has no window
to open: set `ADAPTO_TOKEN` + `ADAPTO_TENANT_ID` instead.

⚠️ **Don't branch on which route they said they'd take — branch on `adapto auth orgs --json`.** A user can
start the web setup and abandon it before creating a project, or register in the terminal and then make a
project in the browser anyway. The tenant list is the only reliable signal for whether `onboard` is needed.

**Then — as part of this auth check — establish the working tenant. Don't assume the saved/active one.**
List with `adapto auth orgs --json`:
- **2+ tenants →** present a **specific picker**: the tenants as **pickable options** under **"Which Adapto
  project do you want to work in?"** — every flow. Never inherit the active one or merely confirm it; show the
  full picker. Then `adapto auth switch-tenant --tenant-id <id>`.
- **Exactly one →** state it and proceed (nothing to pick).
- **Zero tenants (brand-new account) →** there is nothing to switch to yet. Run one command that creates the
  first org + project, issues an API key, and sets it active:
  ```
  adapto onboard --project-name "<name>" [--default-language <code>] [--languages <code,code>]
  ```
  For agent/headless use pass every value as a flag (no prompts; headless falls back to English if no default
  given). `onboard --json` **returns the API-key value** — **capture it silently into `.env` (never print or
  echo it)**, and do **not** `api-key issue` another key; if a key already exists, reuse it via
  `adapto api-key list --json`. This is the CLI-native equivalent of the web onboarding — the whole
  register → activate → onboard → key flow runs in the terminal, with the token-paste as the only human step.

**Only then** continue (→ scaffold / API-key step). The chosen tenant scopes everything downstream. (See `adapto:doctor`.)

### C. Route the project
- Route to `adapto:scaffold` (wraps `create-adapto-app`; the read-client ships with it). This variation
  supports **new projects only** — there is no existing-repo/retrofit flow.

### D. Install the per-repo skill pack — v1, spec-level
Copy the per-repo skills into `.claude/skills/` and write `.adapto/skills.lock` with version pins.
(Detailed in a later build pass.)

## Errors and recovery
- **No `curl`/`wget`** → instruct a manual download from GitHub Releases (no silent fallback).
- **`install.sh` needs sudo / permission denied** → surface the prompt; the user types their password.
  The agent never fabricates, echoes, or logs it.
- **Version still below baseline after install** → likely a stale PATH shadow; suggest `which -a adapto`.
- **User declines the upgrade** → proceed with the manual command printed; `adapto:doctor` will keep
  flagging the version until it's upgraded.

## Forbidden actions
- Never run the install/upgrade (or any host-modifying command) **without explicit per-command consent**
  ([forbidden-actions.md](../../shared/forbidden-actions.md)): inform → show command →
  consent → run → verify.
- Never echo or log a `sudo` password or any secret value.
- Never **replace or modify** the read-client that `create-adapto-app` provides (incl. editing its endpoint
  paths). If the generated frontend misbehaves, report it to the user — don't patch the client.
- Never write CMS content (`mutates: false`).

