# partiri CLI
The official command-line interface for [Partiri Cloud](https://partiri.cloud). Deploy and manage services directly from your terminal.
Built in Rust.
---
## Installation
### Pre-built binary
Download the latest release from [Codeberg Releases](https://codeberg.org/PartiriCloud/cli/releases), extract, and add to your `PATH`.
### Cargo (crates.io)
```bash
cargo install partiri-cli
```
### npm
```bash
npm install -g @partiri/cli
```
### Build from source
```bash
cargo build --release
# Binary at: target/release/partiri
```
---
## Authentication
```bash
partiri auth
```
Stores your API key in `~/.config/partiri/key`.
**Environment variables:**
| `PARTIRI_API_URL` | Override the default API base URL |
| `PARTIRI_TIMEOUT` | HTTP request timeout in seconds (default: 30) |
---
## Quick Start
```bash
# 1. Authenticate
partiri auth
# 2. Initialize config in your project directory
partiri init
# 3. Register the service on Partiri Cloud
partiri service create
# 4. Deploy
partiri service deploy
```
### Adopt an existing service
If the service already exists on Partiri Cloud (created via the web frontend or by a teammate), skip `init` and `create` — `pull` is the only service subcommand that does **not** require a local `.partiri.jsonc` and will generate one for you:
```bash
# 1. Authenticate
partiri auth
# 2. In the project directory, pull the existing service
partiri service pull
```
You will be prompted to pick the workspace, project, and service; the CLI writes a ready-to-use `.partiri.jsonc` in the current directory.
---
## Commands
### Top-level
| `partiri auth` | Configure your Partiri API key |
| `partiri init` | Interactive wizard — creates `.partiri.jsonc` |
| `partiri validate` | Validate the local `.partiri.jsonc` config file |
### `partiri service <subcommand>`
| `partiri service create` | Register the service on Partiri and write its ID to the config |
| `partiri service pull` | Pull an existing service from Partiri and save as `.partiri.jsonc` |
| `partiri service push` | Push local config changes to the existing service |
| `partiri service metrics` | Show current service metrics and recent jobs |
| `partiri service logs` | Show the last 35 log lines from the past hour |
| `partiri service jobs` | List jobs for this service |
| `partiri service deploy` | Trigger a deploy job |
| `partiri service pause` | Pause the service |
| `partiri service unpause` | Resume a paused service |
| `partiri service kill` | Kill the service (requires confirmation) |
| `partiri service link` | Fill in workspace, project, region and pod UUIDs interactively |
| `partiri service token` | Link an auth token to this service (private repos / registries) |
### `partiri projects <subcommand>`
| `partiri projects list` | List all projects in a workspace |
| `partiri projects create` | Create a new project in a workspace |
### `partiri workspaces <subcommand>`
| `partiri workspaces list` | List all workspaces accessible with your API key |
### `partiri mcp <subcommand>`
Install or remove the Partiri MCP server in AI tools. Valid `--client` slugs: `claude-desktop`, `claude-code`, `cursor`, `vscode`, `copilot-cli`, `windsurf`. Omit `--client` to pick interactively.
| `partiri mcp install [--client <slug>]` | Install the Partiri MCP server into an AI tool |
| `partiri mcp uninstall [--client <slug>]`| Remove the Partiri MCP server from an AI tool |
---
## Config File — `.partiri.jsonc`
`partiri init` creates a `.partiri.jsonc` in your project root. The file uses JSON5 syntax (supports `//` comments and trailing commas).
```jsonc
{
// Assigned by Partiri after running 'partiri service create'. Leave null until then.
"id": null,
"fk_workspace": "<uuid>",
"fk_project": "<uuid>",
"service": {
"name": "my-service",
// "webservice" | "static" | "private-service"
"deploy_type": "webservice",
// "node" | "rust" | "python" | "go" | "ruby" | "elixir" | "php" | "jvm" | "dotnet" | "cpp" | "static" | "registry"
"runtime": "node",
"root_path": ".",
// Git repository source
"repository_url": "https://github.com/org/repo",
"repository_branch": "main",
// Or registry image source (not compatible with deploy_type "static")
// "registry_url": "registry.example.com",
// "registry_repository_url": "myorg/myimage:latest",
// Authentication token for private repos/registries — set via 'partiri service token'
// "fk_service_secret": "<uuid>",
"build_command": "npm run build",
// "build_path": "dist",
// "pre_deploy_command": "npm run migrate",
"run_command": "npm start",
"fk_region": "<region-uuid>",
"fk_pod": "<pod-uuid>",
"health_check_path": "/health",
"maintenance_mode": false,
"active": true,
// Environment variables injected at runtime
"env": [
{ "key": "NODE_ENV", "value": "production" }
]
}
}
```
### Field reference
| `id` | Auto | Set by `service create`. Leave `null` initially. |
| `fk_workspace` | Yes | UUID of the target workspace. |
| `fk_project` | Yes | UUID of the target project. |
| `service.name` | Yes | Display name shown on Partiri Cloud. |
| `service.deploy_type` | Yes | `webservice`, `static`, or `private-service`. |
| `service.runtime` | Yes | `node`, `rust`, `python`, `go`, `ruby`, `elixir`, `php`, `jvm`, `dotnet`, `cpp`, `static`, or `registry`. |
| `service.root_path` | Yes | Path to the app root within the repository. |
| `service.repository_url` | *Either* | Git repository URL. Required when not using a registry. |
| `service.registry_url` | *Either* | Container registry hostname. Not supported for `static`. |
| `service.build_command` | No | Command to build the project. |
| `service.build_path` | No | Build output directory (e.g. `dist`). |
| `service.pre_deploy_command` | No | Command to run before each deploy (e.g. DB migrations). |
| `service.run_command` | No | Command to start the service. |
| `service.fk_region` | Yes | Region UUID. Listed via `partiri workspaces list`. |
| `service.fk_pod` | Yes | Compute pod UUID (CPU/RAM tier). |
| `service.maintenance_mode` | No | Serve a maintenance page instead of the app. |
| `service.env` | No | Array of `{ "key": "...", "value": "..." }` entries. |
---
## Project Detection
`partiri init` auto-detects your project type and pre-fills defaults:
| `package.json` | `node` | `npm run build` / `npm start` |
| `Cargo.toml` | `rust` | `cargo build --release` |
| `requirements.txt` / `pyproject.toml` | `python` | `pip install -r requirements.txt` |
| `go.mod` | `go` | `go build -o app .` |
| `Gemfile` | `ruby` | `bundle install` |
| `mix.exs` | `elixir` | `mix deps.get && mix compile` |
It also reads the git `origin` remote to pre-fill `repository_url`, and imports variables from a local `.env` file (if present) into `service.env`.
---
## Typical Workflow
```
your-project/
├── .partiri.jsonc ← managed by the CLI
├── src/
└── ...
```
```bash
# First time
partiri auth # save API key
partiri init # interactive wizard → .partiri.jsonc
partiri service create # register on Partiri → writes id to config
partiri service deploy # trigger first deploy
# Ongoing
partiri service push # push local config changes (env vars, commands, etc.)
partiri service deploy # redeploy
partiri service metrics # check live state
partiri service jobs # review deploy history
# Maintenance
partiri service pause # pause the service
partiri service unpause # resume
partiri service kill # permanently stop (with confirmation prompt)
```
---
## Development
```bash
# Run from source
cargo run -- <command>
# Example
cargo run -- service metrics
```
Requires Rust 1.77+ (edition 2021). No system OpenSSL dependency — TLS is handled by `rustls`.