partiri-cli 0.1.1

partiri CLI — Deploy and manage services on Partiri Cloud
# 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` and optionally appends an `export` line to your shell profile (`.zshrc`, `.bashrc`, etc.).

**Environment variables** (override stored credentials):

| Variable           | Description                                      |
|--------------------|--------------------------------------------------|
| `PARTIRI_KEY`      | API key — sent as `x-api-key` on every request   |
| `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
```

---

## Commands

### Top-level

| Command             | Description                                         |
|---------------------|-----------------------------------------------------|
| `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>`

| Subcommand                   | Description                                                        |
|------------------------------|--------------------------------------------------------------------|
| `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 status`     | Show current service details and live state                        |
| `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 token`      | Link an auth token to this service (private repos / registries)    |

### `partiri jobs <subcommand>`

| Subcommand          | Description                              |
|---------------------|------------------------------------------|
| `partiri jobs list` | List deploy jobs for the current service |

### `partiri projects <subcommand>`

| Subcommand              | Description                          |
|-------------------------|--------------------------------------|
| `partiri projects list` | List all projects in a workspace     |

### `partiri workspaces <subcommand>`

| Subcommand                | Description                                      |
|---------------------------|--------------------------------------------------|
| `partiri workspaces list` | List all workspaces accessible with your API key |

---

## 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.
  "service_id": null,

  "workspace_id": "<uuid>",
  "project_id": "<uuid>",

  "service": {
    "name": "my-service",

    // "webservice" | "static" | "private-service"
    "deploy_type": "webservice",

    // "node" | "rust" | "python" | "go" | "ruby" | "elixir" | "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": true,
    "health_check_path": "/health",

    "maintenance_mode": false,
    "active": true,

    // Environment variables injected at runtime
    "env": [
      { "key": "NODE_ENV", "value": "production" }
    ]
  }
}
```

### Field reference

| Field                        | Required | Description                                                  |
|------------------------------|----------|--------------------------------------------------------------|
| `service_id`                 | Auto     | Set by `service create`. Leave `null` initially.             |
| `workspace_id`               | Yes      | UUID of the target workspace.                                |
| `project_id`                 | 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      | Language runtime or `registry` for container images.         |
| `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.health_check`       | No       | Enable health check pings. Requires `health_check_path`.     |
| `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:

| Detected file                         | Runtime   | Default build command               |
|---------------------------------------|-----------|-------------------------------------|
| `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 service_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 status       # check live state
partiri jobs list            # 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 status
```

Requires Rust 1.77+ (edition 2021). No system OpenSSL dependency — TLS is handled by `rustls`.