Metadata-Version: 2.4
Name: opencosmo-portal
Version: 0.3.2
Summary: CLI and local MCP server for the OpenCosmo platform
Requires-Python: >=3.11
Requires-Dist: click>=8.1.0
Requires-Dist: httpx>=0.28.1
Requires-Dist: joserfc>=1.6.1
Requires-Dist: mcp[cli]>=1.26.0
Requires-Dist: pydantic>=2.0
Description-Content-Type: text/markdown

# OpenCosmo Portal CLI (`ocp`)

Command-line interface and local MCP server for the [OpenCosmo](../README.md) platform. Query cosmological simulation datasets at DOE Leadership Computing Facilities from your terminal.

## Installation

```bash
pip install opencosmo-portal
```

Or for development:

```bash
cd cli
uv sync
```

## Quick Start

The default profile points to `http://localhost:8000` (local development).
For development against a local backend:

```bash
# Authenticate via browser (Globus OAuth)
ocp auth login

# Browse available tasks
ocp task list
ocp task info <slug>

# Submit a task and monitor the run
ocp task run <slug>
ocp run status <run-id> --watch
ocp run results <run-id>
```

## Commands

### `ocp auth` — Authentication

| Command             | Description                             |
| ------------------- | --------------------------------------- |
| `ocp auth login`    | Authenticate via browser (Globus OAuth) |
| `ocp auth logout`   | Clear stored tokens                     |
| `ocp auth status`   | Show token status and expiry            |

### `ocp config` — Profile Management

| Command                                | Description              |
| -------------------------------------- | ------------------------ |
| `ocp config list`                      | List all profiles        |
| `ocp config add-profile <name> <url>`  | Add or update a profile  |
| `ocp config set-profile <name>`        | Set default profile      |
| `ocp config remove-profile <name>`     | Delete a profile         |
| `ocp config show [name]`               | Show profile details     |

### `ocp task` — Tasks

| Command                  | Description                                |
| ------------------------ | ------------------------------------------ |
| `ocp task list`          | List available tasks                       |
| `ocp task info <slug>`   | Show task details and input parameters     |
| `ocp task run <slug>`    | Submit a task (interactive or `--input`)   |

### `ocp run` — Runs

| Command                        | Description          |
| ------------------------------ | -------------------- |
| `ocp run list`                 | List your runs       |
| `ocp run status <id> [--watch]`| Check run status     |
| `ocp run logs <id>`            | View run logs        |
| `ocp run results <id>`         | Download results     |
| `ocp run cancel <id>`          | Cancel a run         |
| `ocp run archive <id>`         | Archive a run        |

### `ocp admin tasks install` — Adapter Installation

Install task adapter definitions into the backend database. Discovery is
explicit and non-recursive: directory mode uses the directory argument directly,
while archive modes require `--subdir`; only direct child `*.json` files in that
selected directory are loaded.

```bash
ocp admin tasks install dir ./artifact/build/portal_v2
ocp admin tasks install dir ./artifact/build/portal_v2 --dry-run

OPENCOSMO_API_URL=https://portal.example.org \
OPENCOSMO_API_KEY="$OPENCOSMO_API_KEY" \
ocp admin tasks install dir build/portal_v2

ocp admin tasks install url "https://.../artifacts/download?file_type=archive" \
  --subdir build/portal_v2 \
  --header "PRIVATE-TOKEN:${GITLAB_TOKEN}"

ocp admin tasks install gitlab \
  --host https://git.cels.anl.gov \
  --project hacc/hacc-compute-portal \
  --ref master \
  --job adapter-build \
  --subdir build/portal_v2 \
  --gitlab-token-env GITLAB_TOKEN
```

Supported archives are `.zip`, `.tar`, `.tar.gz`, and `.tgz`. Protected URL
tokens are accepted through explicit token/header options or environment
variables and are not persisted by the CLI or backend.

For CI, provide an admin API key through `OPENCOSMO_API_KEY` and set
`OPENCOSMO_API_URL` to the target portal. The CLI automatically exchanges the
API key for a JWT, uses that JWT for backend requests, and does not persist the
API key or env-derived JWT. `OPENCOSMO_API_KEY` takes precedence over stored
profile tokens.

For non-dry-run installs, the CLI first sends a dry-run request for every
discovered task. If any prevalidation request fails, no real install requests
are sent. Once real installation starts, requests are committed one task at a
time.

### `ocp admin service-accounts` — Service Accounts

Manage API-backed service accounts. All commands require admin permissions.

```bash
ocp --profile prod admin service-accounts list
ocp --profile prod admin service-accounts create ci-task-manager \
  --profile task-manager \
  --description "CI task adapter manager"
ocp --profile prod admin service-accounts update ci-task-manager --profile task-manager
ocp --profile prod admin service-accounts rotate-key ci-task-manager
ocp --profile prod admin service-accounts revoke-key ci-task-manager KEY_ID --yes
ocp --profile prod admin service-accounts disable ci-task-manager --yes
```

Create and rotate print the plaintext API key exactly once. Enabled service
accounts are automatically valid via `urn:opencosmo:service-account`; no
service-account entry is needed in `AUTH_VALID_GROUPS`. For `task-manager`, add
the printed profile-specific URN to backend admin authorization:

```bash
AUTH_ADMINS="urn:globus:groups:id:<admin-group>;urn:opencosmo:service-account:task-manager"
```

OpenCosmo JWTs store group URNs without an issuer field. Group provenance is
enforced before JWT minting through provider-owned namespace validation.
Identity providers declare the group URN prefixes they are allowed to mint;
Globus declares `urn:globus:groups:id:*`. Service accounts get the exact common
valid group `urn:opencosmo:service-account` at runtime and profile role groups
must use the `urn:opencosmo:service-account:` prefix. Callback, session,
auth-code, refresh-token, and device-code paths enforce validated effective
group authorization before accepting or minting tokens.

### `ocp whoami` — User

Show current user info.

### `ocp mcp` — MCP Server

Start a local stdio MCP server for AI assistants like Claude Desktop.

```bash
ocp mcp start
```

Configure in Claude Desktop (`claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "opencosmo": {
      "command": "ocp",
      "args": ["mcp", "start"]
    }
  }
}
```

## Global Options

| Option             | Description                                |
| ------------------ | ------------------------------------------ |
| `--profile, -p`    | Use a specific profile                     |
| `--format, -f`     | Output format: `table` (default) or `json` |
| `--version`        | Show version                               |
| `--help`           | Show help for any command                  |

## Releasing

The CLI is published to PyPI as `opencosmo-portal` via GitHub Actions (trusted publisher / OIDC).

### Automated (recommended)

Use the **Release CLI** workflow in GitHub Actions:

1. Go to **Actions → Release CLI → Run workflow**
2. Select the bump type (`patch`, `minor`, or `major`)
3. The workflow bumps `cli/pyproject.toml`, commits, tags, and pushes — which
   triggers the publish workflow automatically

### Manual

1. Bump `version` in `cli/pyproject.toml` (or run `cd cli && uv version --bump patch`)
2. Commit: `git commit -am "release: CLI v0.2.0"`
3. Tag: `git tag cli-v0.2.0`
4. Push both: `git push origin main cli-v0.2.0`

The [`publish-cli.yml`](../.github/workflows/publish-cli.yml) workflow will:
- Run the full test suite
- Verify the tag version matches `pyproject.toml`
- Build and publish to PyPI

### First-time setup

Register a [trusted publisher](https://docs.pypi.org/trusted-publishers/) on pypi.org:

| Field        | Value                  |
| ------------ | ---------------------- |
| Package name | `opencosmo-portal`     |
| Owner        | `ArgonneCPAC`          |
| Repository   | `OpenCosmoPortal`      |
| Workflow     | `publish-cli.yml`      |
| Environment  | `pypi`                 |

Then create a `pypi` environment in GitHub repo settings → Environments.

## Configuration

Config and tokens are stored in `~/.opencosmo/`:

```
~/.opencosmo/
├── config.json          # Profiles (name → API URL)
└── tokens/
    └── <profile>.json   # OAuth tokens per profile
```
