Metadata-Version: 2.4
Name: sdu-ucloud-cli
Version: 0.1.0
Summary: Unofficial CLI for SDU UCloud web service
Author-email: Rasmus Larsen <rasmus.larsen@alexandra.dk>
License: MIT License
        
        Copyright (c) 2026 Rasmus Larsen
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: cli,hpc,sdu,ucloud
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Utilities
Requires-Python: >=3.10.13
Requires-Dist: httpx<1.0,>=0.27
Requires-Dist: platformdirs<5.0,>=4.2
Requires-Dist: rich<14.0,>=13.7
Requires-Dist: typer<1.0,>=0.12
Provides-Extra: dev
Requires-Dist: pytest<9.0,>=8.2; extra == 'dev'
Requires-Dist: ruff<1.0,>=0.6.5; extra == 'dev'
Description-Content-Type: text/markdown

# ucloud-cli

`ucloud-cli` is an unofficial command-line client for SDU UCloud (`https://cloud.sdu.dk`).
It lets you manage common workflows from a terminal: projects, jobs, job submission, status checks, accounting, and SSH access.
It is published on PyPI as `sdu-ucloud-cli` and installs the `ucloud` command.

This tool uses the same web endpoints as the UCloud dashboard.
There is no stable public API contract for these endpoints, so behavior can change over time.

## Install

Install from PyPI:

```bash
uv tool install sdu-ucloud-cli
ucloud --help
```

Install from a local checkout:

```bash
uv tool install .
ucloud --help
```

Run directly from source:

```bash
uv sync
uv run ucloud --help
```

Install from Git without cloning:

```bash
uv tool install "git+https://github.com/rlrs/ucloud-cli.git"
ucloud --help
```

## First login flow

Login directly with username/password (supports MFA challenge):

```bash
uv run ucloud auth login --username <username>
uv run ucloud auth status
```

Refresh the access token from the stored `refreshToken` cookie:

```bash
uv run ucloud auth refresh
```

If you already have a browser session in Firefox, import it automatically:

```bash
uv run ucloud auth import-firefox
```

Fallbacks (manual browser capture):

```bash
uv run ucloud auth import-curl capture.curl
uv run ucloud auth login-cookie --cookie-header "name=value; other=value"
```

## Probe endpoints

```bash
uv run ucloud request GET /api/projects
uv run ucloud request GET /api/projects --output json
uv run ucloud request POST /api/example --json '{"id":"123"}'
```

You can attach a project context header to any request:

```bash
uv run ucloud request GET /api/jobs/browse --project <project-id>
```

## Project context

Set a default project once and reuse it across commands:

```bash
uv run ucloud projects browse --limit 20
uv run ucloud projects use --project <project-id>
uv run ucloud projects current
```

You can also run `uv run ucloud projects use` without `--project` to pick from an interactive list.

## Drives and files (read-only)

Browse drives in the active project:

```bash
uv run ucloud files drives
```

List files in a directory:

```bash
uv run ucloud files ls /
uv run ucloud files ls /1081839/DFM
```

Inspect a single path:

```bash
uv run ucloud files stat /1081839/DFM/readme.txt
```

Show storage usage/quota from drives + wallets:

```bash
uv run ucloud files df
uv run ucloud files df --project all
```

Render a recursive tree (read-only crawl):

```bash
uv run ucloud files tree /1093173
uv run ucloud files tree /1093173/eval-service --dirs-only
uv run ucloud files tree / --crawl-drives --max-depth 2
uv run ucloud files tree /1093173/eval-service --sort-by size --reverse --no-dirs-first
```

`--max-depth` limits tree display depth only; size aggregation still uses crawl results.

## Browse jobs

```bash
uv run ucloud jobs browse
uv run ucloud jobs browse --filter-state RUNNING --items-per-page 100
uv run ucloud jobs browse --all --items-per-page 100
uv run ucloud jobs browse --project all
uv run ucloud jobs browse --output json --limit 20
```

`jobs browse` uses the active project context and prints it above the result.
Set one with `ucloud projects use --project <project-id>` or override with `--project`.
Use `--project all` to browse across all visible projects.
When available, the project line includes both title and id.
Browse output includes remaining time until expiry (`remaining`).

## Job status and stop

```bash
uv run ucloud jobs status <job-id>
uv run ucloud jobs status <job-id> --poll --interval 2
uv run ucloud jobs stop <job-id>
```

## SSH into a job

Open SSH directly from the latest `jobs/retrieve` SSH update:

```bash
uv run ucloud jobs ssh <job-id>
```

Print the resolved command without executing:

```bash
uv run ucloud jobs ssh <job-id> --print-only
```

## Submit jobs (safe default)

`jobs submit` is dry-run by default and does not send anything to UCloud unless `--execute` is present.
The selected project controls the `Project` request header (job ownership context), while mounted drive paths can still point to other projects.
Project-scoped commands print the active project and allow `--project` override.

```bash
uv run ucloud jobs submit --from-curl job-submit.curl
uv run ucloud jobs submit --from-curl job-submit.curl --execute
```

Copy a previous job as a template:

```bash
uv run ucloud jobs submit --from <job-id>
uv run ucloud jobs submit --from <job-id> --execute
```

Useful overrides (without editing raw JSON):

```bash
uv run ucloud jobs submit --from-curl job-submit.curl \
  --name "debug-run" \
  --app-version Aug2026 \
  --product-id u3-gpu-4 \
  --replicas 1 \
  --time 12:00 \
  --mount /<id>/<dir> \
  --mount-ro /<id>/<dir>
```

This prints a readable summary first. Add `--show-payload` to inspect full JSON and `--write-payload job.json` to save it.

Other payload input modes:

```bash
uv run ucloud jobs submit --payload-file job.json
uv run ucloud jobs submit --json '{"type":"bulk","items":[]}'
```

## Browse accounting wallets

```bash
uv run ucloud accounting wallets
uv run ucloud accounting wallets --items-per-page 250
uv run ucloud accounting wallets --output json --limit 20
```

`accounting wallets` is project-scoped and uses the active project (or `--project`).

## Per-user job accounting

Aggregate historical job usage per user inside the active project:

```bash
uv run ucloud accounting jobs
uv run ucloud accounting jobs --max-pages 10
uv run ucloud accounting jobs --output json
uv run ucloud accounting jobs --project all
```

`accounting jobs` uses `jobs/browse` with pagination and sums estimated GPU-hours by owner.
By default it includes all job states; use `--filter-state` to narrow scope.
Pass `--project all` to aggregate across all visible projects.
Running jobs are counted only up to the current time (not full allocation).
Accounting tables include one column per machine family (for example `u3-gpu`, `u1-dfm`, `u1-standard-h`).
GPU families are shown in `gpuh`; non-GPU families are shown in `h`.

## Project helper

```bash
uv run ucloud projects browse
uv run ucloud projects browse --items-per-page 250 --sort-by favorite
uv run ucloud projects browse --output json --limit 20
```

## Auto-discover endpoints from source

If you have the UCloud source repository cloned as `ucloud/`, you can parse the generated endpoint map:

```bash
uv run ucloud discover endpoints
uv run ucloud discover endpoints --contains jobs --contains browse
uv run ucloud discover endpoints --method GET --output json --write endpoints.json
```

By default this reads:
`ucloud/frontend-web/webclient/app/Authentication/RpcNameTable.ts`
