CLI

Command reference

Every Ghosty CLI command with examples (agents, channels, connectors, credentials, turns, sites, browser), global options and exit codes.

Updated 2026-10-10

Every command accepts --json and --help (ghosty skills --help and ghosty help skills show that command's usage and examples). <id> is an agent: its name (ghosty agents get pia-0, case-insensitive) or its id (shown by ghosty agents ls). If several share a name, the one in the ghosty use workspace wins; if there are still several, the CLI prints their ids to pick from.

Naming rule (like gh): noun then verb (ghosty cards show, ghosty boards create); turning something on or off is enable / disable (ghosty skills disable <id> pdf-doc); on / off only as an option's value (--sponsor on). The old forms (board, skills on|off, --on/--off, --vence) still work and say which one is new.

Session

CommandWhat it does
ghosty loginOpens the browser and signs you in (OAuth2).
ghosty login --deviceSign in from another device with a link + code (automatic over SSH or CI).
ghosty login --device --profile <client>Operate SOMEONE ELSE's account (a client): send them the link and code, they approve, and the session lands in that profile. Use it with --profile <client>; ghosty logout --profile <client> revokes it.
ghosty logoutSigns out and revokes the session on the server.
ghosty whoamiWhich email you are signed in as. With --json it also returns your account's plan.
ghosty usageYour plan and how much you've used this week and month (also ghosty me usage). See .
ghosty use <workspace>Default workspace: boards takes it without typing it, agents create is born there (--workspace none for a personal one) and agents ls shows only its agents (--all for all). ghosty use tells which; --clear removes it. Per profile (--profile).

Agents

bash
ghosty agents lsghosty agents ls --engine ghosty-lite --ids            # only ids, to chain with xargsghosty agents ls --sponsor testers@ghosty.studio       # staff: agents of ANY account (also --owner EMAIL); operate them by idghosty agents set <id> --prompt-file persona.md --prompt-mode replace   # its prompt WITHOUT the house personaghosty agents create --name Moon --engine ghosty-lite --model gpt-5.6-luna --env GHOSTY_THINKING_EFFORT=maxghosty agents get <id>                         # full configghosty agents get <id> --fields name,model,promptghosty agents get <id> --prompt-out PROMPT.md  # the prompt to a file (come back with set --prompt-file)ghosty agents create --name Pia --workspace sales --channels teams=off   # born in the workspace, owned by its ownerghosty agents create --name tania-mkt --like <pia-id> --dry-run          # with another agent's setup (not its prompt, env or channels)ghosty agents create --name tania-mkt --like <pia-id> --board new --no-notify   # its own board with the source's columns; shared without emailsghosty agents get <id> --fields toolsets,connectors   # what it really has: effective toolsets and connectorsghosty agents set <id> --prompt-file PROMPT.md # identity / instructionsghosty agents set <id> --name "Sales" --model claude-sonnet-5ghosty agents set <id> --engine claude --model claude-haiku-5-5 --env FLEET_EFFORT=highghosty agents set <id> --engine claude --dry-run      # what changing the engine does (sessions, machines, memory), without changing itghosty agents set <id> --connect google-drive          # gives it access to your Drive (--disconnect removes it)ghosty agents set <id> --channels wa=on,teams=off      # turn channels on/off (wa = personal WhatsApp)ghosty agents set <id> --unset-env EASYBITS_API_KEY,EASYBITS_BASE_URL   # delete env variables (also: --env K=)ghosty agents set <id> --prompt-base <base-id> --prompt-overlay overlay.json --dry-run   # prompt = another agent's + an overlay; regenerates by itselfghosty agents set <id> --prompt-base <base-id> --prompt-overlay mirror.json      # mirror.json = {"edits":[]}: one prompt and one memory; changes to the base replicateghosty agents set <id> --toolsets +crm                 # gs tool groups: a list replaces; +x / -x adds or removesghosty agents share <id> ana@company.com --role admin  # share without handing it over (editor or admin); agents shares <id> lists themghosty agents unshare <id> ana@company.comghosty agents teams ls <id>                    # Teams workspaces you administer: where it answers and with which @handleghosty agents teams on <id> lawyers --handle counsel   # turn it on there (without --handle, from its name); on an active one it changes the @handleghosty agents teams on <id> lawyers --factory plan,build,check   # make it @plan, @build and @check of that workspace's Software Factoryghosty agents teams off <id> lawyers           # pause it there: it stops answering and keeps its @handleghosty agents teams rm <id> lawyers --yes      # remove it from there and free the @handle; the agent staysghosty agents set <id> --voice elevenlabs:<voice-id> --voice-replies auto   # voice notes in channelsghosty agents set <id> --auto-stage on         # moves board cards by itself after each customer turnghosty agents set <id> --quote iva=0,prefix=SFI,vigencia=15   # house cotizar tool config (issuer, VAT, folio); empty clears it (rfc=)ghosty agents set <id> --catalog products.csv   # its catalog (sku,nombre,precio,unidad,categoria); replaces the previous oneghosty agents set <id> --quote iva-incluido=true,iva.GRANEL=16,solo-factura=true   # prices include VAT except bulk, which adds 16% only with an invoiceghosty agents set <id> --tool cotizar=off      # turns a house tool off in every channel (per channel: wa:cotizar=off)ghosty agents doctor <id>                      # checks the config; exits 1 if it finds a problemghosty agents archive <id>                     # stops answering on every channel and leaves the lists; nothing is deleted. Deleted automatically after 7 daysghosty agents restore <id>                     # brings it back as it was: Teams with its @handle, WhatsApp, memory and conversationsghosty agents ls --archived                    # archived agents and the date they get deletedghosty agents rm <id>                          # deletes the agent, its machines, its bundle (skills) and its versions; usage and turns stay (billing). Owner or staff (logged); asks you to type its nameghosty agents rm <id> --from-workspace         # if it's active in Teams: turn it off there first, then delete it (owner or staff)ghosty agents set <id> --tool wa:actualizar_identidad=off   # one tool per channel (channel:tool) or everywhere (tool=off); =on only removes the vetoghosty agents set <id> --avatar ./face.png     # its face in Teams (or an https link); stored at img.ghosty.studioghosty agents set <id> --bag "MiniGhosty"      # which bag of its workspace it spends from (staff only; none = the workspace balance)ghosty engines ls --models                     # engines and models valid for --engine/--model, with their costghosty agents restart <id>                     # Ghosty · Lite and Goose only: loads new skillsghosty agents demo <id> --slug shifts && ghosty agents demo enable <id>     # public link to try it without an account (see below)ghosty agents box <id> --contains /opt/claude-worker/skills/pdf-doc/render-doc.mjs=pdf-templates   # is its machine on the new image?ghosty agents box <id> --recycle               # replace it (never mid-answer); the new one starts on the next turn (Ghosty · Lite and Goose too, with history from their last backup) (--reenv only re-bakes the env; --force even if busy)ghosty agents box <id>                         # also shows its capacity: conversations per box, boxes on, turns now and what the plan allows

agents get shows the agent's env; values that look like secrets (…KEY, …TOKEN, …SECRET) come back as •••.

agents box shows which machines serve the agent and, with --check PATH (repeatable) or --contains PATH=TEXT, whether they have what you expect. Use it after an image change: on ✗, --recycle and check again after one turn. On Ghosty · Lite and Goose use agents restart.

create adds an agent to your account (no workspace) and returns its id. Without --engine it uses Claude; without --model, the engine's default. An engine or model that doesn't exist is rejected (also without --engine) and the error lists the valid ones; ghosty engines ls --models shows them beforehand.

--env K=V,K2=V2 sets variables on the agent's machine, in create or set; K= removes one. The most useful: GHOSTY_THINKING_EFFORT (off · low · medium · high · max) sets how much the model thinks on Ghosty · Lite.

Connecting Drive (or another connector) to your account gives no agent access: each one gets it with --connect <connector> or on its page → Connectors. Only the owner can grant it.

set changes only what you pass. Prompt and model apply from the next turn. --engine switches the engine; --model is then a model of the new engine. On Claude, effort is --env FLEET_EFFORT=low|medium|high|xhigh|max; without it, it runs at medium. Codex, DeepSeek, Goose and DeepAgents are deprecated: use Claude, Ghosty · Lite or Gemini.

Public demo: agents demo

A /p/<name>-<code> link so anyone can try your agent without an account, exactly as you built it (its machine, its skills, its engine), paid by you. With "Keep it" the visitor creates an account and takes their own copy, with the trial conversation and files.

bash
ghosty agents demo <id>                                   # status: link, expiry, caps and numbersghosty agents demo <id> --slug shifts && ghosty agents demo enable <id>                # create the link and turn it onghosty agents demo <id> --expires "2026-10-15T20:00"        # stops accepting messages then (your machine's time)ghosty agents demo <id> --expires no                        # no expiryghosty agents demo <id> --welcome "Hi! Upload your shift spreadsheet" --starter "Show me how to start" --chips "What do you do?|How much is it?"ghosty agents demo <id> --turns 150 --per-ip 30           # abuse capsghosty agents demo <id> --sponsor on                      # the copy of whoever keeps it runs on YOUR keyghosty agents demo <id> --rotate                          # new code: the old link stops workingghosty agents demo disable <id>
OptionWhat it does
--slug NAMELink name. A 6-character code is appended so it can't be guessed.
enable · disableghosty agents demo enable <id> turns it on and disable off (--on/--off still work as aliases).
--expires "YYYY-MM-DDTHH:MM"Fixed date when it stops accepting messages, the same for everyone; in your machine's time. --expires no removes it. After it, visitors only see "Keep it".
--turns NMessages per visitor (default 150).
--per-ip NMessages per IP per day (default 30).
--welcome TEXTChat greeting. Empty = the default greeting.
--starter TEXTHighlighted suggestion, first and in color; tapping it gets a 3-step walkthrough. --starter "" removes it.
--chips "a|b|c"Suggestions, separated by | (they may contain commas and question marks).
--sponsor on|offWith on, the copy of whoever keeps it uses your engine key (that agent only) and doesn't count against their plan.
--rotateNew code if the link leaked; open conversations continue.

With no options it only shows the status. The output includes trials, messages and copies kept (how many on your key) and, if the agent failed to answer a visitor, the last reason.

Web widget: agents embed

A chat bubble with your agent on your site, with one line of code. It only loads on the domains you list; each visitor gets their own isolated conversation and talks as a customer. Details in .

bash
ghosty agents embed enable <id> --domains "mystore.com,*.mystore.io"   # turns it on and gives you the <script> to pasteghosty agents embed <id>                                   # state, domains, caps, the code and numbersghosty agents embed <id> --welcome "Hi! How can I help?" --color "#0e1317"ghosty agents embed <id> --per-visitor 30 --per-ip 60      # abuse capsghosty agents embed <id> --title "My store" --subtitle "Replies in minutes" --avatar https://mystore.com/logo.png --icon avatarghosty agents embed <id> --position left --offset 24,24 --theme auto --placeholder "Ask anything"ghosty agents embed <id> --bubble-text "Questions?" --auto-open 15 --starters "Prices?|Shipping?"   # your suggestions (up to 4)ghosty agents embed <id> --style '{"fontFamily":"Barlow","radius":0,"headerBg":"#2d4a2e"}'   # fine style; --style none resets itghosty agents embed <id> --theme-source teams                # your Teams workspace brand (--workspace SLUG)ghosty agents embed <id> --theme-source site --site-url https://mystore.com   # your site's colorsghosty agents embed <id> theme > theme.json                  # export the theme; --style-file theme.json applies itghosty agents embed <id> --copy '{"waking":"One moment, please","thinking":["Reviewing your question…"]}'   # what it says while it works; --copy none resetsghosty agents embed <id> --out src/components/GhostyChat.tsx   # your own React component (token and theme baked in; .jsx without types; --force overwrites)ghosty agents embed <id> --rotate                          # new token: the old code stops loadingghosty agents embed disable <id>
OptionWhat it does
enable · disableTurns it on or off everywhere, instantly. Turning it on needs the Claude engine and at least one domain.
--domains "a.com,*.b.com"Where it may load. a.com includes www.a.com; *.b.com, its subdomains. Replaces the list.
--per-visitor NMessages per visitor per day (default 30).
--per-ip NMessages per IP per day (default 60).
--welcome TEXTThe first message the visitor sees (empty = "¡Hola! ¿En qué te ayudo?").
--color "#rrggbb"Main color; the text on top is computed by contrast.
--title T · --subtitle THeader name (default: the agent's) and a line under it.
--avatar URL|noneYour https image (re-hosted on img.ghosty.studio); none = the agent's ghost.
--icon chat|avatar|ghostWhat the floating button shows.
--placeholder TGrey text in the message box.
--position right|left · --offset X[,Y]Corner and distance in px from the side and the bottom (0–200).
--theme light|dark|autoPanel theme (auto = the visitor's).
--bubble-text TLabel next to the button.
--auto-open S|offOpens by itself after S seconds (1–120), once per visit, never on phones.
--starters "a|b"Up to 4 of your suggestions; "" removes them. Ghosty's are never shown.
--style '{json}'|noneFine style without free CSS (typeface, corners, per-piece colors). Patch per key; see .
--font NAME · --radius 0-24Shortcuts for style.fontFamily and style.radius.
--theme-source custom|teams|siteImports the theme from your Teams brand (--workspace SLUG) or your site (--site-url); it stays editable.
--style-file FILEApplies a theme exported with agents embed <id> theme.
--copy '{json}'|noneThe phrases while the agent works (waking, connecting, thinking 1–8, stillWorking, cantStart, interrupted, retryLabel; plain text ≤ 80) and showDuration/showCopyButton. Patch per key (null = Ghosty's); see .
--copy-file FILEThe same copy object from a file.
themeghosty agents embed <id> theme prints the theme (and copy) as JSON.
--out FILE.tsx|.jsxWrites a complete, editable, dependency-free React component with your token and theme at the top. Won't overwrite an existing file without --force. See .
--rotateNew token if the code leaked or you want to cut it off everywhere.

The output also includes the React snippet (npm i @ghostystudio/widget + <GhostyWidget token="emb_…" />); in --json, under react ({install, code}).

Try a demo and see what happened: demos

bash
ghosty demos try guardias-k3x9q2 "remember MANZANA-47"                # as a visitor, no browser (same thread across runs; --new for another)ghosty demos try guardias-k3x9q2 "what word did I tell you?" --recycle-between --agent <id>   # switches boxes between messages: does it remember?ghosty demos history <id> --since 2d --timeline                       # what visitors did (Ghosty staff only)

demos try counts against the demo's caps (messages per visitor and per IP per day) and shows up in its numbers and CRM. demos history shows turns, messages, attachments, deliveries and clones; it is Ghosty staff only: the owner sees numbers (agents demo), not their visitors' chats.

The agent as a file

ghosty agents export writes an agent's whole setup to a YAML (compatible with recipes); ghosty apply makes an agent match the file, showing the plan first.

bash
ghosty agents export pia-0 --out ./pia          # agent.yaml + skills/<slug>/… (without --out: YAML to stdout)ghosty apply ./pia --dry-run                    # the plan: + adds, ~ changes, - removes, ! notesghosty apply ./pia                              # asks and applies (--yes without a terminal)ghosty apply ./pia --agent tania-mkt --dry-run  # the same file on another agentghosty apply ./pia --create --name sofi-mkt     # a new agent from the file
  • Anything the file doesn't mention is left alone; the fields it has become exactly what it says.
  • Lists (databases, documents, shares, own skills, env vars) add and change; removing needs --prune (without it they show with !).
  • Secrets never leave: they're exported as ${NAME}. With NAME in your environment it changes; otherwise today's value stays.
  • Before applying, the agent's current version is saved (Versions, in the web). apply doesn't move an agent between workspaces.

Configure an agent

Every agent has its own machine and disk: files, skills and MCP work with any engine. On pool engines (Claude, Codex, DeepSeek, Gemini) they enter by themselves on the next turn; on Ghosty · Lite and Goose new skills enter with agents restart (needsRestart in agents get).

Files

bash
# Up to 10 MB eachghosty files ls <id>ghosty files put <id> prices.md --file ./prices.mdcat notes.txt | ghosty files put <id> notes.txtghosty files get <id> prices.md --out ./copy.mdghosty files rm <id> prices.md

Derived prompt

An agent can inherit another agent's prompt plus an overlay of edits: a store's branch using the head office's prompt with its own name, hours and catalog. When the base changes, the derived prompt regenerates by itself.

json
{ "edits": [  { "what": "name", "find": "Tania", "replace": "Pia", "all": true },  { "what": "branch", "find": "## Minimum order\n", "replace": "## Ixmiquilpan branch\n…\n\n## Minimum order\n" },  { "what": "scope", "find": "\\*\\*What I handle:\\*\\*[^\\n]*", "regex": true, "replace": "**What I handle:** both brands." }] }
  • Edits run in order and each must find its place. If the base changed right there, the derived agent keeps its previous prompt and agents doctor flags it (prompt.base).
  • --dry-run tells whether every edit applies (--out FILE writes the result). --prompt-base none unlinks and keeps today's prompt.
  • While linked, its prompt can't be edited directly (409): change the base or the overlay.

Patch the prompt

To change one piece of the prompt without rewriting all of it (and without overwriting what someone else changed in between), with the same overlay format:

bash
ghosty agents set <id> --prompt-patch hours.json --dry-run   # the diff: which lines changeghosty agents set <id> --prompt-patch hours.jsonghosty agents set <id> --prompt-append october-notice.md     # add that text at the end
  • It applies on the server, on the prompt as it is at that moment: no need to download it with get --prompt-out and upload it again.
  • If an edit doesn't find its place, nothing changes (409 saying which one). --prompt-patch and --prompt-append together: edits first, then the text.
  • It's logged (agent.prompt_patch). It doesn't apply to a derived prompt: change the base or the overlay there.

Skills

bash
# From the catalog by name, or your own with --fileghosty skills ls <id>ghosty skills disable <id> pdf-doc                 # turn one off (its own or Ghosty's); enable turns it back onghosty skills house <id> --only pdf-doc,office-reader --dry-run   # Ghosty's skills in bulk (--enable / --disable)ghosty skills add <id> grill-meghosty skills add <id> my-skill --file ./SKILL.mdghosty skills get <id> my-skill                    # list its filesghosty skills get <id> my-skill --out ./my-skill   # download the whole folder (prints the absolute path)ghosty skills templates <id>                       # pdf-doc templates: its own and Ghosty'sghosty skills add <id> my-skill --dir ./my-skill   # upload a folder (SKILL.md + assets)ghosty skills rm <id> my-skill                     # keeps a local copy and prints the undo commandghosty agents restart <id>                         # Ghosty · Lite and Goose only

skills rm saves the copy under ~/.config/ghosty/trash/ and prints the command that restores it.

skills templates reads a live machine (run one turn first) and lists what pdf-doc sees: agente:<skill> or casa. An agent's own template is <skill>/pdf-templates/<name>.html in any of its skills; with the same name it wins over the house one.

MCP servers

bash
# `set` REPLACES the whole listghosty mcp get <id> > servers.jsonghosty mcp set <id> --file servers.json

One key per end user: in an http MCP, a header may carry ${turn.token} ("Authorization": "Bearer ${turn.token}"). Each message-stream or turns call sends its turnToken and gs applies it to that turn only, through its proxy: the token never enters the box and is never stored. A turn without turnToken on that agent fails with an error. Not allowed in sse, stdio, the URL, or ACP agents.

Quoting with the house tool: VAT and catalog

The cotizar tool does the math, the folio and the PDF; the agent only sends the lines. Each line's VAT comes from the agent's config, in this order:

  1. If the call sends iva_pct, that one for everything.
  2. With solo-factura=true and no factura: true on the quote: 0.
  3. If the line's category has a rule (iva.GRANEL=16): that one.
  4. With iva-incluido=true (prices already include it): 0.
  5. Otherwise: iva (16 by default).

The category comes from the agent's catalog (--catalog), not from the model; the one the agent sends only counts when the product is not in the catalog. When lines carry different rates, the PDF breaks it down ("IVA (GRANEL 16%)"). An agent with its own cotizar skill doesn't use this tool: saving that skill turns it off.

Check an agent: agents doctor

Like brew doctor: it only prints what needs attention, each finding with the command that fixes it, and exits 1 when there is a problem (usable as a gate in a script). --verbose also lists what passed.

It checks: skills that could fire on the same request (two quoting skills on at once), skills the prompt names (skill \cotizar`, .claude/skills/cotizar/) that the agent lacks or has off, an own skill named like a house tool that is still on (the model may use the generic one), tools the prompt names that don't exist or have no permission, customer-write tables that no longer exist, db_/doc_` in the prompt with nothing granted, and turns that failed in the last 24 h.

Databases

bash
ghosty dbs ls <id>                                   # the account's databases and what this agent hasghosty dbs tables <id> <db>                          # tables, rows and columnsghosty dbs query <id> <db> "SELECT count(*) FROM products"ghosty dbs query <id> <db> "SELECT * FROM products WHERE sku = ?" --arg ABC-12ghosty dbs query <id> <db> "UPDATE folio SET n = n + 1" --writeghosty dbs export <id> <db>                          # the whole database: <db>.sqlite (sqlite3, DB Browser for SQLite, DBeaver)ghosty dbs export <id> <db> --table products         # one table as CSV (opens in Excel): <db>-products.csvghosty dbs grant <id> <db> --external-write quotes,folio   # what it may write from WhatsApp/Messengerghosty dbs grant <id> <db> --external-rows customers:phone+phone2   # from WhatsApp/Messenger each customer sees only THEIR rows ("" = no filter)ghosty dbs revoke <id> <db>ghosty dbs rename <id> totequim siiqtec --dry-run    # also rewrites the prompts, env and SKILL.md that name itghosty dbs ls <id> --orphans                         # databases no agent has grantedghosty dbs rm <id> <db> --dry-run                    # deletes the whole database (revoke only removes access); owner or staffghosty dbs import <id> <db> --from easybits:<db-id> --dry-run   # copy tables from EasyBits ($EASYBITS_API_KEY)ghosty dbs import <id> <db> --from easybits:<db-id> --tables products,prices --append
  • query is read only; --write allows INSERT/UPDATE/DELETE/DDL. --arg V gives the value of each ?, in order (repeatable).
  • export downloads a copy: without --table, the whole database as SQLite (every table with its rows); with --table, that table as UTF-8 CSV. --out says where to save it. It uses your session, not the agent's gat_ token, and is recorded in the audit log. The same downloads are on each database's page (/app/datos?tab=dbs → the database → .sqlite / table.csv).
  • import replaces each table's rows (idempotent); --append adds them instead and --tables a,b copies only those. --dry-run prints the plan (+ create, ~ replace N → M rows) and changes nothing. If the database is shared with agents already writing in gs (quotes, folios), it warns about the rows that exist only in gs and asks before deleting them.
  • db is an alias of dbs, and dbs sql of dbs query.

Catalog photos

A catalog's photos should live at permanent links (img.ghosty.studio): links from EasyBits or the customer's website expire or change, and WhatsApp stops sending them.

bash
ghosty dbs tables <id> <db>                                                # per photo column: permanent · external · emptyghosty dbs rehost <id> <db> --table catalogo --column imagen_url           # copies external ones to permanent links (idempotent)ghosty dbs import <id> <db> --from easybits:<db-id> --rehost-images catalogo.imagen_urlghosty dbs photos put <id> <db> --table catalogo --key-column sku --dir photos/ --dry-run   # loose photos: SKU-123.jpg → the row with sku = SKU-123
  • import warns when replacing a table would turn permanent links back into external ones, and gives you the exact flag.
  • photos put only takes JPEG, PNG or WebP up to 10 MB; --dry-run lists keys with no row and files that aren't images. The column is imagen_url unless --column.
  • On the web (/app/dbs, Tables tab) you get the same counts, a «Hacer permanentes» button, and you can drag a photo onto a row.

Documents

bash
ghosty agents docs ls <id>                           # documents it reads and may sendghosty agents docs grant <id> "Catalog 2026.pdf"     # --write: it may replace it · --no-deliver: never sends itghosty agents docs grant <id> "Catalog.pdf" "Prices.xlsx"     # several at once; --like <other> copies another agent'sghosty agents docs revoke <id> "Catalog 2026.pdf"ghosty agents docs add <id> --url https://example.com/prices.pdf --description "2026 prices"   # upload and grant (--file for a local one)ghosty agents docs replace <id> "Catalog.pdf" --file catalog-oct.pdf --note "October prices"   # new versionghosty agents docs history <id> "Catalog.pdf"        # versions: who, when and from where; and which agents use itghosty agents docs restore <id> "Catalog.pdf" 3      # back to v3 as a new version

<db> and the document accept the id or the name. An agent token (gat_…) only sees what was granted and cannot grant itself anything.

A document is one document even when several agents use it: replace uploads a new version that keeps the name (only the extension follows the type), the access and every agent that uses it, so a prompt that names it doesn't break. The previous version stays in the history (20 are kept). With an agent token, replace and restore only work if the agent has «Can update it» (grant --write).

Turns

bash
ghosty turns ls <id> --errors --since 1h             # failed turns and whyghosty turns ls <id> --status running                # running · done · stopped · errorghosty turns ls <id> --skipped --since 1d            # WhatsApp Business messages that did NOT open a turn, and why (operator active, records only, paused…)ghosty turns ls <id> --session web:…                 # one conversation; on Claude the «resumed» column says whether it resumed (✓) or started from scratch (⚠ orphan|stale|replaced)ghosty turns ls --workspace descti --quota-hits      # a WHOLE workspace's messages (WhatsApp Business and Teams) that got no turn because the balance ran outghosty turns ls <id> --json --limit 100ghosty turns show <id>                               # last turn: what came in, what it answered, each tool with its secondsghosty turns show <id> --full                        # the whole message and answerghosty turns cancel <id> <conversation>              # stop: the running turn AND its background jobs (video, subagents, wake-ups)ghosty turns show <id> <turn-id>                     # a specific one (the id is in turns ls)ghosty turns grep <id> "IVA" --since 7d --role agent # what the agent said (or --role user, the customer) and in which turn

turns grep searches the conversation text (not steps or tools) and returns each match with its turn, to open with turns show. In the «resumed» column, «1st turn» is the first turn of a new SDK session: not a memory loss.

--errors is the same as --status error. --since takes 30m, 1h, 2d or an ISO date; --limit defaults to 20 (max 500).

turns show first prints what came in (in) and what it answered (out), on any engine and channel (WhatsApp groups included). Then it answers "where did 4 minutes go?": the turn's timeline (+12.3s Bash office-reader … 8.1 s), the slowest tools and the total model calls and output tokens. That part reads the engine's transcript, so it only exists on pool engines (Claude, Codex, DeepSeek, Gemini), not on Ghosty · Lite or Goose.

WhatsApp channels

bash
ghosty channels whatsapp ls <id>                     # WhatsApp Business numbers and who answers themghosty channels whatsapp enable <id> 5512345678 --dry-runghosty channels whatsapp disable <id> 5512345678

Enabling a number makes the agent answer real customers: it asks you to type the number's last 4 digits (or --yes). A number has one agent: enabling it takes it from the other.

Groups belong to the agent's paired personal WhatsApp (not WhatsApp Business): which ones it answers, and as whom. equipo = the team (writes to databases, admin tools); cliente = like any customer.

bash
ghosty channels wa groups ls <id>                                   # name, on/off, role, jid (--cached: don't ask WhatsApp)ghosty channels wa groups enable <id> "Pia-cotizadora" --role equipo --dry-runghosty channels wa groups set <id> 120363…@g.us --name "SoFi team"   # the name gs shows (WhatsApp's doesn't change)ghosty channels wa groups disable <id> "Pia-cotizadora"ghosty channels wa groups set <id> "Sales team" --wake mention      # only answers when mentioned or replied toghosty channels wa groups create <id> "Sales team" --role equipo     # creates the group and prints the invite link

<group> is its name or its jid. Turning a group on asks first (or --yes): the agent starts answering there.

--wake: mention (the default when you turn a group on) only opens a turn when someone @-mentions the agent, writes its name or replies to one of its messages; everything else reaches it as context on its next turn. all answers every message (imported groups and groups made with create).

Who was answering this number?

If a number or a page was left without an agent, the «last answered by» column tells which agent answered it last and when (from gs's turns), so you can give it back:

bash
ghosty channels whatsapp integrations <id>            # + «last answered by» per numberghosty channels whatsapp integrations <id> --orphans  # only those nobody answers today that did have turnsghosty channels messenger ls <id> [--orphans]         # the same for the workspace's Messenger pagesghosty channels whatsapp enable <agent> 5512345678 --dry-run   # give it back

Bring a number from somewhere else

To migrate an agent from EasyBits (or a droplet) without signing the number up again:

bash
# WhatsApp Business: the number already lives in Formmy; point it at this agentghosty channels whatsapp integrations <id>                                            # the owner's numbers in Formmy (and those already linked in gs): number, who answers today, id; staff: --email other-accountghosty channels whatsapp link <id> --integration <formmy-id> --answer off --dry-run   # the plan: what changes in gs and in Formmyghosty channels whatsapp link <id> --integration <formmy-id> --answer on              # from now on it answers real customersghosty channels whatsapp history <id> --integration <formmy-id> --days 7 --dry-run    # recent cards, messages, orders and files from Formmy to the board (the dry run works before linking; importing counts the ones that arrive paused and retries by itself during a deploy)ghosty channels whatsapp history <id> --integration <id> --days 7 --dry-run --list      # WHICH ones: phone, name, first message, whether from an adghosty channels whatsapp history <id> --integration <id> --only-ads --column "New"     # import only those from an ad (or --phones a,b) into that columnghosty channels whatsapp link <id> --integration <id> --answer off --forward --ads-only on   # only conversations from an ad open a cardghosty channels whatsapp link <id> --integration <id> --board Sales   # one agent, several numbers: each number fills its own board (agent = the agent's)ghosty channels whatsapp link <id> --integration <id> --answer on --partner-tenant org_123 --partner-agent nik-public   # a number of one of your partner's businesses: that agent answers it (see Partners)ghosty channels whatsapp history <id> --integration <formmy-id> --days 7 --media      # only re-copy the missing filesghosty channels whatsapp unlink <id> --integration <formmy-id>                        # back to where it was
# Personal WhatsApp: the Baileys session exported from EasyBits, no QRghosty channels wa import <id> --from easybits:<agent-id> --own-number no --dry-run   # straight from EasyBits ($EASYBITS_API_KEY): first says whether the origin session is alive, keys and groupsghosty channels wa import <id> --from-file session.json --own-number no --dry-runghosty channels wa import <id> --from-file session.json --own-number noghosty channels wa import <id> --from-dir store/auth --own-number no --dry-run   # Baileys multi-file folder (nanoclaw)ghosty channels wa status <id>ghosty channels wa pause <id>                    # the way back on this side (keeps the session)ghosty channels wa pair <id> --phone 5215512345678   # pair a new number by code, no QR (in Mexico 52… and 521… are different accounts: it tells you which to try)
  • --answer has no default: on answers real customers; off only records. Formmy only forwards when its channel is on: on turns it on; with off, only if you add --forward (the plan warns when gs won't see the conversations).
  • The owner, an admin of the agent or Ghosty staff can do it. If the number's owner in Formmy has a different email, only staff.
  • history goes after link and never duplicates: run it before the cutover and again right at it. It fires no "new lead" alerts.
  • history also copies the files (photos, PDFs, audio) to gs, and the summary says how many were copied and how many failed. Formmy deletes them after 7 days: bring the number within that week. Failed ones are retried with --media, which touches no cards or messages; with --dry-run it says how many are missing.
  • import: first turn off WhatsApp in EasyBits without logging out (two connections with the same keys knock each other off; logging out invalidates them). --own-number no = it's a person's number: only their chat with themselves counts as the owner's. Delete the file afterwards: it holds the account's keys.

Board

bash
ghosty boards ls siiqtec                                 # the workspace's boards, with agents and cardsghosty boards create siiqtec "Siiqtec - Ixmiquilpan" --columns-from mainghosty boards assign <id> "Siiqtec - Ixmiquilpan"        # where its NEW cards goghosty boards move-cards siiqtec --from main --to "Siiqtec - Ixmiquilpan" --integration <formmy-id> --dry-run   # and the existing onesghosty boards rm siiqtec "Test"                          # only an empty one that is not the main boardghosty cards ls <id> --q 7712                            # recent cards (folio, name, phone, column)ghosty cards ls <id> --paused --limit 200               # the ones the agent doesn't answer: paused (e.g. brought by history from Formmy) or manualghosty cards show <id> "#12"                             # the thread: who wrote, text, attachment and whether gs kept a copyghosty cards archive <id> --integration test --dry-run   # archive cards in bulk (reversible)ghosty cards archive <id> --column Lost --before 30d --yesghosty cards pause <id> "#12" --mode 2h                  # pause the agent in that conversation (30min | 2h | 24h | until_tomorrow | permanent)ghosty cards resume <id> "#12"                           # resume it; also lifts "operator only" (escalated)ghosty cards reply <id> "#12" --directive "offer delivery"   # "Ask for a reply": answers what the customer left pendingghosty cards pending <id> --since 2026-10-06T02:13Z      # the ones waiting for an answer, and why some can't be answeredghosty cards pending <id> --since 12h --reply --dry-run  # what it would answer; without --dry-run it answers them one by one (asks, or --yes)

resume doesn't answer by itself (the wake-up Formmy sends on resume is ignored); reply does, only on WhatsApp Business and only if that agent answers the number. pending flags and never answers: paused, escalated, outside WhatsApp's 24 h window (Meta only takes templates), only a reaction, not WhatsApp Business, and numbers answered by nobody. pause, resume and reply are logged.

The board belongs to the workspace: an agent shared with you doesn't give you its board; the owner has to add you to the workspace. At least one filter is required (--integration, --column or --before).

Credentials

bash
ghosty credentials ls                                # provider keys in your vault (last 4 only)ghosty credentials set elevenlabs                    # hidden prompt; or --from-env VAR, or through stdinghosty credentials rm elevenlabs

A key is never accepted as an argument: it would stay in your shell history. creds is an alias of credentials.

Connectors

bash
ghosty connectors ls --q shop                        # your connectors: connected / available / soonghosty connectors connect shopify                    # OAuth: opens the browser (--no-open only prints the URL)ghosty connectors connect stripe --from-env STRIPE_SECRET_KEY   # key-based: verified before it's savedghosty connectors disconnect shopify                 # revokes it at the provider and removes it from your accountghosty agents set <agent> --connect shopify          # then give it to an agent

The same as /app/connectors and the app. Key connectors with several fields (Odoo, WooCommerce…) are asked one by one; secrets without echo and never as an argument.

Confirmations

agents rm, files rm, skills rm, credentials rm, board archive, replacing rows with dbs import and channels whatsapp enable ask before acting. Without a terminal (a coding agent, CI) they never wait for an answer: add --yes, or they exit 2 with the exact command to retry.

Talk to an agent

Test turns

bash
# One test turn: waits for the full answer (up to 3 min)ghosty try <id> "what are your opening hours?"ghosty try <id> "turn it into a PDF" --media photo.jpg                # with attachments, as from the app (repeatable, up to 8)ghosty try <id> "hi" --waba --session 5210000000009               # the real WhatsApp path; prints what it WOULD send (the test card is archived afterwards; --keep leaves it)ghosty try <id> "quote this" --waba --session 5210000000009 --media list.jpgghosty try <id> "" --waba --session 5210000000009 --media note.ogg --as-formmy   # the attachment arrives as Formmy sends it (proxy with credential)ghosty try <id> "and shipping?" --waba --session 5210000000009 --history thread.json --resetghosty try <id> --replay sample.json --out ./replay --max 5     # real conversations; report on your diskghosty try <id> --replay sample.json --out ./replay --concurrency 4   # conversations at once (default 8, max 30)ghosty try <id> --reset                  # forget the test session

--waba goes through the same path as a real WhatsApp Business customer (inherited context, price rule, board, voice) and sends nothing: no message, no voice note, no payment link. It lists everything that would have gone out, including what tools send: 📍 location, 📄 files, 🎤 voice, ↩️ quotes, 🔘 buttons, 👤 contacts and reactions. With --as-formmy the attachment goes the way a real one does: proxy with credential, copy to gs and transcription; it says at the end whether the copy arrived. --replay runs from your machine and writes replay.json after every step; if Ghosty deploys mid-run it waits the Retry-After and continues, and --resume picks up an interrupted run.

Conversations

bash
ghosty chat <id> "summarize the last email"ghosty chat <id> "what does this contract say?" --media contract.pdfghosty chat <id>                         # interactive; Ctrl-C cancels the turn, Ctrl-D exitsghosty chat <id> "go on" --conversation <conversation-id>ghosty conversations ls <id>ghosty conversations show <id> <conversation> [--limit 20]   # what was said (0 = all)

try is for testing configuration; chat uses the agent's real conversations, the same ones you see in the dashboard and the app.

Schedule turns

The agent works on its own at the time you set: each run lands in a conversation and notifies your phone (iOS or Mac app). If its answer is exactly OK, it stays silent; use that for "check and tell me only if…".

bash
ghosty schedule add <id> "Check the campaign and summarize it" --at 2026-10-01T09:00-06:00 --every 12h --until 2026-10-25 --title "Campaign"ghosty schedule add <id> "Remind me to call Ana" --in 30mghosty schedule add <id> "Keep going with the report" --in 2h --conversation <conversation-id>ghosty schedule ls <id>                  # pending turns and recent runsghosty schedule rm <id> <schedule-id>

Without --conversation a new conversation is opened (named after --title if given). Rules: repeat every 15 minutes at least, --until is required when repeating, at most 30 days ahead, and up to 5 pending per conversation.

In a channel conversation (--conversation waba:…, wa:<jid> for personal WhatsApp —a group or a chat— or messenger:…) the answer goes out through that channel; an «OK» answer is not sent. On WABA only within the 24 h window; on personal WhatsApp, if the agent's number is connected.

In a Teams thread

bash
ghosty schedule add minighosty "Introduce yourself to the team" --teams descti#general/4812 --at 2026-10-01T09:00ghosty schedule ls minighosty --teams desctighosty schedule rm minighosty <id> --teams descti

At that time the agent answers in the room (or in the thread: the number is the id of the message that starts it) as if someone mentioned it, with that room's memory. It must be active in the workspace's Teams and you must be a member. Without a thread it posts in the room. --every doesn't work with --teams yet.

Your account

bash
ghosty me files ls --kind documentghosty me files ls --q contract                    # search by name (library + your threads), --cursor for the next pageghosty me files get <file-id> --out contract.pdf   # download it (no --out: the signed link)ghosty me files export --dry-run                   # how many files and MB there are, per folderghosty me files export --out backup/               # download ALL: documents/, conversations/, library/ (rerunning only brings what's new)ghosty chat <id> "summarize it" --file <file-id>   # attach from your files, no re-uploadghosty agents docs dedupe --dry-run                # documents with the same content: one stays with everyone's accessghosty me files upload ./contract.pdfghosty me files rm <file-id>ghosty me memories ls                              # what your agents remember about youghosty me memories add "I prefer short answers"   # app-wide: they apply to all your agentsghosty me memories edit <id> "new text"ghosty me memories rm <id>ghosty docs                              # opens these docs

Usage

bash
ghosty usage                             # or: ghosty me usage# Plan Pro#   This week    42% used  resets 2026-10-05#   This month   18% used  resets 2026-11-01#   Top-ups     available
bash
ghosty usage --workspace descti --by agent,day --days 14   # turns, failed, tokens and «no balance» per agent and day (CDMX); owner or staffghosty usage --boxes --workspace siiqtec    # a workspace's boxes against its limit (spares, asleep) and per agentghosty plan apply siiqtec --dry-run         # what changes if you apply the scheduled plan NOW (seats, parallel, hosting, tokens)

plan apply can be run by staff, or by the workspace owner when there's no subscription (with one, the new plan starts when the invoice is paid). Without a workspace, both use the one from ghosty use.

With --json it returns plan.name, week.pct and month.pct (0 to 1; month.pct is null if your plan has no monthly cap), their resetsAt, creditMxn (top-up balance) and exhausted (true when you have no usage left). Change plan or top up: .

Workspaces

Token bags, renewal and slug of a workspace. The owner can read the bags; changing them, renewing and renaming is for Ghosty staff (logged in the workspace's audit).

bash
ghosty spaces ls                                             # your workspaces: role, plan, combo (staff: --user EMAIL, someone else's)ghosty spaces create mailmask --dry-run                      # new workspace owned by you (trial, same rules as the web); drop --dry-run to create itghosty spaces join denik                                     # staff: enter a client's workspace (no seat; logged) · leave to get outghosty spaces set denik --combo sales --dry-run              # staff: teams | sales | both (without Sales its boards are invisible)ghosty spaces set mailmask --model-cap 4 --house-claude on  # staff: + house Claude (when the owner brings no key);: the most expensive model it can pick (0.25 | 1 | 4 | none = its plan's); a trial caps at 0.25 and Claude does not fitghosty bags ls descti                                        # bags, spend, whether they cut and which agents spend from eachghosty bags create descti "MiniGhosty" --tokens 20M --note "agreed 30-sep"ghosty bags set descti "Astra" --recurring off              # one-time: counts from today and never refillsghosty bags set descti "Astra" --tokens 30M                 # raise the capghosty agents set minighosty --bag "MiniGhosty"             # hang an agent on it (none = the workspace balance)ghosty bags rm descti "Old"                                 # only if no agent uses itghosty spaces renew descti --until 2026-11-01 --note "paid October"   # «paid until»; refuses with Stripeghosty spaces rename totequim siiqtec --dry-run             # slug only; id, board, Stripe and WhatsApp stayghosty spaces transfer siiqtec --to siiqtec@gmail.com --keep-as admin --copy-keys --dry-run   # new owner: copies the keys they lack, the previous one stays admin; ACP boxes move with their /data, pool boxes are recycledghosty spaces archive tests --dry-run                       # owner or staff: same as Settings → Archive (asks you to type the slug); leaves /app and spaces lsghosty spaces restore tests                                 # brings it backghosty spaces log siiqtec --since 30d                       # the log: transfers, staff in/out, renewals

A transfer only changes the owner: the space, its agents, their skills and history stay as they are. Documents, databases, boards and numbers its agents use move to the new account; anything an agent outside the space also uses stays, and the dry run says so. --copy-keys copies the provider keys and connectors (MercadoPago, Skydropx…) the new owner lacks.

Archiving deletes nothing: the workspace stops showing in /app and ghosty spaces ls, and its agents, data and history stay. The owner or staff can do it; it's logged (workspace.archive / workspace.restore) and ghosty spaces restore <workspace> undoes it.

A monthly bag (default) refills every workspace period; a one-time bag (--recurring off) counts everything spent since it was created and, when it runs out, it's over. With --hard-cap on (default) turns stop at 100% with «out of balance»; with off it only counts. An agent with no bag spends from the workspace balance.

Audit log

Who changed what: the agent page's Save, channel changes, pauses and replies from the CLI, prompt patches, transfers, staff in and out and «log in as». Ghosty staff see everything; anyone else, only their own workspaces and agents. A gat_ agent token can't read it.

bash
ghosty audit ls --workspace siiqtec --since 24hghosty audit ls --agent tania-0 --action agent         # agent.save, agent.prompt_patch…ghosty audit ls --actor brenda@siiqtec.com --since 2026-10-05T00:00Zghosty audit ls --action card --json                   # card.pause, card.resume, card.reply

Factory

A workspace's Software Factory runs (they live in its Teams). Reading needs membership; renaming needs owner, admin or staff (logged as factory.run_rename).

bash
ghosty factory runs ls --workspace business --room mailmaskghosty factory runs show 15 --workspace business       # stage, current plan, PR, preview, latest events and which role is working (--full: the plan)ghosty factory runs rename 15 "CLI docs up to date" --workspace business --dry-runghosty agents ls --handle build --workspace business   # who is @build (without --workspace: in all your workspaces)

runs ls shows how long each run took and what it cost. To see where one run's time and money went:

bash
ghosty factory runs show 13 --timing --workspace mercadito-verde# #13 · pr_review · loops 0 · red CI 0 · $4.32 USD# clock: 4.2 h = working 71.8 min · waiting for a person 3.0 h · other (CI, queues) 1.3 min# at     step           time      in tools  model     usd    state# 17:07  @plan (thread) 1.2 min   0.1 min   opus-5-5  $0.87  done# 17:09  @check (critic) 0.6 min  0.1 min   opus-5-5  $0.51  done# 17:10  @build         68.8 min  66 min    sonnet-5-5 $1.82 done# Slowest commands (≥ 60 s)#   17:23 @build 10.3 min  Bash: until grep -q "TC_EXIT…
  • Working: some role had a turn running. Waiting for a person: the plan or the PR to approve. Other: CI, queues, deploy.
  • Commands of 60 s or more come from each role's transcript. ACP engines don't keep one: they show minutes and cost, without commands.
  • The cost includes @plan's first turn in the thread, before the run existed.

Why it got stuck or failed (a healthy run doesn't call the model; the analysis is saved, --refresh redoes it). See :

bash
ghosty factory runs why 13 --workspace mercadito-verde

And how the workspace's factory is doing:

bash
ghosty factory runs stats --since 7d --workspace mercadito-verde [--repo owner/repo]# runs: 11 · merged: 10 (91 %) · median to PR 29.6 min · to merge 30.3 min# @check→@build loops per run: 0.4 · red CI per run: 0# cost: $29.89 USD · per run $2.72 · per merged PR $2.99

Getting help

Support is by email: each case has its own reply address, so answering the email or writing here lands in the same case. You can also ask your agent in your chat: "report it to support". The case carries your account, your agents and their recent errors, so you don't have to repeat them.

bash
ghosty support open --title "My agent stopped answering on WhatsApp" --body "Since yesterday 6 pm…"ghosty support ls                                    # your cases and their statusghosty support show <id>                             # the threadghosty support reply <id> --body "I tried reconnecting"   # if it was resolved, it reopens

On the web: Support in the menu.

Support

For Ghosty staff (User.isAdmin): what used to be a script in the box for each report. Reading someone else's conversations is logged.

bash
ghosty agents ls --user ana@company.com --app android            # their list exactly as their app gets it (tone, space, last use; no tokens)ghosty usage --boxes --by template                                # the whole fleet by template: how many, real RAM and vCPU, awake and asleepghosty conversations ls --user david@company.com --since 7d          # their conversations in any agent (also --surface android)ghosty conversations show <agent> <conversation> --why               # the thread's kind, whose it is, and whether the owner / its user see it in their list or by linkghosty turns stats --since 14d                                       # real failure rate by engine, channel (Teams and A2A included) and error; without staff, the test channel or deleted agents (--all includes them)ghosty push log --user brenda@siiqtec.com --since 1d                 # which pushes were sent and what Apple/Google answeredghosty agents doctor --user quiroz@company.com                     # their agents: doctor, latest turns (and whether the app picked up each answer), plan/bag and boxes (flags duplicates)ghosty usage --images --plan free --since 7d --by user              # image charges vs the images agents delivered; real cost vs the price tableghosty conversations show <agent> <conversation> --tools            # every tool it ran (secrets masked) and the external domains it namedghosty novedades create --title "PDF and audio" --body "…" --image hero.png --link chats --publishghosty novedades set <id> --min-version 12                           # if their app is older, the button reads «Actualizar» (Play, in-app)ghosty novedades test <id>                                           # only to your phoneghosty novedades send <id> --at "2026-10-02T12:00"                   # scheduled, CDMX time (9–21 h)ghosty support ls --all --status open                        # the inbox; every case also reaches you by email and you answer from there (/resuelto on the 1st line closes it)ghosty support reply <id> --all --body "Done" --resolve      # emails the customerghosty support link <id> blissito/mailmask#52                # when the issue closes (or the PR merges), every tied case gets "fixed"

conversations archive|rm with --kind test|channel is for the agent's owner (or staff): rm never deletes customer threads (--kind channel), which are only archived because their memory is what keeps serving them. --kind personal is for anyone with access to the agent and only touches YOUR own chats with it, never someone else's. What you delete also disappears from the apps (iOS, Android) on their next sync. push log is recorded since 2026-10-01 and kept 30 days; since the same day it includes announcement pushes (kind: novedad), and novedades ls shows how many FCM delivered and rejected. agents ls --user --app also lists their phones with the app build, and the «fetched» column of agents doctor --user exists since 2026-10-01. --tools reads the transcript in Tigris (claude-worker) or the box history (goose, ghosty-lite); never while a turn is running in that thread.

Assigned staff

A Ghosty account executive assigned to a client's account sees and runs, with their own session, that account's agents (with and without a workspace), its documents, databases and boards. They don't see keys or tokens, don't touch plan or billing, and don't transfer or delete. Only staff assigns; the customer sees it as «Your Ghosty account executive» in their account. Every assignment and every write by the executive is logged.

bash
ghosty staff assign brenda@siiqtec.com siiqtec@gmail.com --reason "SIIQTEC migration"   # assign (no-op if already assigned)ghosty staff ls brenda@siiqtec.com                                    # who they serve (--all: also revoked)ghosty staff ls "" siiqtec@gmail.com                                  # who serves that accountghosty staff unassign brenda@siiqtec.com siiqtec@gmail.com --yes      # stops on their next click

In the panel, the executive picks «Atendiendo: » in Documents and databases and in Agents; it is a cookie revalidated on every request, never another session or «sign in as».

Sites

The sites your agents publish, at <slug>.ghosty.page (nobody needs an account anywhere else). sites ls shows yours: live, paused, and unpublished ones that can still be recovered.

Free plan: a site pauses after 30 days without changes (notice 7 days before; every change gives it another 30). While paused its link shows «This page is paused — Reactivate it» and nothing is deleted. After 30 days paused it is unpublished (the link stops working and the slug stays reserved) and its copy is kept 6 more months; then it is deleted for good. Reactivating it any time before that brings it back as it was, on the same link.

Pinned sites: $49 USD a year or $5 USD a month ($990 / $99 MXN), includes up to 3 sites. A pinned site never pauses and carries no «Made with Ghosty» banner. Need more? Each extra pack adds 3 sites for the same price. Releasing a site, cancelling or a failed payment send it back to the Free rule with notice: it never pauses at once.

bash
ghosty sites ls                                                      # your sites: state (pinned, paused, pauses on…) and linkghosty sites pin tacos-don-pepe                                      # pin it: with a free slot right away; otherwise a card-payment linkghosty sites pin tacos-don-pepe --interval month --currency mxn      # monthly, in pesos ($99 MXN a month)ghosty sites pin new-landing --add-pack                              # you already use your 3: add 3 more and pin this oneghosty sites unpin old-landing                                       # release its slot (back to the Free rule with notice)ghosty sites pins                                                    # your subscription, slots used and which sites hold themghosty sites pins --cancel                                           # cancel at period end (--resume undoes it)ghosty sites ls --house                                              # staff: the house sitesghosty sites publish ./melon.html --title "Gelatina de sandía" --slug gelatina-de-sandia   # staff: a single .html or a folder with index.htmlghosty sites publish ./landing/ --site gelatina-de-sandia            # staff: update that one (without --site a new one is always created)ghosty sites slug arbol-palpitante gelatina-de-sandia                # staff: change the slug of any live site

The slug: lowercase letters, digits and hyphens, 3 to 60, no hyphen at the start, at the end or doubled, and not reserved (api, admin, s, www, app, assets, static, dashboard, login). Errors with a code: slug_invalid, slug_taken and slug_unsupported (EasyBits does not accept choosing or changing the slug yet; nothing changes and it exits with 1). Limits: 1 MB per file, 8 MB and 40 files per site.

Browser

bash
ghosty browser logout          # signs the browser out: revokes the Ghosty for Chrome tokens of your terminal agents and disconnects the extension

Asks for confirmation (--yes for scripts). To reconnect the terminal, copy the new command from the extension panel. See .

Partners

ghosty partner gives an agent to each of your customers (one shared agent, memory per customer). It has its own page: .

Language

The CLI speaks Spanish if your system is in Spanish (LANG=es_MX…) and English otherwise; --lang es|en or GHOSTY_LANG forces it. It also translates the server's messages to English. With --json, keys and codes don't change.

Tab completion

bash
source <(ghosty completion zsh)          # in ~/.zshrc, after compiniteval "$(ghosty completion bash)"          # in ~/.bashrcghosty completion fish > ~/.config/fish/completions/ghosty.fish

It completes commands, subcommands and flags, plus your agents' and workspaces' names (cached for 5 minutes).

Global options

OptionWhat it does
--jsonMachine output: stdout carries JSON only. Notices and progress go to stderr.
--token <token>Use this token instead of the session. Also via the GHOSTY_TOKEN variable.
--profile <name>Use a separate saved session (also GHOSTY_PROFILE), e.g. one per account. Letters, digits, - and _.
-y, --yesSkip confirmations (required without a terminal).
-h, --helpHelp. ghosty help <command> too.
-v, --versionVersion.

An agent token (gat_…, generated on the agent's page) reaches only that agent: it works for agents get/set/restart, files, skills, mcp and try, but not for listing agents or chat.

Environment variables

VariableWhat it does
GHOSTY_TOKENToken instead of the session (like --token).
GHOSTY_PROFILESession profile (like --profile).
GHOSTY_URLAnother server (default https://www.ghosty.studio).
XDG_CONFIG_HOMEWhere the session is saved: $XDG_CONFIG_HOME/ghosty/config.json (default ~/.config). With a profile, config.<name>.json.
NO_COLORNo colors, no banner.
GHOSTY_NO_UPDATE_CHECKDon't ask npm for new versions (it also skips with CI). By default it checks once a day and notes it on stderr.
EASYBITS_API_KEYEasyBits key for dbs import --from easybits:….
GHOSTY_PARTNER_KEY · GHOSTY_PARTNER_KEY_SECRETSign partner commands with your server's credential (GHOSTY_PARTNER_SECRET still works). See .

Exit codes

CodeMeaning
0OK.
1API error (the message says which).
2Usage error: unknown command or option, missing argument.
3Not signed in. Run ghosty login.