origin is the command-line interface for Origin Cloud:
log in, then manage organisations, projects, access, instances, networks and
volumes, and look up regions and zones, from a terminal or a script. Every
command prints JSON.
The CLI is published at packages.origincloud.eu, as one binary per platform
(origin-linux-amd64, origin-linux-arm64, origin-darwin-arm64,
origin-darwin-amd64) with a SHA256SUMS file and a GPG signature over it.
The Linux builds are statically linked.
With the install script, which picks the binary for your machine, checks it
against SHA256SUMS, and SHA256SUMS against the release key's signature
when gpg is installed, and installs it to ~/.local/bin:
curl -fsSL https://packages.origincloud.eu/install.sh | sh
origin --versionORIGIN_VERSION (such as v1.10.0) installs a specific version,
ORIGIN_INSTALL_DIR another directory, and ORIGIN_BASE_URL downloads the
binary from an HTTPS mirror instead; with a mirror, SHA256SUMS still comes
from packages.origincloud.eu and its signature must verify, so gpg is
required.
With apt, on Debian and Ubuntu (amd64 and arm64):
sudo curl -fsSLo /usr/share/keyrings/origincloud-archive-keyring.gpg \
https://packages.origincloud.eu/apt/origincloud-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/origincloud-archive-keyring.gpg] https://packages.origincloud.eu/apt stable main" \
| sudo tee /etc/apt/sources.list.d/origincloud.list
sudo apt-get update
sudo apt-get install origincloud-cliThe release key's fingerprint is
FEE6 FD74 A88C 5DB8 959F 5A1B 0BE6 AF84 2E0B 034A. Each version lives under
https://packages.origincloud.eu/cli/<version>/ for a manual download.
To build it yourself instead, with the Rust toolchain rust-toolchain.toml
names:
cargo install --locked --path crates/cliorigin id login # log in through your browser
origin id login --device # or with a code, on a machine without one
origin resourcemanager list-organizations
origin location list-zones
origin pvs list-volumes --project my-project-123 --zone eu-central1-az1
origin --help # every command group
origin pvs create-volume --help # every flag of a commandThe login session is stored in ~/.local/share/origincloud/session.json
(under $XDG_DATA_HOME when set), readable by you only, and renewed as it
expires; the profile, with your defaults, in
~/.config/origincloud/default-profile.json (under $XDG_CONFIG_HOME), or the
file --config names:
origin config profile-set default-project my-project-123
origin config profile-set default-zone eu-central1-az1
origin config profile-set region eu-central1
origin config profile| Profile key | Environment | Used for |
|---|---|---|
default-username |
ORIGINCLOUD_USERNAME |
Prefilled on the login page. |
output-format |
ORIGINCLOUD_OUTPUT_FORMAT |
json, the only format; --output overrides it. |
default-project |
ORIGINCLOUD_PROJECT |
--project of the generated commands, such as origin pvs's, when not given. |
default-zone |
ORIGINCLOUD_ZONE |
--zone of the generated commands, when not given; not of the lists, which list every zone without --zone. |
region |
ORIGINCLOUD_REGION |
The region the generated commands work in: the --region of the network commands' regional resources, when not given, and the front door the compute, network and pvs commands call, such as pvs.{region}.origincloudapis.eu. Without it, the region of the default zone (eu-central1 for eu-central1-az1); without either, --region must be given, and the calls go to the regionless host, such as pvs.origincloudapis.eu, which serves every resource. The location and resourcemanager commands always call their regionless host. |
As in the AWS CLI, a flag comes first, then the environment variable, then
the profile's value: an environment variable overrides the profile while a
command runs, and origin config profile-set changes the file alone, and
checks the value first. A command that fails
prints {"code": "failure", "description": "..."} and exits with status 1;
a command line the CLI can't parse exits with status 2 before sending
anything.
Irreversible commands (every delete, origin iam revoke-service-account,
and growing a volume with origin pvs update-volume --size-gib) refuse to run without --yes and say
what they would have done; the refusal happens before any request.
origin compute create-key-pair without --public-key prints the private
key it generates as privateKey, which the API returns this once, and says
so on standard error: save it, readable by you alone, such as with
origin compute create-key-pair | (umask 077; jq -r .privateKey > my-key).
A group per service of the API:
origin compute: instances, images, key pairs, volume attachments, and the instance types and image families on offer.origin network: VPCs, subnets, route tables and routes, ACLs, security groups and their rules, internet and NAT gateways, floating IPs, network interfaces and DNS policies, and the associations between them.origin pvs: the persistent volume service's volumes, snapshots and storage classes.origin resourcemanager: organizations and projects, and their quotas.origin location: the regions and zones, and which services each zone offers.
Their commands are generated from the API definitions in origincloudhq/api and call the Rust SDK, so there is one for every method of the API, with the API's own descriptions as help:
-
Command names. The service's name, then the method's name in kebab case:
CreateVolumeisorigin pvs create-volume,ListZonesisorigin location list-zones. -
Resource names. A resource is named by its parts, each an id of letters, digits,
-and_.--projectand--zoneare shared by every name a command builds, and default to the profile'sdefault-projectanddefault-zone; a regional resource oforigin network, such as a VPC, takes--regioninstead of--zone, which defaults to the profile'sregion, or the region of itsdefault-zone; the resource's own id is the flag named after it (--volume vol-123,--zone eu-central1-az1fororigin location get-zone), or after the field for a reference (--source-snapshot snapshot-123,--storage-class gp1). That flag also takes a whole name, such as--volume projects/my-project-123/zones/eu-central1-az1/volumes/vol-123, whose project and zone then fill in the others: thenameof a listed volume can be passed straight on. A part of a parent's name without a default, such as--instanceoforigin compute create-volume-attachment, is required, unless a whole name given to another flag has it. -
Other flags. Each other field of the request, and of the volume or snapshot it carries, is the flag of its name in kebab case:
size_gibis--size-gib. Output-only fields aren't flags, and neither is a field the method doesn't take although its request has it (import-volumehas no--source-snapshot). A boolean takes its value,--flag trueor--flag false; left out, one the API doesn't require isfalse. A duration is given as30s,2mor1m30s, a time as RFC 3339, such as2026-11-01T12:00:00Z. -
Tags.
--tag KEY=VALUE, repeated for more. On an update,--tagreplaces all of a resource's tags, and--no-tagsremoves them all; the two exclude each other, so the tags are only emptied when you say so. To set or remove one tag and keep the others, give every tag to keep with--tag:origin pvs get-volumeandget-snapshotshow the current ones. -
Lists. A repeated field is a flag named in the singular, repeated for each element, in order:
--security-group sg-1 --security-group sg-2. Where the API doesn't keep a list's order, the flag's help says so, and an element given twice is refused. -
Optional fields. A field the API marks optional is left out when its flag isn't given, and sent when it is, zero or empty included (
--max-connections 0). An update sets it, or with--no-and its name (--no-max-connections) unsets it. -
Choices. A oneof, a choice of fields of which a request carries at most one, is one flag per field, and giving two is refused:
--mirror-network,--mirror-addressor--mirror-log. Where the API requires a choice, a create must give exactly one. An update sets the one given, which replaces whichever was set, and--no-and the choice's name (--no-mirror) sets none of an optional one. -
Nested fields. A field holding a message is one flag whose value is comma-separated
KEY=VALUEpairs, the keys being the message's field names, with_or-; a repeated one takes one flag per element:--rule protocol=TCP,port=443,cidr=0.0.0.0/0 --rule protocol=UDP,port=53
Each key is typed and checked like a flag of its own (an enum's values, a number,
trueorfalse, a duration, a time, a resource name by its id or whole name), a required key must be given, and the flag's help lists the keys. Every such field also has a-jsonflag taking the field as the API's JSON, or@FILEto read it from a file, for what pairs can't say: a value with a comma, or a message nested deeper. Its fields are named as the command prints them, in camel case, or as the API definitions name them. Before anything is sent it is checked at every depth, each refusal naming its path: a field the message doesn't have, a key given twice, a value of the wrong type, an enum value that isn't one, an element given twice where the API keeps each once. A resource name in a field of the message itself is completed with--projectand--zone, as in the pairs; one nested deeper must be whole:--rules-json '[{"protocol": "TCP", "match": {"headers": [{"name": "x-env", "value": "prod"}]}}]' -
Updates. An update changes only what its flags name:
update-volume --volume vol-123 --tag team=webreplaces its tags and keeps its size. It needs at least one. A list, a map or a nested message is replaced whole: give every element to keep, and the keys of a nested message not given are reset; the flags' one-line help says so, and the command says on standard error which keys it resets.--no-and the field's name (--no-logging) empties one that isn't required. Growing a volume can't be undone and is charged, so--size-gibneeds--yes. -
Waiting. A command whose method answers with a long-running operation (most creates, updates and deletes) waits until it is done and prints the result;
--no-waitprints the operation as soon as the API accepts it. Ctrl-C stops the waiting, not the operation. -
Operations. A service whose methods answer with operations has two commands for them, which call its own host:
get-operationprints an operation as it is now, andwait-operationwaits until it is done and prints it, with itsresponseor itserror, exiting with status 1 when it failed.--timeout(such as5m) bounds the wait: when it passes first,wait-operationprints the operation as it is and exits with status 1. Both take the operation'sname, as--no-waitprinted it, or its id with--projectand--zone:origin pvs create-volume --size-gib 8 --storage-class gp1 --no-wait origin pvs wait-operation --operation projects/my-project-123/zones/eu-central1-az1/operations/op-123
-
Lists. A list command lists every page;
--page-sizeor--page-tokenasks for one page, whosenextPageTokennames the next. Without--zone, a list of zonal resources, such aslist-volumesorlist-instances, lists every zone that offers the service, in catalog order, as one list; one page needs--zone. An empty list prints as[]. -
Output. The API's JSON: the resource as the API returns it, with its fields in camel case, such as
sizeGib. -
Credentials. The login session, or, when they are set, the variables every Origin Cloud SDK reads:
ORIGINCLOUD_ACCESS_TOKEN, orORIGINCLOUD_CLIENT_IDandORIGINCLOUD_CLIENT_SECRETfor a service account.
--endpoint URL, an option of each of these groups, such as
origin pvs --endpoint URL, sends that group's calls to another base URL,
such as a test server's: https://, or http:// to this machine only. Each
group has its own environment variable for it, ORIGINCLOUD_{SERVICE}_ENDPOINT,
such as ORIGINCLOUD_PVS_ENDPOINT, so that redirecting one service leaves the
others at their own hosts. A list without --zone looks up the zones at
the location service, so ORIGINCLOUD_LOCATION_ENDPOINT, not the group's
endpoint, redirects that lookup. The CLI says on standard error whenever an
endpoint is used.
origin mcp serve serves the API to an AI agent as an
MCP server, on standard input and output.
An MCP client starts it as a local server, such as an AI coding assistant:
claude mcp add origincloud -- origin mcp serveor, for a client configured in JSON:
{ "mcpServers": { "origincloud": { "command": "origin", "args": ["mcp", "serve"] } } }- Tools. A tool per method of the API, generated like the commands:
pvs_create_volume,location_list_zones, and each service's_get_operationand_wait_operation. Each takes the method's request in the API's JSON, as its input schema describes, and answers with the response. Arguments the schema doesn't describe, such as a misspelt field, are refused, not dropped.current_contexttells the agent the profile'sdefault-projectanddefault-zone, and the region the commands use. - Resource names. Whole, such as
projects/my-project-123/zones/eu-central1-az1/volumes/vol-123. - Operations. A tool starting an operation waits for it up to 30
seconds, and answers with the operation: done, with its result or its
error, or not done yet, for the service's
_wait_operationtool. - Confirmation. The tools that delete something, or change it for good
(growing a volume), are marked destructive, for the MCP client to have
you confirm; they don't ask for
--yes.--read-onlyserves only the tools that change nothing. - Toolsets. A service's tools are its toolset:
--toolsets pvs,locationserves only those. - Credentials and endpoints. As the generated commands': the login
session or the SDK's variables, the region the commands use, and each
service's endpoint variable, such as
ORIGINCLOUD_PVS_ENDPOINT.
The tools are the library origincloudhq/mcp, which a server on the network can serve as well.
See CONTRIBUTING.md, which describes how the commands of each service are generated.
Apache License 2.0; see LICENSE.