@ciridae/cli
v0.1.1
Published
Command-line access to the Ciridae platform through MCP
Readme
Ciridae CLI
Ciridae CLI. Sign into production MCP once, then manage projects and
their deployments through production Crucible. Use resource commands for common
operations and api for the rest.
# Requires Node 24+:
npm install --global @ciridae/cli
ciridae init
ciridae auth login
ciridae auth status
ciridae auth whoami
ciridae organizations list
ciridae organizations current
ciridae config set project PROJECT_ID
ciridae config list
ciridae projects list
ciridae projects describe PROJECT_ID
ciridae deployments list
ciridae ghost-envs listciridae init writes one canonical Agent Skill to
~/.ciridae/skills/ciridae-cli/SKILL.md. It always links the shared
~/.agents/skills location and also links ~/.codex/skills, ~/.cursor/skills,
and ~/.claude/skills when those agent directories exist. The command prints
every detected target. ciridae init --check reports link and skill state plus
whether production credentials are saved without changing files.
The CLI owns and refreshes the skill through the <!-- CIRIDAE USER GUIDANCE -->
delimiter. Append personal instructions after that delimiter; updates preserve
that suffix and replace everything before it. A file without the delimiter is
fully replaced by the next ciridae init. All agents share the same user suffix
through their symlinks. Normal platform commands silently refresh the canonical
file, so new guidance arrives with CLI updates without another setup step.
Organizations have UUIDs and display names, not slugs. organizations use accepts
a UUID or an exact, case-insensitive display name; duplicate names require a UUID.
It saves the UUID for this MCP endpoint, separately from login credentials.
organizations current shows the current server-side name, UUID, and verified
directory access. organizations list marks active/default rows and reports
whether the default organization is accessible.
Ciridae, which owns the Crucible project, is the built-in default organization
(65a84feb-d9f1-43f0-8304-53303c96e1d1), but only when it appears in the
current user's accessible directory. An explicit saved selection takes precedence.
Without access to Ciridae, choose another org with organizations use NAME_OR_UUID.
An unavailable saved org requires reselection, not a silent switch to the default.
The automatic default is never written as an explicit user choice.
Project lists are scoped to it; project details and child-resource reads reject
projects outside it. Pass --organization NAME_OR_UUID to override the selection
for one command without changing the saved default. Every command verifies the
selected organization against the current account's directory.
config set organization NAME_OR_UUID also selects the organization. Use
config set project PROJECT_ID to save a working project within that org;
switching organizations does not carry a project into the new organization.
--project PROJECT_ID overrides the saved project for one resource command.
config get-value project prints the saved ID; config unset project clears it.
config unset organization restores the accessible Ciridae default. Saved projects
are checked against current server ownership when used, not treated as permissions.
Versions and updates
ciridae --version # Installed version only; offline
ciridae version # Installed version and an immediate npm lookup
ciridae version --json # { installed, latest, updateAvailable }
npm install --global @ciridae/cli@latestNormal interactive commands check npm's latest tag in a detached, finite process
at most once an hour. A known newer version is shown on stderr on every eligible
invocation, with the install command. Updates are never installed automatically.
The first lookup becomes visible on a subsequent command; ciridae version checks
immediately, with a two-second network deadline. If npm is unavailable or the
package is not published, it reports that instead of claiming to be up to date;
JSON returns latest: null.
Automatic checks and notices are disabled for piped output, noninteractive input,
CI, Codex/Claude agent sessions, JSON/raw/quiet output, and when
NO_UPDATE_NOTIFIER is set. Explicit version still performs its requested lookup.
The advisory cache lives at $XDG_CACHE_HOME/ciridae/npm-update.json (default
~/.cache/ciridae/npm-update.json), separate from credentials. Checks send only
the package name and CLI version to npm, never MCP credentials or command data.
A failed check retains the last known release and waits an hour before retrying.
Resource commands
The command model follows gcloud's conventions:
resource groups, list/describe/create, saved working context with per-command
overrides, automatic pagination, and --async for long-running creation.
It is not a full gcloud flag-language implementation.
ciridae projects list --search agent --limit 20
ciridae projects list --all-organizations --format=json
ciridae deployments list --project PROJECT_ID
ciridae deployments describe DEPLOYMENT_ID
ciridae deployments logs DEPLOYMENT_ID --limit 100
ciridae deployments logs DEPLOYMENT_ID --follow --format=json
ciridae projects settings describe
ciridae full-environments list
ciridae full-environments describe ENVIRONMENT_ID
ciridae ghost-envs describe GHOST_ENV_ID
ciridae env-vars list
ciridae env-vars list --environment ENVIRONMENT_ID
ciridae env-vars list --ghost-env GHOST_ENV_ID
ciridae integrations list
ciridae service-keys list
ciridae templates list
ciridae workflows describe WORKFLOW_ID_OR_RUN_UUID
ciridae workflows wait WORKFLOW_ID_OR_RUN_UUID --timeout 600
ciridae ghost-envs exec GHOST_ENV_ID --command 'pwd' --cwd /workspaceResource lists default to tables; use --format=json for JSON arrays. Descriptions
default to JSON. organizations list retains its default JSON envelope with
active/default/access annotations. projects list follows all pages by default;
--page-size sets the API batch size and --limit caps the total across all chosen
organizations. --all-organizations explicitly ignores the active org for that list.
Deployment and Ghost Env lists take --project, not a positional project argument.
Resource flags go after the leaf command, as shown above.
Each resource API read has a 60-second response deadline, independent of the total
workflow wait timeout. Browser OAuth is not bounded by that deadline. No request is
automatically replayed after a timeout; inspect remote state before retrying a write.
Environment-variable values are hidden by default in both tables and JSON.
--show-values includes whatever values the backend returns; treat that output as
sensitive. Full-environment IDs are checked against the selected project's inventory.
Global variables include editable and provider-managed entries. Integrations are
org-scoped; templates and service-key metadata are account-visible collections.
Workflow IDs are explicit and use the selected project's scope.
Logs accept --since/--until RFC3339 timestamps, repeated --severity and
--stream flags. A finite JSON read returns an array, newest first. --follow
polls and prints unseen entries oldest first; JSON follow output is NDJSON.
Each poll sees at most --limit entries (maximum 1000). This is a best-effort tail,
not lossless archival export; a warning reports non-overlapping polling windows.
workflows wait reports state changes on stderr and prints the completed result
on stdout. Failed, canceled, timed-out, or unknown status exits nonzero. Timeout and
Ctrl+C stop the local wait only, not the remote operation. Inspect before retrying.
Workflow server blocker: Crucible's workflow permission checker requires
scope=project and project_id, but the deployed MCP/OpenAPI schema omits both.
Calling the advertised tool without them returned HTTP 500 in the live smoke test.
The CLI supplies the correct project-scoped arguments, but the MCP schema must be
updated before workflows describe/wait can work. No auth bypass or raw-API policy
change is included. Project creation waits through project details, so its wait
path does not depend on this broken workflow endpoint.
Create a project
The file is the server's create-project body, excluding the IDs selected by the CLI.
For example, save this as project.json:
{
"project_name": "Example Project",
"customer_name": "Ciridae",
"repository_name": "example-project",
"source_provider": "github",
"repository_only": true,
"deployment_mode": "gcp_kubernetes"
}ciridae projects create example-project --template bundled-agent-template --file project.jsonCreation shows the target and asks for confirmation; --quiet/-q accepts it for
scripts. It waits for project setup by default. --async returns the accepted
project immediately; --timeout bounds waiting without canceling provisioning.
Creation does not switch your working project. For environment and Azure DevOps
configuration fields, inspect the server-owned schema:
ciridae api describe proj__int-provisioning__post_plates_template_project_id_projectsExec transport limitation
ghost-envs exec prints stdout/stderr separately and propagates the remote exit
code. MCP currently buffers the entire response, so output appears only after
completion. It is not an interactive terminal or live stream. The gateway's
30-second upstream read timeout and bounded response size still apply; the CLI
cannot fix those limits without a server change. An incomplete response fails with
an unknown outcome; commands are never automatically replayed. Use this for short,
finite commands only. The upstream exec route also inserts raw chunks into SSE;
multiline chunks may not be correctly framed. The CLI rejects malformed events
instead of silently dropping lines or reporting success. Correct server framing
and live streaming remain server work. Remote exec and project creation have not been live-tested
as part of this read-only smoke pass.
Raw API and authentication
This is UI-like working context, not a reduced authorization grant. api call
remains an explicit, unscoped escape hatch and does not inject organization
arguments. Server permissions still apply. Login/logout does not change the
saved selection; a different account must still have access to it.
Production MCP is the default. Use --server URL after a command only to test
another MCP gateway deployment:
ciridae auth login --server http://localhost:8000/mcp
ciridae api list --server http://localhost:8000/mcp
ciridae api call TOOL_NAME --json '{}'Selecting a gateway does not select the environment of a project behind it. Project and deployment selection belongs to resource commands. Production remains the default even if only another gateway's credentials are saved. Dev/staging Crucible instance selection is deferred; changing the gateway URL does not guarantee a different Crucible backend. Existing sandbox integrations and their access settings remain unchanged.
Discover tool arguments before calling them:
ciridae api list --search int-provisioning
ciridae api describe proj__int-provisioning__get_v1_projects
ciridae api list --search deployments --json
ciridae api call cir__whoamiTool discovery follows all pages. Text output has one line per tool; --json
includes full descriptions and schemas. api describe does not execute a tool.
Use --format=json for resource JSON and api call --raw for the complete MCP
envelope. Raw api call prints structured JSON when the server supplies it. Tool failures exit 1
and retain the server error in JSON; invalid arguments exit 2. Counts, login
instructions, and diagnostics go to stderr so stdout can be piped to jq.
organizations list supplies names and UUIDs for selecting your active org.
OAuth opens in the default browser and returns through a localhost callback.
Keep the command running until authorization completes; it waits until you
finish or press Ctrl+C. After cancelling, rerun login and use the newly opened
browser page, not an old callback link.
Repeat logins reuse the callback port saved with that server's client
registration. Authenticated commands do not listen on that port unless browser
authorization is needed. Close another login attempt if the port is in use.
Login state is stored in a user-only file under ~/.config/ciridae or
$XDG_CONFIG_HOME/ciridae. Each server host and port has its own registration
and token pair: logging in or out of one gateway leaves the others alone.
Login records the verified account email so offline logout can report
Signed out EMAIL (SERVER_URL). Logins without a recorded email say so; logging
out again reports Already signed out (SERVER_URL). Logout removes local credentials,
not the server-side installation or access grant.
ciridae auth login
ciridae auth login --server http://localhost:8000/mcp
ciridae auth list
ciridae auth status
ciridae auth logout --server http://localhost:8000/mcpauth list and auth status inspect saved credentials offline; they do not
claim the server has accepted them. auth login verifies the signed-in email
before printing Connected as EMAIL (SERVER_URL). It does not discover tools
or require Crucible access. Missing or unverified identity makes login exit
nonzero. Tool availability and permissions are checked when you use a tool;
the server still enforces each call.
Commands select the gateway's credentials and let the MCP SDK discover its OAuth service and refresh tokens as needed. Tokens are not copied between gateways.
Automatic User-Agent
Run commands normally. The CLI sets the HTTP User-Agent automatically from the
calling agent's environment: CLAUDECODE=1 selects
claude-code ciridae-cli/0.1.0; otherwise CODEX_SHELL=1 selects
codex ciridae-cli/0.1.0. Without either marker it sends ciridae-cli/0.1.0.
These markers identify the product, not its version, so no agent version is guessed.
If both are inherited, Claude Code takes precedence.
MCP clientInfo also identifies ciridae-cli via claude-code or
ciridae-cli via codex, keeping the CLI version separate and avoiding merged
client observations under one login. OAuth identity and grants are unchanged;
User-Agent is self-reported attribution, not authorization.
No custom flag or Ciridae-specific environment variable is needed. There are no local command metrics or analytics uploads; attribution uses MCP's existing server-side activity tracking. Environment values, session IDs, arguments, and command output are never copied into the User-Agent.
First-cut limits
This first cut is intended for supervised use. Concurrent CLI processes share
credentials and saved context. Credential refresh/persistence is not serialized,
and file writes are not atomic; overlapping refreshes can lose usable local auth
state. Avoid parallel login/refresh until this is hardened. Agents should pass
explicit --organization and --project instead of changing shared defaults.
Raw api call can mutate production and has no CLI-level confirmation. Never put
secret values directly into shell-history-visible command arguments. Dedicated
secret setters with file/stdin input are not part of this first cut. After a timed
out write, inspect remote state before retrying. Project creation and remote exec
have been traced in source but have not been live-tested against a disposable project.
The workflow-schema and exec-streaming limitations above remain server follow-ups.
Development
From the monorepo root:
pnpm install --frozen-lockfile --filter @ciridae/cli...
pnpm --filter @ciridae/cli typecheck
pnpm --filter @ciridae/cli lint
pnpm --filter @ciridae/cli format:check
pnpm --filter @ciridae/cli test
pnpm --filter @ciridae/cli build
pnpm --filter @ciridae/cli dev --help
pnpm --dir apps/ciridae-cli pack --out /tmp/ciridae-cli.tgz
npm install --global /tmp/ciridae-cli.tgzThe dedicated CLI workflow runs these checks and installs the npm tarball in a
fresh prefix to check the entry point, bundled callback asset, and Agent Skill.
The CLI uses
Commander and the official MCP TypeScript SDK, with the root pnpm workspace lock.
It has no private backend-package dependencies and does not change the public
Python ciridae distribution.
npm releases
The package is public @ciridae/cli; package.json owns its version. Review the
packed files as public source before releasing. Publishing is manual, not triggered
by merge: bump the version in a PR, merge it, then dispatch Publish Ciridae CLI
on main. The workflow validates, packs, smoke-tests, and publishes the exact
tarball with the latest tag through the npm-publish GitHub environment.
The initial 0.1.0 tarball was published manually from commit c63086953.
Its trusted publisher is configured for repository ciridae-ai/ciridae, workflow
ciridae-cli-publish.yml, environment npm-publish, with npm publish permission
only. Verify it with npm trust list @ciridae/cli. The first automated publish
still needs to be exercised after the workflow lands on main; do not republish
the immutable 0.1.0 version. No npm token is stored in this repository.
See npm trusted publishing.
This repository is private, so npm provenance is not requested.
For prototype users, uninstall the Python executable with uv tool uninstall ciridae-cli
before the npm install, then run command -v ciridae to confirm which executable
your shell uses. Existing OAuth registrations, tokens, and working context retain
their on-disk format; no second implementation or migration is shipped. Low
breakage risk: the local runtime/install command changes from Python to Node,
but resource command names and flags are retained.
