GCP CLI & SDK Setup
floci-gcp accepts all requests unconditionally — no real GCP credentials are needed. GCP SDKs automatically skip credential validation when *_EMULATOR_HOST environment variables are set.
Environment Variables
Set these in your shell before running any GCP SDK or CLI code:
export PUBSUB_EMULATOR_HOST=localhost:4578
export FIRESTORE_EMULATOR_HOST=localhost:4578
export DATASTORE_EMULATOR_HOST=localhost:4578
export STORAGE_EMULATOR_HOST=http://localhost:4578
export SECRET_MANAGER_EMULATOR_HOST=localhost:4578
Add them to your shell profile (.bashrc / .zshrc) to persist across sessions.
gcloud CLI
# Set default project (no real GCP project required)
gcloud config set project floci-local
# Pub/Sub
gcloud pubsub topics create my-topic
gcloud pubsub subscriptions create my-sub --topic=my-topic
gcloud pubsub topics publish my-topic --message="hello"
gcloud pubsub subscriptions pull my-sub --auto-ack
# Cloud Storage
gcloud storage buckets create gs://my-bucket
echo "hello" | gcloud storage cp - gs://my-bucket/hello.txt
gcloud storage ls gs://my-bucket
SDK Configuration
Java (GCP SDK for Java)
// Pub/Sub
ManagedChannel channel = ManagedChannelBuilder
.forTarget("localhost:4578")
.usePlaintext()
.build();
CredentialsProvider noCredentials = NoCredentialsProvider.create();
TopicAdminClient topicClient = TopicAdminClient.create(
TopicAdminSettings.newBuilder()
.setTransportChannelProvider(
FixedTransportChannelProvider.create(GrpcTransportChannel.create(channel)))
.setCredentialsProvider(noCredentials)
.build());
SubscriberStubSettings subscriberSettings = SubscriberStubSettings.newBuilder()
.setTransportChannelProvider(
FixedTransportChannelProvider.create(GrpcTransportChannel.create(channel)))
.setCredentialsProvider(noCredentials)
.build();
// Cloud Storage
Storage storage = StorageOptions.newBuilder()
.setHost("http://localhost:4578")
.setProjectId("floci-local")
.setCredentials(NoCredentials.getInstance())
.build()
.getService();
storage.create(BucketInfo.of("my-bucket"));
storage.create(BlobInfo.newBuilder("my-bucket", "hello.txt").build(),
"hello from floci-gcp".getBytes());
// Firestore
FirestoreOptions options = FirestoreOptions.newBuilder()
.setHost("localhost:4578")
.setProjectId("floci-local")
.setCredentials(NoCredentials.getInstance())
.build();
Firestore db = options.getService();
db.collection("users").add(Map.of("name", "Alice")).get();
// Datastore
DatastoreOptions options = DatastoreOptions.newBuilder()
.setHost("http://localhost:4578")
.setProjectId("floci-local")
.setCredentials(NoCredentials.getInstance())
.build();
Datastore datastore = options.getService();
// Secret Manager
SecretManagerServiceClient client = SecretManagerServiceClient.create(
SecretManagerServiceSettings.newBuilder()
.setTransportChannelProvider(
FixedTransportChannelProvider.create(GrpcTransportChannel.create(channel)))
.setCredentialsProvider(noCredentials)
.build());
Python (google-cloud)
import os
# Pub/Sub
os.environ["PUBSUB_EMULATOR_HOST"] = "localhost:4578"
from google.cloud import pubsub_v1
publisher = pubsub_v1.PublisherClient()
topic_path = publisher.topic_path("floci-local", "my-topic")
publisher.create_topic(request={"name": topic_path})
future = publisher.publish(topic_path, b"hello from floci-gcp")
future.result()
# Firestore
import os
os.environ["FIRESTORE_EMULATOR_HOST"] = "localhost:4578"
from google.cloud import firestore
db = firestore.Client(project="floci-local")
db.collection("users").add({"name": "Alice", "age": 30})
docs = db.collection("users").stream()
for doc in docs:
print(doc.to_dict())
# Cloud Storage
import os
os.environ["STORAGE_EMULATOR_HOST"] = "http://localhost:4578"
from google.cloud import storage
client = storage.Client(project="floci-local")
bucket = client.bucket("my-bucket")
client.create_bucket(bucket)
blob = bucket.blob("hello.txt")
blob.upload_from_string("hello from floci-gcp")
Node.js
// Pub/Sub
process.env.PUBSUB_EMULATOR_HOST = "localhost:4578";
import { PubSub } from "@google-cloud/pubsub";
const pubsub = new PubSub({ projectId: "floci-local" });
await pubsub.createTopic("my-topic");
const [subscription] = await pubsub.topic("my-topic")
.createSubscription("my-sub");
const [messages] = await subscription.pull({ maxMessages: 1 });
console.log(messages);
Project ID
floci-gcp uses project ID floci-local as the default project when none is specified. Resources created in one project are fully isolated from another.
Change the default with FLOCI_GCP_DEFAULT_PROJECT_ID:
See Multi-Project Isolation for full details.