A free local cloud environment for developers and AI coding agents.
Build, test, and debug Google Cloud applications from your terminal or coding agent. MCP connects your agent to local services, SDK configuration, test data, readiness, and diagnostics.
Run local service workflows without Google Cloud service charges, start with one command, and create local projects for your experiments and test suites within your machine's capacity.
Website · MCP guide · Claude & Codex marketplace setup
Install · Quickstart · How it works · Services · Commands · AI agents & MCP · Troubleshooting
localcloud (aliased lc) is the official host CLI for LocalCloud. It manages the
container runtime lifecycle, multi-project context, SDK environment variables, persistent Docker volumes,
and the Model Context Protocol bridge — so your application code keeps calling the same Google Cloud client
libraries it already uses, just pointed at loopback.
$ lc doctor
╭── LocalCloud v0.1.14 ───────────────────────────────────────────────────────────────────────╮
│ │ Top commands │
│ Checking LocalCloud setup │ localcloud (or lc) status | start | stop | restart │
│ │ eval $(lc env) Exports env vars that redirect cloud se…│
│ ╭────╮ │────────────────────────────────────────────────────────────────│
│ ╭──╯ ╰──╮ │ Context │
│ ╭─╯ ╰─╮ │ Data Volume: localcloud-data Project: local-gcp-project│
│ ╭╯ ╰╮ │ User: local-developer │
│ ╰──────────────╯ │ Config: built-in defaults (overridable by ./localcloud.yaml) │
│ │ │
├────────────────────────────┴────────────────────────────────────────────────────────────────┤
│ Supported Services (● 22 enabled · ○ 5 disabled) │
│ ● Storage ● Pub/Sub ○ Firestore ● Bigtable ● Spanner ● BigQuery │
│ ● Cloud SQL ● AlloyDB ● Memorystore ● Dataproc ● Tasks ● Scheduler │
│ ● Functions ○ Cloud Run ○ Compute ○ GKE ● Workflows ○ Vertex AI │
│ ● Sheets ● KMS ● Secrets ● IAM ● Logging ● Monitoring │
│ ● Resource Mgr ● Service Usage ● Billing │
╰─────────────────────────────────────────────────────────────────────────────────────────────╯
Tip: Run localcloud guide for AI agent workflows, or lc for the fast alias.
Docker 29.8.1 (/opt/homebrew/bin/docker) · Colima 0.10.1 (VZ, Rosetta on)
Image agentcloud/localcloud:lite (ID: 66d2113a69fb)
Ports 5380-5406 (in use by localcloud)
[OK] LocalCloud is ready to start 0.5s- 27 services, one container. Storage, Pub/Sub, BigQuery, Spanner, Bigtable, Firestore, IAM, KMS, Dataproc, Cloud Run and more come up together — not as a dozen emulators you wire up by hand.
- Your SDK code doesn't change.
eval "$(lc env)"exports the emulator variables the official Google client libraries already look for. Same calls, same objects, loopback endpoints. - Isolated, durable environments. A named Docker volume is the runtime's identity. Run a scratch environment for CI beside your everyday one, and keep data across restarts.
- Built for humans and automation. Every command renders a readable terminal summary, and the same
result as complete JSON with
--verbose.--dry-runpreviews mutations;--debugprints the equivalentdocker run. - Agent-native. A first-class MCP bridge lets AI coding agents provision, seed, inspect, and reset real GCP-shaped state as part of their own loop — not a UI a person has to click through.
- Zero live-cloud footprint. The CLI validates that every generated endpoint is loopback and refuses to
emit a real
googleapis.comaddress. There is no silent fallback to production.
| LocalCloud | gcloud beta emulators |
Testcontainers | Real GCP dev project | |
|---|---|---|---|---|
| Services | 27 | ~5 (Bigtable, Datastore/Firestore, Pub/Sub, Spanner) | Wraps the same emulators | All |
| Setup | One CLI command | One process per service | Written in test code | Project, billing, IAM |
| SDK wiring | eval "$(lc env)" |
Per-emulator, manual | Per-container, in code | ADC + real credentials |
| Web console | Built in | — | — | Yes |
| Terraform / OpenTofu | lc env --format terraform |
— | — | Yes |
| Agent control (MCP) | Built in | — | — | — |
| Data persistence | Docker volume, survives restarts | Process lifetime | Test lifetime | Durable |
| Cost / credentials | None | None | None | Billed, real keys |
Breadth is service availability — a callable, service-level integration. Operation-level parity is service-specific and recorded per service in the LocalCloud compatibility matrix.
Docker Desktop, Colima, OrbStack, Rancher Desktop, or Docker Engine, installed and running. LocalCloud needs at least 4 GiB of memory available to the container for stable operation.
No Docker yet? On macOS with Homebrew, lc doctor --fix (or lc start in a terminal) offers to install
Colima, a free, lightweight Docker engine, and starts it with 4 CPUs
and 8 GiB of memory.
On Apple Silicon, run the Docker VM on VZ with Rosetta rather than QEMU: it is faster, and QEMU has
known issues with LocalCloud (the BigQuery emulator can fail under it). lc doctor reports the Docker
app, its VM type and Rosetta, and lc doctor --fix offers to switch Colima or Rancher Desktop.
curl -fsSL https://local.cloud/install.sh | shThe installer adds localcloud and the shorter lc alias when available.
brew install LocalGCloud/tap/localcloud
brew upgrade localcloud # upgrade
brew uninstall localcloud # removeUpdate the CLI to the latest release:
lc updatelc update detects how LocalCloud was installed (script installer or Homebrew) and upgrades the CLI in place. For Homebrew, brew upgrade localcloud also works.
Signed release archives with Sigstore verification bundles are published for:
| Platform | Architectures | Minimum |
|---|---|---|
| macOS | Apple Silicon | macOS 13+ |
| Linux | x86_64, aarch64 |
glibc 2.35+ (Ubuntu 22.04+) |
Intel Macs are not supported: 0.1.11 was the last release with an Intel macOS archive.
Windows users can run the container directly — see the Docker setup instructions.
$ lc --version
localcloud 0.1.14 (commit c2bed60e4464, released 2026-11-03)Release builds embed their exact source commit and release date, so a binary can always be traced back.
Five minutes from nothing to a working Cloud Storage bucket.
lc doctorConfirms Docker connectivity, reports the Docker app and its VM setup, and shows the resolved LocalCloud
context. Continue when the last line starts with [OK]. It creates no LocalCloud state, so it is always safe
to run first.
If it lists Setup findings, lc doctor --fix offers to fix them, asking before each change.
lc startConfig built-in defaults (overridable by ./localcloud.yaml)
Data volume localcloud-data
Origin managed
Project local-gcp-project
User local-developer
Image agentcloud/localcloud:lite
Image status Available locally
URL http://127.0.0.1:5380
Ports 5380-5406
Services alloydb, bigquery, bigtable, cloudbilling, cloudfunctions, cloudiam,
cloudresourcemanager, cloudscheduler, cloudsql, cloudtasks, dataproc, gcs,
kms, logging, memorystore, monitoring, pubsub, secretmanager, serviceusage,
sheets, spanner, workflows
[OK] LocalCloud is ready 8.4sstart checks the registry for a newer image by default (--no-pull to skip), publishes the canonical
ports on all host interfaces, waits for service readiness, and tails logs for five seconds.
A service that reports a permanent failure doesn't fail the start. The command succeeds and warns
that the service is not available, giving the runtime's reason.
Use lc start --local-only to bind published ports to 127.0.0.1 instead.
Pass --local-only on subsequent start, restart, and reset commands to keep that binding.
Running start again on a live runtime is safe.
eval "$(lc env)"This exports the variables the official Google client libraries already read:
export STORAGE_EMULATOR_HOST="http://127.0.0.1:5382"
export BIGQUERY_EMULATOR_HOST="http://127.0.0.1:5388"
export SPANNER_EMULATOR_HOST="127.0.0.1:5386"
export BIGTABLE_EMULATOR_HOST="127.0.0.1:5385"
export GOOGLE_CLOUD_PROJECT="local-gcp-project"
export CLOUDSDK_CORE_PROJECT="local-gcp-project"
export CLOUDSDK_API_ENDPOINT_OVERRIDES_STORAGE="http://127.0.0.1:5382/"
# …one entry per enabled service, plus gcloud endpoint overrides and a local access tokenNo LocalCloud-specific client. No endpoint arguments. The environment does the work.
|
Python from google.cloud import storage
client = storage.Client()
bucket = client.create_bucket("my-bucket")
bucket.blob("hello.txt").upload_from_string(
"Hello from LocalCloud!"
) |
Node.js / TypeScript import { Storage } from "@google-cloud/storage";
const storage = new Storage();
const [bucket] = await storage.createBucket("my-bucket");
await bucket.file("hello.txt")
.save("Hello from LocalCloud!"); |
|
Go ctx := context.Background()
client, _ := storage.NewClient(ctx)
defer client.Close()
bucket := client.Bucket("my-bucket")
_ = bucket.Create(ctx, "local-gcp-project", nil) |
gcloud CLI gcloud storage buckets create gs://my-bucket
gcloud storage ls |
lc console # open the web console for the selected project
lc status # runtime health, endpoints, and ownership
lc logs # recent runtime logs
lc restart # recreate runtime with current local image (--pull to check registry)
lc stop # stop the container; the data volume is untouchedYour data survives stop and restart. lc start brings it back exactly as it was.
Tip for AI coding agents: Skip manual shell setup! Head to AI agents & MCP to configure Cursor, Claude Code, or Windsurf in one command (
lc mcp install).
your code ──► google-cloud-* SDK ──► 127.0.0.1:5380-5406 ─────────┐
terraform ──► GOOGLE_*_CUSTOM_ENDPOINT ───────────────────────────┤
AI agent ──► lc mcp (stdio) / :5380/mcp (HTTP) ──────────────────┤
│
┌─────────────────────────────────────────────┘
┌───────────▼─────────────────────────────────────────────┐
│ Docker container · agentcloud/localcloud │
│ │
│ :5380 gateway · console · admin API · MCP · facades │
│ :5382 Cloud Storage :5386-87 Spanner │
│ :5383 Pub/Sub :5388-89 BigQuery │
│ :5384 Firestore :5390 Memorystore │
│ :5385 Bigtable :5391 PostgreSQL │
└───────────────────┬─────────────────────────────────────┘
│
Docker volume: localcloud-data
mounted at : /var/lib/localcloud
The CLI never becomes a proxy — it configures and supervises. Once lc start returns, your SDK talks to
the container directly.
This is the one concept worth internalizing, because every flag follows from it:
| Axis | Flag | What it selects | Scope |
|---|---|---|---|
| Data volume | --data-volume |
The durable runtime identity — a named Docker volume mounted at /var/lib/localcloud. Two volumes are two independent LocalClouds. |
Docker |
| Project | --project-id |
A logical Google Cloud project inside one runtime. Many projects share a volume. start and MCP startup create a missing one. |
Request |
| User | --user |
The attributed caller sent to LocalCloud services, normalized to <name>@localcloud.invalid where a principal is required. |
Request |
Project and user are request context: switching them is instant and never touches Docker. Defaults are
localcloud-data, local-gcp-project, and local-developer. The MCP bridge instead gives each git
repository its own project, named after the repository, unless --project-id or the repository's
localcloud.yaml names one.
New runtimes prefer the canonical range 5380–5405 (plus DNS 5410/udp). With Cloud SQL MySQL
enabled, the set also includes 5406, which LocalCloud's MySQL companion container publishes. If that
complete set is unavailable, the CLI proposes one contiguous alternative from 5508–5539, then
5821–5840, then 5322–5342, and asks before creating the container. Such a runtime publishes only
the ports its enabled services use, so four can run beside the canonical one. To pick the host ports
yourself, set host.port_range: 6000-6099 or pass --port-range 6000-6099. The CLI never scans the
operating system's general ephemeral range, and lc env always emits the ports actually in use.
27 Google Cloud–compatible services, 22 enabled by default:
| Group | Services |
|---|---|
| Storage & databases | Cloud Storage, Firestore, Bigtable, Spanner, BigQuery, AlloyDB, Cloud SQL, Memorystore |
| Messaging & orchestration | Pub/Sub, Cloud Tasks, Cloud Scheduler, Cloud Workflows |
| Compute & serverless | Cloud Functions, Cloud Run, Compute Engine, GKE, Dataproc |
| Security & identity | Cloud IAM, Secret Manager, Cloud KMS |
| Management & billing | Resource Manager, Service Usage, Cloud Billing |
| Observability | Cloud Logging, Cloud Monitoring |
| AI & productivity | Vertex AI, Google Sheets |
Full catalog — service IDs and defaults
Use the ID with --services or services.enabled in localcloud.yaml.
| ID | Google Cloud service | Default |
|---|---|---|
gcs |
Cloud Storage | ● on |
pubsub |
Pub/Sub | ● on |
firestore |
Firestore | ○ off |
bigtable |
Bigtable | ● on |
spanner |
Spanner | ● on |
bigquery |
BigQuery | ● on |
sheets |
Google Sheets | ● on |
secretmanager |
Secret Manager | ● on |
cloudtasks |
Cloud Tasks | ● on |
cloudscheduler |
Cloud Scheduler | ● on |
cloudfunctions |
Cloud Functions (2nd Gen) | ● on |
alloydb |
AlloyDB | ● on |
dataproc |
Dataproc | ● on |
cloudiam |
Cloud IAM | ● on |
cloudresourcemanager |
Cloud Resource Manager | ● on |
serviceusage |
Service Usage | ● on |
cloudbilling |
Cloud Billing | ● on |
logging |
Cloud Logging | ● on |
monitoring |
Cloud Monitoring | ● on |
gke |
GKE | ○ off |
compute |
Compute Engine | ○ off |
cloudrun |
Cloud Run | ○ off |
memorystore |
Memorystore (Redis/Valkey) | ● on |
workflows |
Cloud Workflows | ● on |
vertexai |
Vertex AI | ○ off |
kms |
Cloud KMS | ● on |
cloudsql |
Cloud SQL | ● on |
● on services start automatically
when services.enabled is unset; ○ off services are available but must be selected explicitly.
Select an explicit set at start time, or reset to the built-in default:
lc start --services gcs,pubsub,bigquery,firestore
lc start --services defaultServices you enable or disable in the Console are saved on the data volume and come back on the next
start. --services outranks them for that start without clearing them, and start prints a
Service sources line naming where each enabled service came from. See
Which services run.
Lite and full images. lc start runs the lite image (agentcloud/localcloud:lite) by default. It has
every service above, but BigQuery's lite edition (no BigQuery ML, JavaScript UDFs, or EXTERNAL_QUERY on
Cloud SQL; Spanner's still works), and GKE creates metadata-only clusters. --full runs the full image
(:latest, or <version> instead of <version>-lite); the runtime keeps it on later starts and restarts
until --lite.
lc start --fullStaying current. A runtime keeps the image it was started with. A floating tag like lite is
refreshed by --pull. A version tag like agentcloud/localcloud:0.1.8-lite never moves by itself,
so start and restart look for a newer version on the same channel (lite or full) and, in a terminal,
ask before switching:
A newer LocalCloud image is available for this runtime.
Current agentcloud/localcloud:0.1.8-lite (the image data volume 'localcloud-data' last ran)
Offered agentcloud/localcloud:0.1.11-lite (Docker Hub; will be pulled, 373.1 MB)
The runtime is recreated on the new image and its data volume is migrated forward, so going back may not be possible.
Use 0.1.11-lite now? [y/N]The check reads Docker Hub's tag list at most once every 6 hours. When Docker Hub can't be reached,
it offers newer images already on your machine instead. A "no" is remembered for that data volume
until a newer version appears. Scripts and --verbose runs never switch: they get an Image update
line instead. An explicit --pull switches without asking. Set LOCALCLOUD_IMAGE_UPDATE_CHECK=false
to turn the check off. See Which image runs.
lc and localcloud are interchangeable in every example.
| Command | Purpose |
|---|---|
lc update |
Update the CLI through its script installer or Homebrew |
lc doctor |
Inspect Docker access, VM engine, and host setup; --fix interactively resolves issues |
lc start |
Start the runtime; supports --services, --local-only, --tls, --no-ui, and creating the project named by --project-id |
lc status |
Show runtime health, ownership, endpoints, and Docker details |
lc env |
Generate SDK, Terraform, or Docker Compose configuration; --identity starts a local identity session |
lc console |
Open the web console for the selected project and user |
lc logs |
Print recent runtime logs |
lc restart |
Recreate the container with the local image (default: --no-pull); --pull checks the registry and moves a pinned version to the newest |
lc reset |
Reset the selected project (--all-projects prints manual recreate steps) |
lc stop |
Stop the runtime without deleting persistent data |
lc cleanup |
Remove malformed Docker resources, stale runtime state, and legacy files |
lc guide |
Print authoritative coding-agent guidance |
lc mcp |
Run the stdio MCP bridge; lc mcp install configures AI coding agents |
Run lc COMMAND --help for command-specific flags and the valid --fields paths.
Every command speaks to a person and to a script from the same result:
| Flag | Effect |
|---|---|
| (none) | Concise terminal summary, with spinners and elapsed time in an interactive shell |
--verbose |
The complete structured result as JSON on stdout |
--fields PATH[,PATH…] |
Append specific JSON paths to the concise summary |
--dry-run |
Validate and print every planned Docker and LocalCloud mutation, changing nothing |
--debug |
Diagnostics on stderr, including a copyable equivalent docker run command |
lc status --verbose | jq '.container.url'
lc start --fields mcp.direct_url,container.name
lc start --dry-run # preview before mutating anything
NO_COLOR=1 lc doctor # symbols still carry status without colorService selection is marked with ● (on) and ○ (off) as well as color, so it stays legible under
NO_COLOR or a dumb terminal.
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Completed with failures (for example cleanup partial), or an unexpected internal error |
2 |
LocalCloud error — invalid input, Docker problem, or a failed operation. Rendered as Error [code] message |
130 |
Command interrupted with Ctrl-C |
An isolated environment per test suite. A second volume is a second, fully independent LocalCloud.
lc start --data-volume ci-e2e --project-id pr-1421
lc status --data-volume ci-e2e
lc stop --data-volume ci-e2eSeveral projects on one runtime. Switching is a request-context change, not a restart.
lc start --project-id payments-dev
eval "$(lc env --project-id payments-dev)"
lc start --project-id analytics-dev
eval "$(lc env --project-id analytics-dev)"Terraform and OpenTofu. --format terraform emits GOOGLE_*_CUSTOM_ENDPOINT variables that the Google
provider reads — evaluate them into your shell, do not redirect them into a .tf file.
$ eval "$(lc env --format terraform)"
$ env | grep GOOGLE_ | head -4
GOOGLE_STORAGE_CUSTOM_ENDPOINT=http://127.0.0.1:5382/storage/v1/
GOOGLE_BIGQUERY_CUSTOM_ENDPOINT=http://127.0.0.1:5388/
GOOGLE_PROJECT=local-gcp-project
GOOGLE_OAUTH_ACCESS_TOKEN=localcloud-user.bG9jYWwtZGV2ZWxvcGVy…
$ terraform applyDocker Compose services. Emit the same endpoints as Compose-ready environment entries.
lc env --format docker-composeA JSON payload for scripts.
lc env --format json | jq '.STORAGE_EMULATOR_HOST'Signed local identity for host processes. Application Default Credentials obtain LocalCloud-signed
ID and access tokens for a service account from a 12-hour metadata relay on 127.0.0.1. The command
warns, without changing anything, when GOOGLE_APPLICATION_CREDENTIALS or gcloud's application-default
credentials would take precedence, and keeps the relay out of a configured HTTP(S)_PROXY. See
env --identity.
eval "$(lc env --identity --account [email protected])"
python my_app.py # google.auth.default() now returns the runner account
eval "$(lc env --identity --stop)"In CI. Skip the registry check for reproducibility (--no-pull also keeps the newer-version check
off the network), disable log tailing, fail loudly, and leave out the web console the tests never open.
lc start --data-volume ci-$GITHUB_RUN_ID --no-pull --no-ui --tail 0 --verbose
# …run tests…
lc stop --data-volume ci-$GITHUB_RUN_IDPreview before you mutate. Lifecycle dry runs are strictly read-only and never pull.
lc start --dry-run # every planned Docker and LocalCloud mutation, in order
lc restart --dry-runRestart with local image vs pull. By default, lc restart recreates the container using the
currently available local Docker image, without pulling. A runtime pinned to a version tag still gets the
newer-version offer, which reads Docker Hub's tag list at most every 6 hours. Pass --no-pull to stay off
the network entirely. Use --pull to fetch a newer image.
lc restart # fast restart with current local image (e.g. after building locally)
lc restart --no-pull # same, and never contacts Docker Hub
lc restart --pull # pull a newer image (a pinned version moves to the newest on its channel)If the new image cannot start on the existing data, restart recreates the runtime on the image it was
running and says so in the error (rolled_back_to_image).
Reset one project without losing the others.
lc reset # clears the selected project; reseed from the Console
lc reset --all-projects # prints manual recreate steps; deletes nothinglc reset --all-projects deliberately mutates nothing. Recreating every project means deleting the data
volume, and LocalCloud never runs docker volume rm for you — it prints the steps and exits non-zero so
nothing is destroyed by accident.
LocalCloud provides native Model Context Protocol (MCP) integration, giving AI coding agents a local cloud environment to build, test, and debug Google Cloud applications with standard SDKs and zero Google Cloud service charges for local workflows.
Follow the local setup guide for Claude, Codex, Cursor, and other clients for installation, GitHub plugins, connection checks, and a first test prompt. Local setup does not depend on official Directory approval.
- On-demand auto-start: When your agent makes a call or initializes, the MCP bridge checks and starts LocalCloud in the background automatically (guarded by file lock against race conditions). Pass
--no-startif you prefer manual runtime control. - Shared default environment: Sessions using the default
localcloud-datavolume reuse its runtime. Select another data volume deliberately when you need a separate Docker environment. - Safe local testing: Agents generate authentic emulator environment variables (
eval "$(lc env)"), query local databases (BigQuery, Spanner, Cloud SQL), publish/pull Pub/Sub messages, and test Cloud Storage buckets directly against loopback. - Project contexts: Use
--project-idfor different applications and tests. Projects share the selected runtime and are not a security boundary.
Configure LocalCloud for your AI coding client in one command:
# Install for Cursor (user-level in ~/.cursor/mcp.json)
lc mcp install --client cursor
# Install for Claude Code (user scope via claude CLI)
lc mcp install --client claude-code
# Install for Claude Desktop (claude_desktop_config.json)
lc mcp install --client claude-desktop
# Register directly in Codex (CLI and local desktop sessions)
codex mcp add localcloud -- "$(command -v localcloud)" mcp
# Install for Gemini CLI (~/.gemini/settings.json)
lc mcp install --client gemini
# Install for Antigravity (~/.gemini/config/mcp_config.json)
lc mcp install --client antigravity
# Install for Windsurf (~/.codeium/windsurf/mcp_config.json)
lc mcp install --client windsurf
# Configure every supported client installed on this machine
lc mcp install --client allUse claude-code explicitly for Claude Code; claude is a Claude Desktop alias. --client all configures only the clients it detects and fails if it finds none. Codex uses its own registration command. --client cline writes Cline's shared settings file; see Cline to edit it by hand. Choose a direct connection or the GitHub plugin per client to avoid duplicate tools.
- Global by default: Installs into user-level configuration (
--global). Use--projectwith a client that supports repository scope (Cursor, Claude Code, Gemini CLI, or Antigravity). Claude Desktop, Windsurf, and Cline always use user configuration. For a project installation in a GUI client, add--command-path "$(command -v localcloud)"to keep an absolute executable path. - Desktop PATH resilience: On macOS, automatically resolves to permanent system binaries (
/opt/homebrew/bin/localcloudor/usr/local/bin/localcloud), ensuring GUI applications launched from the Dock or Finder run smoothly without shell PATH issues. - Custom overrides: Pass
--command-path <CMD>to supply a custom executable (e.g.lcor/opt/homebrew/bin/lc), or--bareto force the barelocalcloudcommand.
Prompt your agent to use LocalCloud emulators:
You have access to the
localcloudMCP server. Follow itsuse-localcloud-instead-of-gcpprompt. Runlocalcloud guideor uselocalcloud_get_envto direct all Google Cloud client libraries and Terraform to local loopback emulators.
You can also run lc guide in your terminal: it prints authoritative, copy-pasteable workflow guidance generated from the runtime's own service catalog, so it cannot drift from what the image actually ships.
The MCP bridge exposes the running runtime's tools, resources, and prompts. Discover its catalog to check the capabilities available in your environment:
| Capability | Tools & Resources | What the agent does |
|---|---|---|
| Service discovery & health | localcloud_list_serviceslocalcloud_check_readiness |
Discovers running services, assigned loopback ports, and verifies emulator readiness before sending requests. |
| API catalog & schemas | localcloud_get_api_cataloglocalcloud_browse_resources |
Inspects full Google Cloud REST OpenAPI schemas, method parameters, and browses buckets, tables, and topics. |
| Data querying & SQL | localcloud_query_data |
Runs real SQL queries against local BigQuery, Cloud Spanner, and Cloud SQL databases without requiring client SDKs. |
| SDK & Terraform wiring | localcloud_get_envlocalcloud_generate_terraform_env |
Generates environment export commands (STORAGE_EMULATOR_HOST, etc.) and Terraform provider overrides. |
| Testing & scenarios | localcloud_list_recipeslocalcloud_export_state |
Seeds test data scenarios, creates project state checkpoints, and diffs state changes. |
Run the three reproducible cloud workflows for complete agent prompts and Python/SDK test runs for Cloud Storage, Pub/Sub, and BigQuery:
(Watch the recorded demo or see the full MCP Architecture & Guide).
If you prefer to configure your MCP client manually:
{
"mcpServers": {
"localcloud": {
"command": "/opt/homebrew/bin/localcloud",
"args": ["mcp"]
}
}
}(On macOS desktop apps, an absolute path like /opt/homebrew/bin/localcloud is recommended when launched from Dock/Finder; use bare "localcloud" when launching from a terminal shell with PATH configured).
For clients that speak HTTP directly, use http://127.0.0.1:5380/mcp together with X-LocalCloud-Project and X-LocalCloud-User headers.
Sample data is owned by container startup and the Console Re-seed Data action.
The CLI does not discover, mount, or apply seed files. Existing host.seed
settings are ignored; use server.auto_seed: false to disable container bootstrap.
Managed containers with an old CLI seed mount are recreated on start/restart
with their existing data volume preserved.
Everything above works with zero configuration. When you want a versioned, shared setup, drop a
localcloud.yaml beside your project:
version: 1
context:
project: payments-dev
user: local-developer
host:
data_volume: payments-data
memory: 8g
data: persistent
docker_socket: auto
services:
enabled:
- gcs
- pubsub
- bigquery
- firestoreThe file is a recursive partial overlay on the packaged defaults: omitted values inherit, and a mapping
member set to null is deleted. The CLI resolves it in this order:
- an explicit positional path —
lc start ./custom.yaml LOCALCLOUD_CONFIG./localcloud.yaml- the runtime's remembered config
~/.local/share/localcloud/localcloud.yaml, or$LOCALCLOUD_HOME/localcloud.yamlwhenLOCALCLOUD_HOMEis set- built-in defaults
An explicit, environment, or remembered path that is missing or unreadable fails rather than silently
falling back. CLI flags override the corresponding host values.
server and services.catalog settings, such as server.allowed_origins for a LAN dev app or
per-service retention limits (everything is kept by default), pass through to LocalCloud, which refuses
any key it does not know. See Gateway settings, which also lists
retired keys to remove from older files.
The image comes from --image/--lite/--full, then host.image, then LOCALCLOUD_IMAGE, then the
image the data volume last ran, then agentcloud/localcloud:lite
(details).
host.docker_socket: auto (the default) mounts the host Docker socket only when an enabled service needs
it — Compute Engine, Cloud Run, GKE, or Dataproc. Set true to always mount it, or false as a hard
opt-out.
start, restart, reset, and stop send anonymous startup-error and hourly usage events. Set
LOCALCLOUD_TELEMETRY=false or DO_NOT_TRACK=1 to turn them off; see
Telemetry for exactly what is sent.
→ Full configuration reference
| Symptom | What it means | Fix |
|---|---|---|
Error [docker_unavailable] |
Docker is not installed, not running, unreachable, or denies access (details.reason) |
Follow the message; lc doctor --fix installs Colima or starts your Docker app |
Error [fix_confirmation_required] |
lc doctor --fix ran without a terminal (or with --verbose) |
Run it in an interactive terminal; it asks before each fix |
BigQuery or another service stops soon after start on Apple Silicon |
The Docker VM runs on QEMU | lc doctor, then lc doctor --fix to switch to VZ with Rosetta |
Error [docker_socket_unavailable] |
A service needs the Docker socket but it is missing or blocked | Check the socket path, or set host.docker_socket: false to disable Docker-backed services |
Error [health_timeout] / runtime_readiness_timeout |
The container started but services were not ready in time | lc logs --tail 200; confirm at least 4 GiB is available, or raise it with --memory 8g |
Error [services_not_ready] |
The gateway is up, but the services the error names were still warming up at the deadline, or /readiness gave no answer (the error says why). The runtime keeps running, so status, logs and stop find it |
lc logs --tail 200 for those services; leave them out with --services if you don't need them |
Warning: <Service> is not available (…) |
The runtime reports that service as failed for good (for example engine_port_unpublished); the other services run |
Follow the remedy in the warning; lc status repeats it |
Warning: The Cloud SQL MySQL companion '…' could not start |
Its host port (5406 by default) is held by another container or process |
Free the port, or pin another with host.environment.LOCALCLOUD_MYSQL_PORT |
Error [port_mapping_confirmation_required] |
Canonical ports are busy and the shell is non-interactive; the message names each busy port's container or process when it can tell | Free the ports, or re-run with --accept-dynamic-ports |
Error [data_volume_collision] |
More than one compatible container uses the same volume | lc cleanup --dry-run to inspect, then lc cleanup |
Error [ownership_mismatch] / ownership_forbidden |
A Docker resource is not CLI-managed | The CLI never removes resources it does not own — remove it manually, or use a different --data-volume |
Error [unknown_project] |
The project does not exist in this runtime | Only start creates projects: lc start --project-id NAME |
Error [mcp_connection_timeout] |
The /mcp endpoint was not ready in 10 s |
lc status to confirm the runtime is up, then lc mcp --connect-timeout 30 |
A failed start or restart error carries rolled_back_to_image |
The newer image could not start on the existing data, so the runtime was recreated on its previous image | lc logs --tail 200; stay on the previous image, or pass --image to choose one |
Image update line after start/restart |
A newer version of the runtime's pinned image exists; non-interactive runs only report it | Run the command it names, answer the prompt in a terminal, or set LOCALCLOUD_IMAGE_UPDATE_CHECK=false |
Error [dry_run_pull_conflict] |
--dry-run was combined with --pull |
Previews are strictly read-only — use --dry-run --no-pull, with the image already present locally |
Error [removed_flat_config] |
localcloud.yaml uses a pre-1.0 flat key |
The message names the replacement path — see configuration |
| Stale containers, networks, or locks | Interrupted runs left resources behind | lc cleanup --dry-run, then lc cleanup |
Still stuck? lc doctor --verbose and lc status --verbose produce the complete machine-readable state,
and --debug prints the exact docker run the CLI would use.
| Guide | Contents |
|---|---|
| CLI reference | Every command, flag, output mode, and field path |
| Configuration | localcloud.yaml, service catalog, volumes, projects, identity |
| Integrations | Python, Node, Go, Terraform/OpenTofu, and MCP client setup |
| MCP guide & architecture | Auto-start, project isolation, tool catalog, and client installers |
| MCP local setup guide | Claude, Codex, Cursor and other clients: install, plugins, connection checks, first prompt |
| MCP privacy | What the CLI and plugin handle, telemetry, and outbound traffic |
| MCP reproducible workflows | Step-by-step agent test scenarios for Storage, Pub/Sub, BigQuery |
| MCP listings and submissions | Marketplace, directory, awesome-list, and announcement links; status and follow-up |
| Lifecycle testing | End-to-end container lifecycle test runbook and verification |
| Performance benchmarks | Empirical latency and load benchmarks for container lifecycle, MCP bridge, and emulated GCP services |
| local.cloud/docs | Product documentation, service compatibility, and the console |
LocalCloud CLI targets Python 3.11+ and uses uv.
uv sync --extra test # install dependencies
uv run --extra test python -m pytest -q # full suite
uv run --extra test python -m pytest -q -m "not docker" # no Docker required
uv run lc --help # run from sourceFor live container lifecycle qualification, follow the Lifecycle test runbook.
Tests that need a live Docker engine are marked docker; deselect them with -m "not docker".
lc env --identity consumes LocalCloud's typed identity session contract. The fixtures in
tests/fixtures/identity/ are validated against the contract vendored in
tests/fixtures/identity/localcloud-contract.json, which records the LocalCloud revision it came
from; refresh it with python3 scripts/sync-identity-contract.py --localcloud <checkout>, and set
LOCALCLOUD_SOURCE=<checkout> to also check it against that checkout. The end-to-end session test
runs a real lc start and lc env --identity against an image (on Colima, use a --basetemp
under your home directory so that Docker can bind-mount the configuration):
LOCALCLOUD_RUN_IDENTITY_E2E=1 LOCALCLOUD_IMAGE=localcloud:<tag> \
uv run --frozen --extra test python -m pytest -m docker \
tests/integration/test_identity_session_acceptance.pyLocalCloud is proprietary software governed by the LocalCloud Public Preview License. LocalCloud MCP is free for the documented local development workflows.
- Website — local.cloud
- Documentation — local.cloud/docs
- Support — open an issue on GitHub, or email [email protected]
