Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Meza-dev/Ghostly/llms.txt

Use this file to discover all available pages before exploring further.

Ghostly is a local-first runtime composed of several cooperating packages, all orchestrated by a single CLI. Understanding how they fit together helps you configure the engine correctly, extend it for your workflow, and debug unexpected behaviour. This page walks through the monorepo layout, each component’s responsibilities, and the request lifecycle for an assisted run.
Local-first by design. All cryptographic keys, LLM credentials, run artifacts, and test data are stored on the developer’s machine — in ~/.ghostly/auth.json and a local SQLite database. Ghostly makes no outbound connections to a Ghostly cloud service. The only external network calls are the ones you configure: to your chosen LLM provider endpoint.

Monorepo layout

Ghostly/
├── apps/
│   ├── api/          # Hono REST server + Prisma/SQLite persistence
│   └── web/          # React SPA dashboard (served statically by the API)
└── packages/
    ├── cli/          # @ghostly-io/cli — installer and local runner
    ├── runner/       # @ghostly-io/runner — Playwright execution engine
    ├── mcp-server/   # MCP server for IDE integration (Cursor)
    ├── scanner/      # AST analyser — routes, components, selectors
    └── client/       # @ghostly-io/client — TypeScript REST API client
Each package is independently versioned and published under the @ghostly-io npm scope. The CLI bundles the compiled API, web dashboard, and MCP server as embedded assets so a single npm install -g @ghostly-io/cli is all end-users need.

Components in detail

The CLI is the single entry point for developers. It is published to npm as @ghostly-io/cli and registered as the ghostly binary (with the legacy alias ghost kept for backwards compatibility).What it does
  • Zero-config installerghostly install saves credentials to ~/.ghostly/auth.json, writes the MCP server configuration to ~/.cursor/mcp.json, installs Chromium via Playwright, and copies Cursor rules and skills to ~/.cursor/.
  • Credential managementghostly keygen generates a UUID (or hex token) API key and persists it to ~/.ghostly/auth.json. Every subsequent CLI command reads from this file.
  • Engine launcherghostly up runs prisma db push to migrate the local SQLite schema, generates the Prisma client, seeds the initial admin user on a fresh database, and then spawns the bundled API server process with all required environment variables injected.
Commands
CommandDescription
ghostly keygenGenerates a UUID API key and saves it to ~/.ghostly/auth.json. Pass --token for a random hex token instead.
ghostly installSaves credentials, configures the MCP server in ~/.cursor/mcp.json, installs Chromium, and syncs Cursor rules/skills.
ghostly configInteractive prompt to set the LLM provider, model, API key, and base URL. Pass --clear to reset.
ghostly up [-p PORT]Migrates the SQLite DB, generates the Prisma client, and starts the API + dashboard (default: port 4000).
ghostly updateUpdates the globally installed CLI to the latest published version.
Auth file structure (~/.ghostly/auth.json)
{
  "apiKey": "<uuid-or-hex-token>",
  "apiUrl": "http://localhost:4000",
  "llm": {
    "provider": "openai-compatible",
    "model": "gpt-4o",
    "apiKey": "<your-llm-api-key>",
    "baseUrl": "https://api.openai.com/v1"
  }
}
The API is a Hono HTTP server bundled inside the CLI’s npm package. It is launched by ghostly up and listens on 127.0.0.1:4000 by default.PersistenceGhostly uses Prisma with a SQLite backend. The database file is created automatically on first run. Key models:
ModelPurpose
UserDashboard accounts with email + hashed password. Role: admin or member.
ApiKeyPer-user API keys for programmatic access.
ProjectGroups runs by label and colour.
RunA single test execution: status, base URL, assisted metadata, and code hints.
StepIndividual Playwright actions within a run, with screenshot paths and a11y snapshots.
RunEventOrdered SSE event log for each run — streamed live to the dashboard.
AssistMemoryCached successful step plans per (userId, project, baseUrl, goal) — replayed on future runs.
UserLlmSettingsPer-user LLM provider, model, API key, and base URL overrides.
AuthenticationThe API supports two parallel auth mechanisms:
  • JWT (Authorization: Bearer <token>) — issued by POST /v1/auth/login for dashboard users.
  • API key (X-Api-Key: <key>) — the key from ~/.ghostly/auth.json, used by the CLI and MCP server.
Routes
POST   /v1/auth/login              # Issue a JWT for a dashboard user
POST   /v1/auth/register           # Register a new user (admin only)
GET    /v1/auth/me                 # Current authenticated user info

POST   /v1/run                     # Start a new run (direct or assisted)
GET    /v1/runs                    # List runs for the authenticated user
GET    /v1/runs/:id                # Get a single run by ID
POST   /v1/runs/:id/cancel         # Cancel a running test

GET    /v1/runs/:id/events/stream  # SSE stream of run events

POST   /v1/plan                    # Request a step plan from the LLM strategist

GET    /v1/projects                # List projects for the authenticated user
POST   /v1/projects                # Create a new project
DELETE /v1/projects/:id            # Delete a project

GET    /v1/api-keys                # List API keys for the authenticated user
POST   /v1/api-keys                # Create a new API key
DELETE /v1/api-keys/:id            # Delete an API key

GET    /v1/settings/llm            # Read per-user LLM settings
PUT    /v1/settings/llm            # Update per-user LLM settings
GET    /v1/settings/llm/providers  # List available LLM providers
GET    /v1/settings/llm/models     # List available models for current provider
POST   /v1/settings/llm/test       # Test the current LLM configuration

GET    /health                     # Liveness probe → { "status": "ok" }
GET    /v1/ping                    # Auth + LLM config probe
The runner is the Playwright execution engine. It exposes two public functions:runFlow(input: RunInput, opts?): Promise<RunResult>Executes a pre-defined list of steps directly — no LLM involvement. Each step is one of:
ActionDescription
gotoNavigate to a URL (same-origin enforced by default).
clickClick an element using smart selector fallbacks.
fillType into an input or textarea, with field-type expansion.
pressSend a keyboard key press.
waitForSelectorWait until an element is visible.
snapshotCapture an accessibility tree snapshot.
runAssistedFlow (the AI-driven mode)Invoked when a goal string is supplied instead of a step list. The pipeline works in horizons:
  1. Strategist — the LLM receives the goal, the current page URL, and optional codeHints from the Scanner. It returns the next batch of steps (a horizon).
  2. Observer — after each step, Playwright captures the live accessibility tree (page.locator("body").ariaSnapshot({ mode: "ai" })). The snapshot is fed back to the strategist for the next horizon.
  3. Healer — if a selector throws, the healer agent reads the a11y snapshot and proposes a repaired selector. The step is retried before being marked as failed.
Smart selector expansionBefore executing a click or fill, the runner expands the primary selector into a list of fallback candidates (e.g. a button:has-text("Login") selector also tries getByRole("button", { name: /Login/i })). The first candidate that resolves within the timeout wins; all errors are collected and surfaced as a single descriptive message if every candidate fails.Guardrails (from schema.ts)
const DEFAULT_RUN_GUARDRAILS = {
  maxSteps: 25,
  maxTimeoutMs: 120_000,
  enforceSameOrigin: true,
};
ArtifactsOn failure (or when explicitly enabled), the runner saves:
  • Screenshots — per-step PNG files (step-N-ok.png / step-N-failed.png).
  • Video — a .webm recording of the full run.
  • Console logs — up to 40 browser console messages captured during the run.
  • Detected alerts — visible toast/dialog messages collected from well-known CSS selectors.
The dashboard is a React SPA built with Vite. In production it is served as static files by the API server itself — the GHOST_WEB_DIR environment variable points apps/api to the compiled dist/ folder bundled inside the CLI package.Key views
ViewDescription
OverviewSummary cards: total runs, pass rate, recent activity.
Runs panelFilterable list of all runs with status badges and duration.
Run detailStep-by-step timeline with screenshots, a11y snapshots, and detected alerts. Video replay when a recording is available.
LLM settingsPer-user form to override the provider, model, API key, and base URL saved in user_llm_settings.
Real-time updates via SSEThe dashboard subscribes to GET /v1/runs/:id/events/stream as a Server-Sent Events stream. Each RunEvent row written by the API during execution is pushed to the client in sequence, updating the step timeline without polling.
The MCP server bridges MCP-compatible IDEs (primarily Cursor) to Ghostly’s local REST API. It is injected into ~/.cursor/mcp.json by ghostly install and communicates with the API using the key from ~/.ghostly/auth.json.Exposed tools
ToolDescription
ghostly_run_flowSubmit a goal (or a step list) for a given project and base URL. Returns a run ID and status.
submit_planPush a manually authored step plan to the API for immediate execution.
get_project_mapReturn the Scanner’s route/component map for a target repository — useful for giving the LLM context.
analyze_componentRun the Scanner on a specific component file and return its extracted selectors and props.
list_ghostly_projectsList all projects belonging to the current user.
read_flow_docsRetrieve built-in Ghostly flow documentation for IDE-side prompt augmentation.
The Scanner performs static AST analysis of a target repository to extract routes, React/Vue components, and CSS selectors. The output (codeHints) is attached to the Run record and injected into the LLM strategist prompt as grounding context — helping the AI make more accurate selector predictions even before the browser opens.The Scanner is invoked by the MCP get_project_map tool and can also be called directly from the API via the plan route when codeHints are not yet available.
@ghostly-io/client is a lightweight TypeScript wrapper around the Ghostly REST API. It is intended for use in custom scripts, CI pipelines, or third-party integrations that need to submit goals, poll run status, or retrieve step results programmatically — without going through the CLI or MCP server.

Assisted run lifecycle

The following sequence describes what happens from the moment a user submits a plain-English goal to the moment the dashboard shows a final verdict.
1

User submits a goal

The user enters a goal and a target URL in the dashboard (or via the ghostly_run_flow MCP tool in Cursor). The dashboard posts to POST /v1/run with the goal, project ID, and base URL. The API creates a Run record in SQLite with status running.
2

API calls the LLM strategist

The API resolves the user’s LLM configuration (from user_llm_settings or the environment), then calls the strategist with the goal, any codeHints from the Scanner, and the current run context. The strategist returns the first horizon of Playwright steps as structured JSON.
3

Runner executes Playwright

The runner receives the step list and opens a headless Chromium browser. For each step it calls the appropriate Playwright action (page.goto, page.click, page.fill, etc.) with smart selector fallback expansion. After every action it captures the a11y tree and any visible alerts.
4

Observer feeds the next horizon

The a11y snapshot from step 3 is sent back to the strategist along with the outcomes so far. The strategist plans the next horizon. This loop continues until the goal’s victory conditions are met or the maximum horizon count is reached.
5

Healer repairs failures

If a selector throws, the healer agent receives the a11y snapshot and the failing step. It proposes a repaired selector and the runner retries before recording the step as failed. Successfully healed selectors are logged for diagnostics.
6

SSE events stream to the dashboard

Throughout execution the API writes RunEvent rows for every step start, step success, step failure, and run completion. The dashboard’s SSE subscription on GET /v1/runs/:id/events/stream receives these events in real time and updates the step timeline live.
7

Run completes and memory is saved

On a successful run, the API writes an AssistMemory record for (userId, project, baseUrl, goal). On the next run of the same goal, Ghostly can replay the cached step plan — skipping LLM calls entirely and making the run faster and more deterministic.

Explore further

Assisted Mode

Deep-dive into the strategist–observer–healer pipeline and how horizons are planned.

Self-Healing Selectors

How the healer agent uses accessibility snapshots to repair broken selectors at runtime.

CLI Reference

Full flag reference for every ghostly command, including advanced up options.

API Reference

OpenAPI-style reference for all /v1/* routes, request bodies, and response shapes.

Build docs developers (and LLMs) love