cockpit 3.0.9 copy "cockpit: ^3.0.9" to clipboard
cockpit: ^3.0.9 copied to clipboard

Production E2E automation CLI, daemon, MCP, drivers, and reports for Flutter and black-box apps.

Cockpit logo

cockpit

Flutter development control plane and headless black-box E2E runner.

cockpit version on pub.dev cockpit pub points cockpit likes on pub.dev cockpit popularity on pub.dev

CI Dart 3.8.0 or newer Android, iOS, macOS, Linux, Windows, and web BSD 3-Clause license

English · 简体中文

cockpit is the authenticated host control plane for Flutter/Dart development and headless black-box E2E. It contains the Supervisor daemon, isolated workspace worker, resource-oriented CLI, and a thin MCP server. It does not bundle a GUI or a web dashboard.

Install #

Cockpit requires Dart 3.8.0 or newer. Flutter workspaces require Flutter 3.32.0 or newer.

dart pub global activate cockpit any
cockpit --help

Run cockpit update to install and verify the latest release while requiring Pub to resolve a version at least as new as the running executable, so stale package indexes fail safely instead of downgrading Cockpit. It safely hands any source-installed native executable back to Pub, restores one optimized AOT executable, removes retired and temporary update payloads, and replaces an older running Supervisor while preserving its authorization mode and durable state. Dart Pub continues to own its shared download cache; Cockpit never deletes unrelated cached packages.

The package publishes four executables:

  • cockpit: interactive resource commands
  • cockpit_mcp: MCP stdio server
  • cockpitd: Supervisor daemon and foreground CI runner
  • cockpit_worker: private workspace worker process

Install For AI Agents #

Preferred: ask the current AI host to install the CLI, complete Skill, native adapter, and MCP surface. Copy this prompt:

Install Cockpit for the current AI host, including the CLI, complete cockpit Skill, native adapter, and cockpit_mcp when supported, by following https://github.com/cockpit-dev/cockpit/blob/main/skills/cockpit/INSTALL.md

Complete host-specific installation and verification instructions live in skills/cockpit/INSTALL.md. Native adapter and MCP details are documented in the agent integration guide.

Flutter Fast Path #

Run from the intended checkout. Cockpit owns discovery, the Supervisor, workspace/target registration, the app process, ports, and bridge state:

cockpit dev start cockpit/main.dart --platform macos
cockpit dev status
cockpit dev inspect "Save"
cockpit dev tap "Save"
cockpit dev wait
cockpit dev screenshot
cockpit dev reload
cockpit dev diagnose --verbosity standard

Omit the entrypoint and platform when they are inferable. Cockpit stores one active numeric handle per canonical Flutter project, guarded by checkout identity; the same project may keep separate platform/target handles. Use cockpit session list, cockpit session show HANDLE, and cockpit dev use HANDLE when identity needs confirmation or selection. Explicit --session targets one command without changing the saved active handle. dev starts its local Supervisor in process-scoped yolo mode. Cockpit does not read a keychain or secret store, and --env values are process-only.

Interactive Workspaces #

The CLI starts the per-user Supervisor when an interactive API command needs it. Register every project root and checkout explicitly:

cockpit daemon start
cockpit root add --path /work/projects --label projects
cockpit workspace register --root-id <rootId> --path /work/projects/app-a
cockpit workspace register --root-id <rootId> --path /work/projects/app-b
cockpit workspace list

CLI Output #

The default is minimal canonical LON, so normal commands omit output options. --verbosity standard|full adds context without changing operation accuracy; --format json|yaml|jsonl|path|none changes encoding or delivery. Use --verbosity full --output <file>.lon for the complete object. Request JSON only for jq, a JSON-only consumer, or JSON wire inspection. --output prints only the verified path. artifact read requires --output; binary data, Base64, hashes, and decision-irrelevant byte counts never enter terminal output.

Workspace commands accept --workspace-id. When it is omitted, Cockpit resolves the current directory against registered active workspaces and requires exactly one match. It never selects a global latest run, active session, or unrelated checkout.

cd /work/projects/app-a
cockpit op list
cockpit case list

op run accepts typed LON, JSON, or YAML and executes an advertised operation. The descriptor controls scope and idempotency; there is no arbitrary URL or HTTP method transport. Its advertised timeout is the default; pass --timeout only for a deliberate override within the advertised maximum.

cockpit op run analyze.workspace \
  --workspace-id <workspaceId>

Authorization Policy #

Dangerous operation kinds, operation safety effects, test safety effects, and production targets require explicit authority. The strict policy document is stored at COCKPIT_HOME/authorization.json and is loaded once when the daemon starts.

cockpit daemon policy validate --file authorization.json
cockpit daemon policy apply --file authorization.json --restart
cockpit daemon policy show

Use cockpit daemon start --yolo (or daemon restart --yolo) for an explicitly unrestricted local daemon. The mode lasts only for that daemon process; starting without the flag returns to the persisted restricted policy. The effective auth is exposed by daemon status and recorded in attempt and suite reports.

Applying without --restart requires a stopped daemon. The default policy denies dangerous operations and sensitive test effects; it does not authorize production or unknown target environments.

Quarantined leases remain blocked by default. Use the advertised lease.list operation to obtain the exact identity, then a reset-authorized lease.recover request to retry verified cleanup. forceRelease: true is limited to explicitly matched logical resources; forwarded ports can only be released after verified cleanup.

Canonical Case Replay #

Validate a case document, then submit an indexed case using its canonical document digest. Replays use explicit workspace, document, case, and idempotency identities.

cockpit case validate \
  --workspace-id <workspaceId> \
  --file example/cases/flutter_login.yaml

cockpit case run \
  --workspace-id <workspaceId> \
  --document-id <documentId> \
  --case-id flutter-login \
  --idempotency-key ci-login-001

cockpit run get --run-id <runId>
cockpit run events --run-id <runId> --after-sequence 0

Run events use authenticated SSE with afterSequence and Last-Event-ID resume support. Gap, terminal, and disconnect states are explicit. Artifacts are read with expected size and SHA-256 values and are rejected when response metadata or bytes differ.

Suites And Black-Box Targets #

Suites reuse indexed cases and add dependency DAGs, scoped fixtures, matrix rows, concurrency, retries, fail-fast behavior, recovery, and aggregate JSON/JUnit/HTML/Markdown reports.

Recovery persists node and attempt checkpoints plus exact fixture/row session bindings. An attempt active at worker termination becomes interrupted and is retried only when the suite policy allows it. A missing bound session is an explicit environment failure, never a silent replacement.

The default restartApp isolation runs before each case's attempt fixtures. Use resetAppData only when the selected driver advertises it, and choose sharedSession explicitly only when state sharing is part of the suite design.

Fields in one locator are an intersection; fallbacks are ordered alternatives. Native black-box targets additionally support state, hierarchy, and spatial constraints when their inspected accessibility capability reports them. A runtime rejects unsupported constraints instead of dropping them. Text and label matching defaults to exact; use an explicit matchMode of contains, typo-tolerant fuzzy, or regex for broader matching. A unique best candidate is selected by route and match quality. Equal best candidates fail as ambiguousTarget; use more signals, a relation, or 0-based index to select a list item.

cockpit suite validate --file example/suites/regression.yaml
cockpit suite run \
  --workspace-id <workspaceId> \
  --document-id <documentId> \
  --suite-id regression \
  --idempotency-key ci-regression-001
cockpit suite report --run-id <runId> \
  --output-dir cockpit-report

Register installed native applications and other system-controlled surfaces as workspace-owned targets. Put the stable platform app/package id on the target; a case may override it in its target requirements when necessary. Android uses ADB accessibility and device controls. iOS uses WebDriverAgent for accessibility and interaction; assign a distinct WDA endpoint when multiple devices or workspaces run concurrently.

An installed Flutter app or native/Flutter mixed stack uses targetKind: flutterApp, a real appId, no entrypoint, and a native-plane case. It is launched and driven through system accessibility with Flutter-aware duplicate semantics normalization. Native screens and embedded platform views remain in the same tree. Entrypoint-backed targets use the optional bridge and semantic plane for development-only Widget, route, and runtime inspection.

cockpit target register \
  --workspace-id <workspaceId> \
  --platform android \
  --device-id emulator-5554 \
  --target-kind nativeApp \
  --app-id com.example.app \
  --environment test \
  --mode automation \
  --idempotency-key android-target-001

cockpit target register \
  --workspace-id <workspaceId> \
  --platform ios \
  --device-id <deviceUdid> \
  --target-kind nativeApp \
  --app-id com.example.app \
  --wda-url http://127.0.0.1:8101 \
  --environment test \
  --mode automation \
  --idempotency-key ios-target-001

Use target list and target get to recover registered resources, target launch to activate one, and target inspect to read its live capabilities. For a launched Flutter or mixed-stack target, the sanitized output.systemControl profile in the target.inspect operation result is the authority for its secondary native driver. Do not reconstruct it from app.get, which intentionally redacts platform app and process identities.

Flutter target launches accept repeatable --dart-define, --dart-define-from-file, --flutter-arg, and --env KEY=VALUE options plus a --timeout budget (20 minutes by default, 31 minutes maximum). MCP and generic operations use the same nested launchConfiguration fields: dartDefines, dartDefineFromFiles, flutterArgs, and environment. Cockpit-managed launch arguments cannot be overridden, and configuration values are not returned. On Android and iOS, environment configures the Flutter build process; mobile application processes do not inherit arbitrary host variables. Use Dart defines or an application-owned configuration channel for values the app must read.

Operation descriptors publish executionMode, defaultTimeoutMs, and maximumTimeoutMs. Synchronous operations block to a result and accept a single --timeout duration such as 90s or 20m. Case and suite submissions are asynchronous durable jobs that return runId; --timeout controls the overall run budget (case: 30 minutes by default, 6 hours maximum; suite: 2 hours by default, 24 hours maximum).

Case setup, main steps, finally, and suite fixtures can use type: system with an advertised system action name and parameters. This keeps install, activation, permissions, device state, and cleanup inside the same safety, timeout, event, and report pipeline as UI actions.

A step-level plane may override the case default with semantic, native, visual, or coordinate. The runtime otherwise derives the plane from the action and locator. Flutter bridge sessions retain a system driver for the same target, allowing semantic Widget steps and native, visual, or coordinate steps to run in one case. Conditions and nested fragment/if/retry/loop steps inherit the effective plane unless they override it.

Text control includes copyText, eraseText, and pasteText. travel applies a bounded sequence of latitude/longitude points with per-route or per-point delays. A visual locator names a workspace-confined template file; an assertScreenshot names a workspace-confined baseline and emits the actual, baseline, and deterministic diff files into the attempt evidence. Select each baseline by a stable platform/device/viewport, pixel-ratio, and orientation profile. Dimension mismatches are not auto-resized because they indicate a wrong profile or a layout regression. Use suite fixtures, case setup/finally, step evidence, and explicit recording operations to express pre/post capture at the scope that owns it.

Foreground CI #

CI uses the same HTTP API and worker boundary as interactive mode. Foreground mode owns the daemon lifetime, registers the supplied checkout, submits the provided CockpitRunSubmission JSON, waits for terminal run truth, and exits with a process status derived from the run outcome.

cockpitd \
  --home=/tmp/cockpit-ci \
  --foreground-workspace=/workspace/app \
  --foreground-submission=/workspace/run-submission.json

The submission contains the canonical case source, idempotency key, inputs, and required features. Foreground mode fills the registered workspaceId.

The repository release gate runs formatting, analysis, every package and example test suite, publication dry-runs, and real Android, iOS, macOS, Linux, web, and Windows regressions in parallel. Android and iOS must prove native locator/action/assertion control rather than screenshot fallback. Publication requires every job to reach a successful terminal state. Each platform regression proves a business mutation, the complete Flutter gesture/text/keyboard/semantics command surface, suite control flow, evidence, and the offline report bundle through observable assertions. Wait for the complete matrix, then diagnose from its reports, events, artifacts, and daemon logs in one pass.

API Discovery #

CockpitDaemonLifecycleClient.ensure() initializes the Cockpit home, validates process identity, and returns the current discovery record. Production clients then:

  1. send its bearer token only to the discovered loopback endpoint;
  2. read GET /api/v2/server;
  3. negotiate API major/minor and required features;
  4. decode public foundation DTOs strictly;
  5. use only advertised /api/v2 resources and operations.

The complete generic client surface is:

GET  /api/v2/operations
GET  /api/v2/workspaces/{workspaceId}/operations
GET  /api/v2/operations/schema
POST /api/v2/operations
POST /api/v2/workspaces/{workspaceId}/operations
GET  /api/v2/runs/{runId}/events

REST owns commands and resources. Authenticated SSE owns durable resumable run events. WebSocket is reserved for the internal Flutter Web bridge and is not a public client command transport. The operation invocation envelope owns scope, idempotency, and deadline; input contains only fields from the selected live request schema.

The shared CockpitSupervisorApiClient implements this flow for the CLI and MCP server, including 1 MiB response limits, bounded pagination, SSE resume, structured API errors, and artifact integrity checks.

MCP #

Run the CLI command or the dedicated executable:

cockpit serve-mcp
cockpit_mcp
cockpit serve-mcp --profile dart
{
  "mcpServers": {
    "cockpit": {
      "command": "cockpit_mcp",
      "args": []
    }
  }
}

MCP exposes bounded resources for server, capabilities, roots, workspaces, operations, targets, documents, cases, suites, runs, and artifacts. Its tools cover root/workspace lifecycle, advertised operations, target lifecycle, case/suite validation and execution, run get/cancel/events, artifact listing, and verified artifact downloads to explicit files. Every tool crosses the authenticated Supervisor HTTP boundary; the MCP process does not construct application services.

Profiles keep tool injection intentional: core is the default, while dart, flutter, app, e2e, and all add their capability domains. flutter includes dart; e2e includes app. Use repeatable --enable and --disable overrides for exact feature names or categories. The Dart profile provides analyze, format, fix, test, LSP, pub, package URI/search, and project creation without embedding or forwarding the official Dart MCP server.

Client Boundary #

The public /api/v2 resources, SSE stream, foundation DTOs, and artifact integrity contract are the only client boundary. A future Flutter GUI or third-party SDK must use that protocol and must not link Supervisor application services in-process.

Exported cockpit-report/ directories are complete offline run artifacts, not server UI. suite report --output-dir cockpit-report downloads the manifest and every declared report artifact with verified size and SHA-256, then commits the directory only after it is complete; the destination must not already exist. index.html embeds its CSS, JavaScript, and canonical report data while media uses bundle-relative paths. report.json is the stable single-file rendering input, and root manifest.json covers every exported file with ownership, size, media type, and SHA-256. Clients must preserve the directory structure and verify the manifest; no HTML route in cockpitd is required. Summary, Coverage, Executions, Evidence, Diagnostics, and Environment/files are task views over one fact graph, not persona-specific copies.

See ../../docs/contracts for protocol material and example/cases for canonical YAML and JSON cases.

1
likes
150
points
539
downloads

Documentation

Documentation
API reference

Publisher

verified publisherfluttercandies.com

Weekly Downloads

Production E2E automation CLI, daemon, MCP, drivers, and reports for Flutter and black-box apps.

Repository (GitHub)
View/report issues

Topics

#flutter #cli #tooling #ai #mcp

License

MIT (license)

Dependencies

args, cockpit_protocol, collection, crypto, dart_mcp, ffi, file, http, image, json_schema, lon, path, process, pub_semver, source_span, stream_channel, vm_service, xml, yaml, yaml_edit

More

Packages that depend on cockpit