# Core

> Manage Spaceship domains, DNS, contacts, transfers, marketplace listings and Hyperlift apps from the command line. Use when the user mentions Spaceship, asks about their domains, wants to check what is expiring, edit DNS records, transfer a domain in, list a domain for sale, or audit a domain portfolio for risk. Covers all 50 operations of the Spaceship public API.

- Skill: `crafter-station/core` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add crafter-station/core`
- Raw SKILL.md: https://api.skillmd.com/api/skills/crafter-station/core/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security, Productivity
- Author: crafter-station (https://skillmd.com/u/crafter-station)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/crafter-station/core

---


# spaceship core

Agent-first CLI for the Spaceship registrar API. Every command speaks JSON, every
write is gated, and every gate can be satisfied without a terminal.

## Output contract

One JSON envelope per command on stdout. JSON is automatic when stdout is not a
TTY, so `--json` is only needed when writing to a terminal.

```json
{
  "version": "1",
  "command": "domains list",
  "timestamp": "2026-08-19T00:00:00.000Z",
  "requestId": "spaceship-<uuid>",
  "ok": true,
  "result": { },
  "nextSteps": [{ "command": "...", "reason": "..." }],
  "rateLimit": { "limit": 300, "remaining": 297, "resetsAt": "..." }
}
```

On failure `ok` is false and `error` carries `code`, `message`, `hint` and
`retryable`. Branch on the exit code rather than parsing text:

| Code | Meaning |
|---|---|
| 0 | success |
| 1 | unexpected failure inside the CLI |
| 2 | usage: bad or missing arguments |
| 3 | missing or rejected credentials |
| 4 | the target does not exist |
| 5 | network failure |
| 6 | refused by a trust gate or the killswitch |
| 7 | rate limited |
| 8 | an async operation was still pending when --wait timed out |

## Discovering the surface

`spaceship schema --json` returns all 50 operations with their trust tier, rate
limit, required scopes and whether they are asynchronous. Read that instead of
parsing `--help`.

## Credentials

`spaceship auth login` prompts for the key and secret, verifies them against the
API, and stores both in the OS keychain. `SPACESHIP_API_KEY` and
`SPACESHIP_API_SECRET` also work and take precedence over stored ones.

Before doing anything else, check the setup:

```bash
spaceship doctor --json
```

It reports whether each credential is present, which source it came from, and
whether it actually works — without ever printing a secret. The key is masked
and the secret is reported as a character count. It exits 3 when credentials are
missing or rejected, so it is a usable precondition check.

`spaceship auth status` is the narrower version: credentials only, no API call.

## Trust tiers

| Tier | What it covers | What it needs |
|---|---|---|
| T0 | reads | nothing |
| T1 | reversible writes | `--apply` |
| T2 | destructive, no money | `--apply --yes` |
| T3 | money or domain loss | `--apply --yes --confirm <target>` |

Without `--apply`, a mutating command previews the exact request it would send
and exits 0 having sent nothing. `--confirm` must match the target exactly.

`--dry-run` forces the preview even with `--apply` present.

## Asynchronous operations

`domains register`, `domains renew`, `domains restore` and `transfer start`
answer 202 and finish later.

- Without `--wait`: the result carries `operationId`; poll with `spaceship ops get <id>`.
- With `--wait`: the CLI polls until the operation settles. Add `--timeout <seconds>`
  to bound it; a timeout exits 8 rather than reporting success.

Do not write your own poll loop. The status endpoint allows 60 requests per 300
seconds and the CLI already paces itself inside that budget.

## Rate limits

The list endpoint allows 300 requests per 300 seconds; the per-domain endpoint
allows **5 per domain** per 300 seconds. Prefer `domains list` over looping
`domains get`, and prefer `portfolio lint` over checking domains one at a time:
it audits a whole portfolio in `ceil(total / 100)` requests.

## Worth composing

```bash
# Confirm the CLI is set up before anything else
spaceship doctor --json

# What needs attention across the whole account, in one or two requests
spaceship portfolio lint --json

# What the lint checks for, as data
spaceship portfolio rules --json

# What is expiring, most urgent first
spaceship domains list --json

# Check many names at once (20 per request, handled internally)
spaceship domains check a.com b.dev c.io --json

# Preview a change before committing to it
spaceship dns set example.com A www 76.76.21.21 --json

# Renew and wait for the registry to confirm
spaceship domains renew example.com --years 1 --apply --yes --confirm example.com --wait --json
```

## Reading the portfolio lint

`portfolio lint` returns findings with a `severity` (`critical`, `warning`,
`notice`), the domain, a message stating what is true, and a runnable `fix`.
Seven rules cover expiry without auto-renew, domains past expiry inside the
recovery window, an open transfer lock, registrar suspensions, unfinished
registrant verification, public WHOIS, and missing nameservers.

`grace1`, `grace2` and `redemption` are distinct states, not one "expired": the
first two renew at the normal price, redemption carries a restore fee. The fix
each finding carries already reflects that difference.

## Safety notes

- `domains delete` cannot be undone and the name may be registered by someone
  else immediately. It is the only mutating endpoint with no documented rate limit.
- `domains renew` reads the current expiry from the API to build its
  double-charge guard; do not pass that date yourself.
- `dns set --force` disables Spaceship's conflict checker.
- Writes refuse while a killswitch file exists at the CLI's home directory.
  Reads and previews keep working.

## When to load another skill

`spaceship skills list` shows what else is bundled. Load one when the task goes
past reading and single changes:

- **portfolio** — auditing many domains at once, expiry sweeps, bulk changes and
  the request budget that makes them possible.

## Keeping up with the API

`spaceship spec diff` compares the live API against the recorded snapshot and
exits 1 when something changed that affects a shipped command.

