
Cloud Create Project
- 2.1k installs
- 546 repo stars
- Updated July 22, 2026
- elastic/agent-skills
Elastic Serverless project creation.
About
The cloud-create-project skill creates Elastic Cloud Serverless projects using Serverless REST API deferring day-2 to cloud-manage-project. Requires EC_API_KEY with Admin or Organization owner role attempting operation letting API enforce 403 on insufficient permissions. Manual setup documents EC_API_KEY EC_BASE_URL in dotenv without chat secrets. Prerequisites cloud-setup skill for credential configuration. Use provisioning new serverless Elasticsearch projects after cloud environment setup validated. Create Serverless projects via REST API. Requires EC_API_KEY Admin or Org owner. Day-2 ops use cloud-manage-project skill. dotenv secrets not chat pasted keys. cloud-setup prerequisite for credentials. Elastic Serverless project creation. User create Elastic serverless project.
- Create Serverless projects via REST API.
- Requires EC_API_KEY Admin or Org owner.
- Day-2 ops use cloud-manage-project skill.
- dotenv secrets not chat pasted keys.
- cloud-setup prerequisite for credentials.
Cloud Create Project by the numbers
- 2,077 all-time installs (skills.sh)
- +162 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #184 of 1,039 Cloud & Infrastructure skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Aug 4, 2026 (Skillselion catalog sync)
cloud-create-project capabilities & compatibility
- Capabilities
- project creation · api provisioning
- Use cases
- devops
npx skills add https://github.com/elastic/agent-skills --skill cloud-create-projectAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2.1k |
|---|---|
| repo stars | ★ 546 |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 22, 2026 |
| Repository | elastic/agent-skills ↗ |
Create new serverless project?
Create Elastic Cloud Serverless projects via REST API with EC_API_KEY Admin or Org owner role.
Who is it for?
Teams provisioning Elastic Serverless.
Skip if: Self-managed cluster install.
When should I use this skill?
User create Elastic serverless project.
What you get
Provisioned Serverless project via API.
- Serverless project instances
- API configuration records
By the numbers
- Base API host documented as https://api.elastic-cloud.com
- Project endpoints use the /api/v1/serverless/projects/{type} path pattern
Files
Create Serverless Project
Create Elastic Cloud Serverless projects using the Serverless REST API. Use the cloud-manage-project skill for day-2 operations like listing, updating, or deleting projects.
Prerequisites and permissions
- Ensure
EC_API_KEYis configured. If not, runcloud-setupskill first. - Creating projects requires a Cloud API key with Admin or Organization owner role.
- This skill does not perform a separate role pre-check. Attempt the requested operation and let the API enforce
authorization. If the API returns an authorization error (for example, 403 Forbidden), stop and ask the user to verify the provided API key permissions.
Manual setup fallback (when cloud-setup is unavailable)
If this skill is installed standalone and cloud-setup is not available, instruct the user to configure Cloud environment variables manually before running commands. Never ask the user to paste API keys in chat.
| Variable | Required | Description |
|---|---|---|
EC_API_KEY | Yes | Elastic Cloud API key used for project creation operations. |
EC_BASE_URL | No | Cloud API base URL (default: https://api.elastic-cloud.com). |
Note: If EC_API_KEY is missing, or the user does not have a Cloud API key yet, first check whether the user hasan Elastic Cloud account. If not, propose starting a free trial at
Elastic Cloud free trial — 14 days of full access with no credit card
required. Once registered, direct the user to generate a key at
Elastic Cloud API keys, then configure it locally using the steps below.
Preferred method (agent-friendly): create a .env file in the project root:
EC_API_KEY=your-api-key
EC_BASE_URL=https://api.elastic-cloud.comAll cloud/* scripts auto-load .env from the working directory.
Alternative: export directly in the terminal:
export EC_API_KEY="<your-cloud-api-key>"
export EC_BASE_URL="https://api.elastic-cloud.com"Terminal exports may not be visible to sandboxed agents running in separate shell sessions, so prefer .env when using an agent.
Critical principles
- Never display secrets in chat. Do not echo, log, or repeat API keys, passwords, or credentials in conversation
messages or agent thinking. Direct the user to the .elastic-credentials file instead. The admin password must never appear in chat history, thinking traces, or agent output.
- Confirm before creating. Always present the project configuration to the user and ask for confirmation before
running the creation script.
- Admin credentials are for API key creation only. The script saves the
adminpassword to.elastic-credentials
for bootstrapping a scoped API key. The admin user has full privileges and cannot be modified in serverless. Never use admin credentials for direct Elasticsearch operations (querying, indexing, etc.) — always create a scoped API key first (see Step 8). The load-credentials command excludes admin credentials by default — use --include-admin only during Step 7/8, then reload without it once the API key is created. Never read or display the contents of .elastic-credentials in chat.
- Recover lost credentials. If the script fails to write
.elastic-credentials(disk full, permissions, etc.), the
save may be incomplete. Check .elastic-credentials for the password first. If missing, use the cloud-manage-project skill's reset-credentials command to generate a new password.
- Region is permanent. A project's region cannot be changed after creation.
- Prefer automatic readiness checks. Pass
--waitto the creation script so it polls until the phase changes from
initializing to initialized. Only fall back to manually polling the status endpoint if --wait is unavailable.
Project types
| Type | Description | Key endpoints |
|---|---|---|
elasticsearch | Search, analytics, and vector workloads | Elasticsearch, Kibana |
observability | Logs, metrics, traces, and APM | Elasticsearch, Kibana, APM, OTLP |
security | SIEM, endpoint protection, cloud security | Elasticsearch, Kibana, OTLP |
Project type inference
Map the user's request to the correct --type value:
| User says | --type |
|---|---|
| "search project", "elasticsearch project", vector search | elasticsearch |
| "observability project", "o11y", logs, metrics, traces, APM | observability |
| "security project", "SIEM", detections, endpoint protection | security |
Do not silently default to any type. If the user does not specify a type, infer it from the conversation context (for example, discussing log ingestion suggests observability, discussing detections or SIEM suggests security, discussing search or vector workloads suggests elasticsearch). Always present the inferred type to the user and ask for confirmation before proceeding. If context is insufficient to infer a type, ask the user to choose.
Product tiers
Observability and security projects support a --product-tier flag. Default to complete unless the user explicitly requests a different tier.
| Project type | Tier | Description |
|---|---|---|
observability | complete | Full observability suite (logs, metrics, traces, APM) |
observability | logs_essentials | Log management only |
security | complete | Full security suite (SIEM, cloud, endpoint) |
security | essentials | Core SIEM only |
Elasticsearch projects do not have a product tier — use --optimized-for instead.
Sensible defaults
Present these defaults to the user before creation. Ask if they want to use or change them:
| Setting | Default |
|---|---|
| Region | gcp-us-central1 |
Project type must be confirmed with the user — do not assume a default. See "Project type inference" above.
Always use --optimized-for general_purpose unless the user explicitly requests vector. Do not proactively offer the vector option.
If the user does not specify a name, ask for one — it is required.
Workflow: Create a project
Project Creation:
- [ ] Step 1: Verify API key is set
- [ ] Step 2: Present defaults and confirm with user
- [ ] Step 3: List available regions (optional)
- [ ] Step 4: Create the project
- [ ] Step 5: Save credentials and endpoints
- [ ] Step 6: Wait for project to initialize
- [ ] Step 7: Set environment variables
- [ ] Step 8: Recommend creating a scoped API keyStep 1: Verify API key is set
echo "${EC_API_KEY:?Not set}"If EC_API_KEY is not set, run the cloud-setup skill first to configure authentication and defaults.
Step 2: Present summary and confirm with user
Before presenting the summary, ensure the project type has been explicitly confirmed by the user. If no type was specified, infer one from the conversation context and propose it. If the context is ambiguous, ask the user to choose from elasticsearch, observability, or security.
Always show a confirmation summary before creating. Include different fields depending on project type:
Elasticsearch project:
Project Summary:
Type: elasticsearch
Name: my-project
Region: gcp-us-central1Observability project:
Project Summary:
Type: observability
Name: my-project
Region: gcp-us-central1
Product tier: completeSecurity project:
Project Summary:
Type: security
Name: my-project
Region: gcp-us-central1
Product tier: completeAsk the user to confirm or override any values before proceeding.
Step 3: List available regions (optional)
python3 skills/cloud/create-project/scripts/create-project.py list-regionsThe output is grouped by cloud provider (AWS, Azure, GCP) and sorted alphabetically. Regions marked with * do not support project creation.
Step 4: Create the project
python3 skills/cloud/create-project/scripts/create-project.py create \
--type elasticsearch \
--name "my-project" \
--region gcp-us-central1 \
--optimized-for general_purpose \
--waitAlways pass --optimized-for general_purpose for Elasticsearch projects. Only use vector if the user explicitly requests it.
For observability and security projects, pass --product-tier complete unless the user explicitly requests a different tier.
Always pass --wait so the script automatically polls until the project is ready.
Step 5: Save credentials and endpoints
The script automatically writes credentials to .elastic-credentials in the working directory. The password is redacted from the JSON output on stdout.
If saving succeeds, tell the user:
Credentials saved to .elastic-credentials — open that file to retrieve your password.Do not read, cat, or display the contents of .elastic-credentials in chat.
If saving fails, the script prints an error to stderr. Check whether .elastic-credentials exists and contains a password (a partial write is possible). If the password is missing or the file does not exist, immediately run the cloud-manage-project skill's reset-credentials command to generate a new password.
The creation response also contains:
- Project ID — needed for all subsequent operations
- Cloud ID — for client libraries
- Elasticsearch and Kibana endpoints — safe to display in chat
The admin credentials are for initial bootstrap only. Recommend creating a scoped API key for ongoing access (Step 8).
Step 6: Wait for project to initialize
When --wait is passed (recommended), the script polls automatically until the project phase becomes initialized. No manual polling is needed.
If the agent ran without --wait, poll manually:
python3 skills/cloud/create-project/scripts/create-project.py status \
--type elasticsearch \
--id <project-id>Repeat until phase changes from initializing to initialized.
Step 7: Set environment variables
The creation script saves credentials and endpoints to .elastic-credentials with the project name in the header. Load them into the current shell with `--include-admin` so admin credentials are available for API key creation in Step 8:
eval $(python3 skills/cloud/manage-project/scripts/manage-project.py load-credentials \
--name "<project-name>" --include-admin)This sets ELASTICSEARCH_URL, KIBANA_URL, any project-type specific endpoints (APM_URL, INGEST_URL), and the admin ELASTICSEARCH_USERNAME/ELASTICSEARCH_PASSWORD needed to bootstrap an API key.
Step 8: Create a scoped API key
The admin user has full privileges and cannot be modified in serverless projects. Do not proceed with Elasticsearch operations using admin credentials. Create a scoped Elasticsearch API key with only the permissions the user needs.
If the elasticsearch-authn skill is available, use it for API key creation — it covers the full lifecycle (create, grant, invalidate, query) and handles scoping privileges correctly. If the skill is not installed, ask the user to either install it or create the API key manually through Kibana > Stack Management > API keys. After creation, save the API key to .elastic-credentials using the project-specific header format (see manage-project skill's "Credential file format" section), then reload without `--include-admin` to drop admin credentials from the environment:
eval $(python3 skills/cloud/manage-project/scripts/manage-project.py load-credentials \
--name "<project-name>")Examples
Create an Elasticsearch project with defaults
python3 skills/cloud/create-project/scripts/create-project.py create \
--type elasticsearch \
--name "my-search-project" \
--region gcp-us-central1 \
--optimized-for general_purpose \
--waitCreate an observability project
python3 skills/cloud/create-project/scripts/create-project.py create \
--type observability \
--name "prod-o11y" \
--region aws-eu-west-1 \
--product-tier complete \
--waitCreate a security project
python3 skills/cloud/create-project/scripts/create-project.py create \
--type security \
--name "siem-prod" \
--region gcp-us-central1 \
--product-tier complete \
--waitGuidelines
- Run the
cloud-setupskill first ifEC_API_KEYis not set. - Always confirm the project configuration with the user before creating.
- Never display passwords or API keys in chat. Direct the user to
.elastic-credentials. - Never silently default to a project type. Infer from context and confirm with the user.
- Default to
general_purposeoptimization. Only usevectorif the user explicitly requests it. - Default to
completeproduct tier for observability and security projects. Only uselogs_essentialsoressentials
if the user explicitly requests it.
- Always pass
--waitso the script polls until the project is ready. - If credential saving fails, immediately reset credentials using the
cloud-manage-projectskill. - After creation, recommend creating a scoped API key instead of relying on admin credentials.
- Region cannot be changed after creation — confirm the choice before proceeding.
Script reference
| Command | Description |
|---|---|
create | Create a new serverless project |
status | Get project initialization status |
list-regions | List available regions |
| Flag | Commands | Description |
|---|---|---|
--type | create, status | Project type: elasticsearch, observability, security |
--name | create | Project name (required) |
--region | create | Region ID (default: gcp-us-central1) |
--id | status | Project ID |
--optimized-for | create | Elasticsearch subtype: general_purpose or vector |
--product-tier | create | Observability/security tier (see "Product tiers" section) |
--wait | create | Poll until project is initialized before exiting |
Environment variables
| Variable | Required | Description |
|---|---|---|
EC_API_KEY | Yes | Elastic Cloud API key |
EC_BASE_URL | No | Cloud API base URL (default: https://api.elastic-cloud.com) |
ELASTICSEARCH_URL | Output | Elasticsearch URL (loaded via load-credentials after creation) |
KIBANA_URL | Output | Kibana URL (loaded via load-credentials after creation) |
APM_URL | Output | APM endpoint (observability projects only) |
INGEST_URL | Output | OTLP ingest endpoint (observability and security projects) |
ELASTICSEARCH_API_KEY | Output | Elasticsearch API key (created in Step 8, loaded via load-credentials) |
Additional resources
- For full API details, request/response schemas, and project-type options, see
references/api-reference.md
Elastic Cloud Serverless API Reference
Reference for the Elastic Cloud Serverless project management API. Base URL: https://api.elastic-cloud.com.
All requests require an API key in the Authorization header:
Authorization: ApiKey <your-api-key>Endpoints
Projects
| Method | Path | Description |
|---|---|---|
POST | /api/v1/serverless/projects/{type} | Create a project |
GET | /api/v1/serverless/projects/{type} | List projects |
GET | /api/v1/serverless/projects/{type}/{id} | Get project details |
PATCH | /api/v1/serverless/projects/{type}/{id} | Update a project |
DELETE | /api/v1/serverless/projects/{type}/{id} | Delete a project |
GET | /api/v1/serverless/projects/{type}/{id}/status | Get project status |
POST | /api/v1/serverless/projects/{type}/{id}/_reset-credentials | Reset credentials |
POST | /api/v1/serverless/projects/{type}/{id}/_resume | Resume suspended project |
GET | /api/v1/serverless/projects/{type}/{id}/roles | Get project roles |
Where {type} is one of: elasticsearch, observability, security.
Regions
| Method | Path | Description |
|---|---|---|
GET | /api/v1/serverless/regions | List all regions |
GET | /api/v1/serverless/regions/{id} | Get region details |
Traffic Filters
| Method | Path | Description |
|---|---|---|
POST | /api/v1/serverless/traffic-filters | Create a traffic filter |
GET | /api/v1/serverless/traffic-filters | List traffic filters |
GET | /api/v1/serverless/traffic-filters/{id} | Get a traffic filter |
PATCH | /api/v1/serverless/traffic-filters/{id} | Update a traffic filter |
DELETE | /api/v1/serverless/traffic-filters/{id} | Delete a traffic filter |
Create project request bodies
Elasticsearch
{
"name": "my-es-project",
"region_id": "gcp-us-central1",
"optimized_for": "general_purpose",
"search_lake": {
"search_power": 100,
"boost_window": 30
}
}| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Project name (1–255 chars) |
region_id | string | Yes | Region ID (for example, gcp-us-central1) |
alias | string | No | Custom domain label (RFC-1035, max 50 chars) |
optimized_for | string | No | general_purpose (default) or vector |
search_lake | object | No | Search power (28–3000) and boost window (1–180 days) |
optimized_for options:
general_purpose— suitable for full-text search, sparse vectors, compressed dense vectors. Default when creating
from the UI.
vector— for uncompressed dense vectors with high dimensionality. Impacts VCU consumption.
Observability
{
"name": "my-obs-project",
"region_id": "gcp-us-central1",
"product_tier": "complete"
}| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Project name |
region_id | string | Yes | Region ID |
alias | string | No | Custom domain label |
product_tier | string | No | complete (default) or logs_essentials |
Security
{
"name": "my-sec-project",
"region_id": "gcp-us-central1",
"product_types": [
{ "product_line": "security", "product_tier": "complete" },
{ "product_line": "cloud", "product_tier": "complete" },
{ "product_line": "endpoint", "product_tier": "complete" }
]
}| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Project name |
region_id | string | Yes | Region ID |
alias | string | No | Custom domain label |
admin_features_package | string | No | standard or enterprise (BYOK, BYOIDP, CCS, CCR) |
product_types | array | No | Array of product line/tier pairs |
search_lake | object | No | Data retention config |
Product lines: security, cloud, endpoint. Product tiers: complete, essentials.
Creation response
All project types return the same response structure:
{
"id": "abc123def456abc123def456abc12345",
"name": "my-project",
"alias": "my-project-bdc0f7",
"region_id": "gcp-us-central1",
"cloud_id": "bXktcHJvamVjdDo...",
"type": "elasticsearch",
"metadata": {
"created_at": "2025-01-15T10:30:00Z",
"created_by": "1014289666002276",
"organization_id": "198583657190"
},
"endpoints": {
"elasticsearch": "https://my-project-bdc0f7.es.us-east-1.aws.elastic.cloud",
"kibana": "https://my-project-bdc0f7.kb.us-east-1.aws.elastic.cloud"
},
"credentials": {
"username": "admin",
"password": "REDACTED"
}
}Observability projects also include apm and ingest endpoints. Security projects include an ingest endpoint.
The credentials block is only returned on creation and reset. Save the password immediately.
Project status
{
"phase": "initializing"
}Phases:
| Phase | Description |
|---|---|
initializing | Project is being created, not ready yet |
initialized | Project is ready for use |
suspending | Project is being suspended |
suspended | Project is suspended (trial expired) |
deleting | Project is being deleted |
deleted | Project has been deleted (terminal state) |
Regions
Common regions for serverless projects:
AWS
| Region ID | Location |
|---|---|
aws-us-east-1 | N. Virginia, US |
aws-us-east-2 | Ohio, US |
aws-us-west-2 | Oregon, US |
aws-eu-west-1 | Ireland |
aws-eu-central-1 | Frankfurt |
GCP
| Region ID | Location |
|---|---|
gcp-us-central1 | Iowa, US |
gcp-europe-west1 | Belgium |
Azure
| Region ID | Location |
|---|---|
azure-eastus | Virginia, US |
Use GET /api/v1/serverless/regions for the complete, up-to-date list. Only regions with project_creation_enabled: true accept new projects.
Error responses
All errors follow this format:
{
"errors": [
{
"message": "Explanatory error message",
"code": "code.error"
}
]
}| HTTP Code | Meaning |
|---|---|
| 400 | Bad request |
| 401 | Invalid API key |
| 404 | Project not found |
| 409 | Conflict |
| 412 | Precondition failed |
| 422 | Unprocessable entity |
Traffic filters
Traffic filters restrict network access to projects. Attach them during creation or using PATCH:
{
"traffic_filters": [{ "id": "traffic-filter-id" }]
}Filter types: ip (IP/CIDR rules) or vpce (VPC endpoint IDs).
#!/usr/bin/env python3
"""Create Elastic Cloud Serverless projects via the Serverless REST API.
Usage:
python3 create-project.py <command> [options]
Commands:
create Create a new serverless project
status Get project initialization status
list-regions List available regions
Requires EC_API_KEY environment variable.
"""
import argparse
import copy
import json
import os
import sys
import time
import urllib.error
import urllib.request
from datetime import datetime, timezone
def load_dotenv(path=".env"):
"""Load KEY=VALUE pairs from a .env file into os.environ (no overwrite)."""
try:
with open(path) as f:
for line in f:
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, _, value = line.partition("=")
os.environ.setdefault(key.strip(), value.strip().strip("'\""))
except FileNotFoundError:
pass
load_dotenv()
BASE_URL = os.environ.get("EC_BASE_URL", "https://api.elastic-cloud.com")
API_PREFIX = "/api/v1/serverless"
VALID_TYPES = ("elasticsearch", "observability", "security")
DEFAULT_REGION = "gcp-us-central1"
def get_api_key():
key = os.environ.get("EC_API_KEY")
if not key:
print("Error: EC_API_KEY environment variable is not set.", file=sys.stderr)
print("Run the cloud-setup skill to configure authentication.", file=sys.stderr)
sys.exit(1)
return key
def api_request(method, path, body=None):
url = f"{BASE_URL}{API_PREFIX}{path}"
headers = {
"Authorization": f"ApiKey {get_api_key()}",
"Content-Type": "application/json",
"User-Agent": "elastic-agentic",
}
data = json.dumps(body).encode() if body else None
req = urllib.request.Request(url, data=data, headers=headers, method=method)
try:
with urllib.request.urlopen(req, timeout=30) as resp:
raw = resp.read().decode()
return json.loads(raw) if raw else {}
except urllib.error.HTTPError as e:
error_body = e.read().decode()
try:
error_json = json.loads(error_body)
print(json.dumps(error_json, indent=2), file=sys.stderr)
except json.JSONDecodeError:
print(error_body, file=sys.stderr)
print(f"\nHTTP {e.code}: {e.reason}", file=sys.stderr)
sys.exit(1)
except urllib.error.URLError as e:
print(f"Error: unable to reach {url}: {e.reason}", file=sys.stderr)
sys.exit(1)
def save_credentials(project_id, project_name, credentials, endpoints):
"""Append credentials to .elastic-credentials in the working directory."""
creds_file = os.path.join(os.getcwd(), ".elastic-credentials")
timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
fd = os.open(creds_file, os.O_WRONLY | os.O_CREAT | os.O_APPEND, 0o600)
os.fchmod(fd, 0o600)
with os.fdopen(fd, "a") as f:
f.write(f"# Project: {project_name} | id={project_id} | {timestamp}\n")
for name, url in endpoints.items():
env_name = name.upper().replace("-", "_") + "_URL"
f.write(f"{env_name}={url}\n")
f.write(f"ELASTICSEARCH_USERNAME={credentials.get('username', '')}\n")
f.write(f"ELASTICSEARCH_PASSWORD={credentials.get('password', '')}\n\n")
return creds_file
def wait_for_ready(project_type, project_id, timeout=300, interval=5):
"""Poll project status until initialized or timeout."""
elapsed = 0
while elapsed < timeout:
result = api_request("GET", f"/projects/{project_type}/{project_id}/status")
phase = result.get("phase", "unknown")
print(f"Status: {phase} ({elapsed}s elapsed)", file=sys.stderr)
if phase == "initialized":
print("Project is ready.", file=sys.stderr)
return result
time.sleep(interval)
elapsed += interval
print(
f"ERROR: Project did not initialize within {timeout}s. "
f"Check status manually with the status command.",
file=sys.stderr,
)
sys.exit(1)
SECURITY_PRODUCT_LINES = ("security", "cloud", "endpoint")
def cmd_create(args):
body = {"name": args.name, "region_id": args.region}
if args.type == "elasticsearch":
body["optimized_for"] = args.optimized_for or "general_purpose"
elif args.type == "observability" and args.product_tier:
body["product_tier"] = args.product_tier
elif args.type == "security" and args.product_tier:
body["product_types"] = [
{"product_line": line, "product_tier": args.product_tier}
for line in SECURITY_PRODUCT_LINES
]
result = api_request("POST", f"/projects/{args.type}", body)
project_id = result.get("id", "")
credentials = result.get("credentials", {})
endpoints = result.get("endpoints", {})
try:
creds_file = save_credentials(project_id, args.name, credentials, endpoints)
except OSError as exc:
print(
f"ERROR: Failed to save credentials to .elastic-credentials: {exc}",
file=sys.stderr,
)
print(
"Credential save may be incomplete. Check .elastic-credentials for the "
"password. If missing, use cloud-manage-project reset-credentials.",
file=sys.stderr,
)
creds_file = None
redacted = copy.deepcopy(result)
if "credentials" in redacted:
if creds_file:
redacted["credentials"]["password"] = "REDACTED — see .elastic-credentials"
else:
redacted["credentials"]["password"] = (
"LOST — credential save failed, reset with cloud-manage-project reset-credentials"
)
print(json.dumps(redacted, indent=2))
print("\n--- Project Created ---", file=sys.stderr)
print(f"Project ID: {project_id}", file=sys.stderr)
print(f"Cloud ID: {result.get('cloud_id', 'N/A')}", file=sys.stderr)
for name, url in endpoints.items():
print(f"Endpoint ({name}): {url}", file=sys.stderr)
if creds_file:
print(f"\nCredentials saved to {creds_file} — do not display in chat.", file=sys.stderr)
else:
print(
"\nWARNING: Credentials were NOT saved. Reset them with "
"cloud-manage-project reset-credentials.",
file=sys.stderr,
)
if args.wait:
print("\nWaiting for project to initialize...", file=sys.stderr)
wait_for_ready(args.type, project_id)
def cmd_status(args):
result = api_request("GET", f"/projects/{args.type}/{args.id}/status")
print(json.dumps(result, indent=2))
phase = result.get("phase", "unknown")
print(f"\nPhase: {phase}", file=sys.stderr)
if phase == "initialized":
print("Project is ready.", file=sys.stderr)
elif phase == "initializing":
print("Project is still initializing. Poll again in a few seconds.", file=sys.stderr)
def cmd_list_regions(_args):
result = api_request("GET", "/regions")
if isinstance(result, list):
regions = result
else:
regions = result.get("items", result.get("regions", []))
by_csp = {}
for r in regions:
csp = r.get("csp", "unknown")
by_csp.setdefault(csp, []).append(r)
for csp in sorted(by_csp):
print(f"--- {csp.upper()} ---")
for r in sorted(by_csp[csp], key=lambda x: x.get("id", "")):
enabled = r.get("project_creation_enabled", False)
marker = " " if enabled else "* "
print(f"{marker}{r['id']:30s} {r.get('name', '')}")
print()
if regions:
print("* = project creation not available in this region", file=sys.stderr)
def main():
parser = argparse.ArgumentParser(
description="Create Elastic Cloud Serverless projects"
)
subparsers = parser.add_subparsers(dest="command", required=True)
p_create = subparsers.add_parser("create", help="Create a serverless project")
p_create.add_argument("--type", required=True, choices=VALID_TYPES)
p_create.add_argument("--name", required=True, help="Project name")
p_create.add_argument("--region", default=DEFAULT_REGION, help="Region ID")
p_create.add_argument(
"--optimized-for",
choices=["general_purpose", "vector"],
help="Elasticsearch project subtype",
)
p_create.add_argument(
"--product-tier",
choices=["complete", "logs_essentials", "essentials"],
help="Product tier for observability or security projects",
)
p_create.add_argument(
"--wait",
action="store_true",
help="Poll until project is initialized before exiting",
)
p_create.set_defaults(func=cmd_create)
p_status = subparsers.add_parser("status", help="Get project status")
p_status.add_argument("--type", required=True, choices=VALID_TYPES)
p_status.add_argument("--id", required=True, help="Project ID")
p_status.set_defaults(func=cmd_status)
p_regions = subparsers.add_parser("list-regions", help="List available regions")
p_regions.set_defaults(func=cmd_list_regions)
args = parser.parse_args()
args.func(args)
if __name__ == "__main__":
main()
Related skills
Forks & variants (1)
Cloud Create Project has 1 known copy in the catalog totaling 2 installs. They canonicalize to this original listing.
- elastic - 2 installs
How it compares
Use cloud-create-project for Elastic Cloud Serverless API provisioning; use Elastic app skills when the task is query and indexing code rather than cloud project creation.
FAQ
Required role?
Admin or Organization owner Cloud API key.
Day-2 skill?
cloud-manage-project for list update delete.
Prerequisite?
cloud-setup EC_API_KEY configured.
Is Cloud Create Project safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.