@uru-intelligence/cli
v0.5.3
Published
Uru full-platform command line interface
Readme
uru
Full-platform uru CLI. The package installs a uru binary and uses the same
registry-backed platform operations exposed through MCP and the web UI.
Do not publish a release until the registry, MCP proxy, generated docs, and staging smoke gates are all green; run it from the repo with Bun while iterating.
cd apps/cli
bun src/index.ts login
bun src/index.ts whoami --json
bun src/index.ts switch <workspace-id>The CLI is registry-backed. Dedicated Gem/Library/Dataset/Automation commands are thin adapters over the same platform tools used by MCP and the web UI; broader workspace, prompt/persona/context, sharing, web/file, business SQL, secret/env/token operations remain exposed through the generated operation registry while dedicated UX commands continue to mature. The CLI does not reimplement Gem lifecycle sequencing client-side.
Current commands
# Link the current directory to a server-side Gem. Writes only .uru/project.json.
bun src/index.ts link --workspace <workspace-id> --path 'library/Golden Gems/My Gem.gem'
# Initialize and operate Gems through first-class Gem commands.
bun src/index.ts init 'library/Golden Gems/My Gem.gem' --file ./main.html
bun src/index.ts build 'library/Golden Gems/My Gem.gem' --dry-run --outdir ./dist/uru
bun src/index.ts status 'library/Golden Gems/My Gem.gem' --json
bun src/index.ts logs 'library/Golden Gems/My Gem.gem' --limit 100
bun src/index.ts logs 'library/Golden Gems/My Gem.gem' --follow
bun src/index.ts --output-format stream-json logs 'library/Golden Gems/My Gem.gem' --follow
bun src/index.ts open 'library/Golden Gems/My Gem.gem'
bun src/index.ts gems inspect 'library/Golden Gems/My Gem.gem'
bun src/index.ts gems validate 'library/Golden Gems/My Gem.gem'
bun src/index.ts gems build 'library/Golden Gems/My Gem.gem'
bun src/index.ts gems edits list 'library/Golden Gems/My Gem.gem'
bun src/index.ts gems edits show 'library/Golden Gems/My Gem.gem' <edit-id>
bun src/index.ts gems versions save 'library/Golden Gems/My Gem.gem' --name "Client review" --message "Ready for review"
bun src/index.ts gems versions list 'library/Golden Gems/My Gem.gem'
bun src/index.ts gems versions show 'library/Golden Gems/My Gem.gem' 14
bun src/index.ts gems versions diff 'library/Golden Gems/My Gem.gem' 13 14
bun src/index.ts gems versions restore 'library/Golden Gems/My Gem.gem' 12
bun src/index.ts gems releases create 'library/Golden Gems/My Gem.gem' 14
bun src/index.ts gems releases list 'library/Golden Gems/My Gem.gem'
bun src/index.ts gems links create 'library/Golden Gems/My Gem.gem' --name Client --pin --version 14
bun src/index.ts gems links set-version 'library/Golden Gems/My Gem.gem' <link-id> 14
bun src/index.ts gems runs list 'library/Golden Gems/My Gem.gem'
bun src/index.ts gems runs show 'library/Golden Gems/My Gem.gem' <run-id>
bun src/index.ts gems logs 'library/Golden Gems/My Gem.gem' --release <release-id>
bun src/index.ts gems logs 'library/Golden Gems/My Gem.gem' --run <run-id>
bun src/index.ts gems read 'library/Golden Gems/My Gem.gem' main.html
bun src/index.ts gems write 'library/Golden Gems/My Gem.gem' main.html --file ./main.html
# Library and dataset helpers over the platform tool surface.
bun src/index.ts library ls library
bun src/index.ts library search revenue
bun src/index.ts library mkdir 'library/Golden Gems'
bun src/index.ts library read 'library/Contexts/Client Brief.md'
bun src/index.ts library write 'library/Contexts/Client Brief.md' --file ./brief.md --create
bun src/index.ts library write 'library/Prompts/Sales Email.md' --content "Draft the follow-up." --create --folder-id <folder-id>
bun src/index.ts library patch-preview 'library/Prompts/Sales Email.md' --content "*** Begin Patch\n..."
bun src/index.ts library favorite 'library/Contexts/Client Brief.md'
bun src/index.ts library upload 'library/Assets/logo.png' --file ./logo.png
bun src/index.ts library upload complete --upload-id <id> --bucket <bucket> --object-path <path> --filename logo.png --size-bytes 1024
bun src/index.ts library patch 'library/Prompts/Sales Email.md' --stdin
bun src/index.ts library cp 'library/Notes/Brief.md' 'library/Archive/Brief.md'
bun src/index.ts library mv 'library/Notes/Draft.md' 'library/Notes/Final.md'
bun src/index.ts library rm 'library/Notes/Old.md'
bun src/index.ts library restore 'library/Notes/Old.md'
bun src/index.ts datasets ls --limit 50 --json
bun src/index.ts datasets query revenue_rows --limit 50 --response-format concise --json
# Registry-family commands send --params-json fields exactly as the tool's input
# schema spells them. Read that schema with --get-schema or `uru operations inspect <id>`.
bun src/index.ts datasets get revenue-rows
bun src/index.ts datasets history revenue-rows --limit 20
bun src/index.ts datasets jobs revenue-rows --limit 20
bun src/index.ts datasets rows --params-json '{"op":"upsert","dataset_id":"revenue-rows","rows":[{"name":"Acme"}]}'
bun src/index.ts datasets create --params-json '{"title":"Revenue Rows","properties":[{"clientKey":"name","name":"Name","type":"title","required":true,"nullable":false,"position":0,"config":{}}]}'
bun src/index.ts datasets sql --params-json '{"sql":"SELECT 1"}'
bun src/index.ts distribution list --limit 20
bun src/index.ts distribution get <collection-id>
bun src/index.ts distribution create "Client pack" --scope workspace
# Automation helpers over the platform tool surface.
bun src/index.ts automations ls --limit 100
bun src/index.ts automations get <automation-id>
bun src/index.ts automations create "Daily revenue digest" --status draft
bun src/index.ts automations update <automation-id> --description "Nightly digest"
bun src/index.ts automations enable <automation-id>
bun src/index.ts automations validate <automation-id> --mode structural --graph-json '{}'
bun src/index.ts automations graph-patch <automation-id> --patch-json '{"ops":[]}'
bun src/index.ts automations triggers list <automation-id>
bun src/index.ts automations connections list
bun src/index.ts automations delete <automation-id> --yes
bun src/index.ts automations trigger <automation-id> --input-message "Run now"
bun src/index.ts automations runs ls <automation-id> --scope workspace --limit 20
bun src/index.ts automations runs tail <run-id> --level warn
bun src/index.ts automations runs cancel <run-id> --yes
# Raw platform-tool escape hatch for diagnostics and low-level operations.
bun src/index.ts tools ls
bun src/index.ts tools schema gem_control_plane --json
bun src/index.ts tools run gem_control_plane --params-json '{"op":"inspect","path":"library/Golden Gems/My Gem.gem"}'
# Show and execute the generated operation registry.
bun src/index.ts operations ls
bun src/index.ts operations ls --family automations
bun src/index.ts operations run gem.inspect --params-json '{"path":"library/Golden Gems/My Gem.gem"}'
bun src/index.ts library search "client brief"
bun src/index.ts docs library_fs
bun src/index.ts docs search library_fs
bun src/index.ts api platform/tools/search_tools/execute -F query=gem
bun src/index.ts api /api/platform/tools/search_tools/execute -F query=gem
# MCP client config helper. Prefer ${URU_API_KEY} or --api-key. List never prints keys.
bun src/index.ts mcp list
bun src/index.ts mcp list --target cursor
bun src/index.ts mcp config --api-key "$URU_API_KEY"
bun src/index.ts mcp install --target cursor
bun src/index.ts mcp install --path ~/.config/claude-code/mcp.json --api-key "$URU_API_KEY"
bun src/index.ts mcp remove --target cursor
# Local auth facts. Never prints a JWT.
bun src/index.ts auth status --json
bun src/index.ts doctor --json
# Local shell integration.
bun src/index.ts complete bash
bun src/index.ts complete zsh
bun src/index.ts complete fish
bun src/index.ts complete powershellGenerated MCP configs use non-interactive npx -y and pin
[email protected]. Pass --package <package@version> only for an intentional,
explicit bridge override.
Gem Version commands save and inspect frozen checkpoints that group coherent
Edits. The Version name and message are optional. Hosted Gems materialize one
Version with releases create; embedded Gems do not need Releases. Neither
action changes a public URL. Only links set-version changes the one named
Link. Provider-internal flags are not accepted: runtime routing is compiled
server-side.
The scaffold defaults to the production API (https://api.uruintelligence.com).
Use --api-url, URU_API_BASE, or URU_API_URL to point it at staging or a local backend:
URU_API_BASE=https://api-staging.uruintelligence.com bun src/index.ts whoami --json
URU_API_BASE=http://127.0.0.1:8000 bun src/index.ts whoami --jsonAuth and local state
The default login path is browser OAuth with PKCE and OS-keychain storage. Browser and device login keep access/session tokens short-lived and store a rotating OAuth refresh credential so the CLI can renew them automatically. The refresh credential has a 30-day lifetime and receives a new 30-day lifetime when it is successfully rotated. Headless environments can use device login or explicit token/API-key paths:
uru loginopens browser OAuth and stores a versioned, renewable credential bundle in the OS keychainuru login --deviceprints a device-code URL for SSH/headless environmentsuru login --token ...stores the token in OS credential storage when available: macOS Keychain, Linuxsecret-tool/libsecret, or Windows Credential Manager via PowerShelluru login --token ... --insecure-storageis the explicit plaintext fallback- Linux token storage requires
secret-tool(often installed aslibsecret-tools); Windows token storage requires PowerShell access to Credential Manager. If the OS store is unavailable, login fails closed with an actionable--insecure-storagefallback message. - browser/device credentials renew within five minutes of session expiry. A workspace switch is request scope and does not rotate the login.
- interactive commands with missing or expired stored auth start browser login and then retry the command without printing login success text to stdout
--no-inputdisables implicit login and exits4when authentication is missinguru logoutinvalidates the current CLI session, revokes the renewable OAuth credential, and clears local auth state- precedence:
--token/--token-file/--token-stdin>URU_TOKEN> OS keychain >--insecure-storagelocal config - manually supplied tokens and CI tokens are used as-is and do not gain OAuth renewal
- local config:
URU_CONFIG_HOME, then XDG config home, then~/.config/uru - config file permissions:
0600 - linked project state:
.uru/project.jsonwith{workspaceId, gemId, libraryPath} - no credentials are written to
.uru/project.json uru auth statusreports logged-in / workspace / storage / expiry and never prints a JWT.uru whoamistays a server identity call.uru switchsets the local default workspace.uru linkbinds this directory to one Gem.--workspace/URU_WORKSPACE_IDoverride one invocation.- The screen says Agent; Library paths and schemas say persona (
library/Agents/Name.persona.md). - Gem-scoped deploy tokens for CI use
uru tokens create|ls|revokeuru tokens createrequires--nameplus exactly one lifetime flag:--expiry <duration>or--expires-at <iso timestamp>- created tokens default to the server-enforced
gem:deployscope - custom
--scope/--scopesvalues must includegem:deploybefore the token can operate Gem deploy/query/control routes
- Gem secrets use
uru secrets put|ls|rm; values are write-only uru env pullwrites a metadata-only template, never downloads remote secret values, and clamps the output file to0600even when overwriting an existing fileuru env run -- <cmd>overlays local values and redacts all non-empty values from captured output
CI cookbook
Use a Gem-scoped token, never a session JWT, and fail closed:
uru tokens create 'library/Golden Gems/My Gem.gem' --name CI --expiry 30d --json
export URU_TOKEN=<token-from-create-once>
export URU_WORKSPACE_ID=<workspace-id>
uru --no-input doctor --json
uru --no-input auth status --json
uru --no-input whoami --json--no-input exits instead of opening a browser. auth status and doctor warn if the token lives in --insecure-storage and do not print the token. env pull writes names only; it does not download secret values.
Install shape
The package name is @uru-intelligence/cli; the installed binary is still uru:
npm install -g @uru-intelligence/cli
uru login --token "$URU_TOKEN"
uru whoami --jsonFor one-off usage:
printf '%s' "$URU_TOKEN" | npx @uru-intelligence/cli whoami --token-stdin --jsonThe package root is a side-effect-free library entry. It does not execute a
command, read local CLI configuration, install signal handlers, write output,
or start network activity on import. The package currently exposes only the
fail-closed internal createUruClient foundation: callers must supply a token
and an explicit workspace, every call accepts cancellation, and it validates
the authenticated workspace before returning a typed result. DG-1 has not
accepted a public high-level SDK compatibility promise, so no broader SDK or
raw API surface is implied by this export. The executable remains the uru
binary; @uru-intelligence/cli/cli is an explicit executable subpath for
packaging tools, not an SDK API.
Release validation
Before publishing, run the full local CLI gate and the staging CLI/MCP smoke with a staging-scoped token. The smoke reads credentials from env or macOS Keychain and never prints the token. To avoid putting a token in shell history, store it as uru_staging_smoke_token with security add-generic-password -a "$USER" -s uru_staging_smoke_token -w '<token>' -U.
bun --filter=@uru-intelligence/cli run ci
URU_CLI_MCP_STAGING_SMOKE_TARGET=staging \
STAGING_AUTH_BEARER_TOKEN=... \
STAGING_WORKSPACE_ID=<workspace-id-if-needed> \
bun --filter=@uru-intelligence/cli run smoke:staging -- --jsonPublish the scoped CLI through the Publish Uru CLI to npm workflow
(.github/workflows/publish-uru-cli.yml) from staging or main. Pass the exact
apps/cli/package.json version as its version input. The workflow rejects
other branches or a version mismatch.
The workflow runs the source gates, builds one tarball, and retains its integrity
values. Package smoke tests check that tarball before npm trusted publishing
runs from the protected environment. Publication uses the retained tarball with
--ignore-scripts, rather than rebuilding it. A retry may reuse an already
published version only when its integrity is identical. A different package
needs a higher version.
The final job rebuilds the checked-out CLI and tests it against staging using credentials supplied by Infisical. It does not install the registry package. Check that job and its retained smoke report, then install the exact published version in a clean directory and verify the intended behavior. A successful npm upload or source smoke alone does not complete registry verification.
The npm package remains the canonical install path. Release builds can also produce standalone Bun-compiled binaries for the planned macOS/Linux/Windows matrix:
bun --filter=@uru-intelligence/cli run build:binaries # current platform
bun --filter=@uru-intelligence/cli run build:binaries:matrix # planned release matrix
bun --filter=@uru-intelligence/cli run smoke:binaries # dry-run matrix plannerThe updater command is intentionally conservative: uru update prints the exact
npm install -g @uru-intelligence/cli@latest command instead of self-mutating
the installation. Interactive text-mode commands also perform a bounded
once-per-24h npm version check and write a single stderr notice when a newer CLI
is available. The notifier is disabled for JSON/streaming output, CI,
NO_UPDATE_NOTIFIER, and URU_NO_UPDATE_NOTIFIER.
