Droploft v2 CLI — Shared Skill
Read this before invoking any other droploft-* skill. It explains how the CLI is structured, how to authenticate, and the contract every command honours.
Three-layer command model
| Layer | Syntax | When to use |
|---|---|---|
| 1 · Flows | droploft <domain> +<verb> |
High-level multi-step ops (interactive picker, polling, progress). E.g. doc +upload, loft +switch. |
| 2 · Resources | droploft <resource> <verb> |
1:1 API mapping with full parameter control. E.g. documents list, lofts get <id>. |
| 3 · Raw API | droploft api <METHOD> <path> [--data <json>] |
Anything not covered above. |
There is also a self-describing schema browser: droploft schema list|get|search.
+ in front of a verb signals "flow". Resource verbs do not start with +. This visual split is intentional — flows can prompt, polls, or open a browser; resources never do.
Authentication (Device Flow)
The default login is RFC 8628 device flow — no local HTTP server, works in SSH/containers.
droploft auth login # opens browser, prints user code, polls until verified
droploft auth login --label "MyLaptop" # custom name for the issued API token
droploft auth login --no-browser # print URL only (don't auto-open)
droploft auth login --token <pat> # CI / non-TTY: skip the browser dance
The browser prompts the signed-in user to confirm the displayed user code. On success the CLI receives a personal API token and stores it in the OS keychain.
Status / logout
droploft auth status # verifies token via /v1/auth/me
droploft auth logout # clears the keychain entry; revoke server-side via /settings?tab=api-token
CI / scripts
Set environment variables instead of running auth login:
DROPLOFT_TOKEN— bypass keychainDROPLOFT_SERVER_URL— override server URLDROPLOFT_PROFILE— choose profile
Profiles
Each profile is a self-contained context: server URL, keychain entry, workspace, loft.
droploft config use staging # switch profile
droploft config set server_url https://api.example # set on active profile
droploft config get server_url
droploft config list # all profiles
droploft config current # active profile snapshot
Per-call override: --profile <name> and --server-url <url> work on every command.
Output contract
Every command writes one of:
- Envelope JSON (
--format json, default for non-TTY):{ok: true, data: ...}or{ok: false, error: {type, message, hint, status}}to stderr. - Table (
--format table, default for TTY): aligned columns, headers sorted alphabetically. - CSV / NDJSON (
--format csv|ndjson): for spreadsheet / streaming consumers.
Errors always go to stderr with a non-zero exit code:
| Code | Meaning |
|---|---|
| 0 | success |
| 2 | usage / validation / non-interactive without flags |
| 3 | auth required |
| 4 | not found |
| 5 | conflict |
| 6 | rate limited |
| 1 | other |
Non-interactive behaviour
The CLI hard-fails any prompt when stdin/stdout is not a TTY. To stay scriptable, pass the missing parameter explicitly:
| Flow | Non-TTY substitute |
|---|---|
auth login |
--token <pat> (or DROPLOFT_TOKEN) |
loft +switch |
--loft <id> |
workspace +switch |
--workspace <id> |
Self-discovery
If you don't know which endpoint to call, ask the CLI itself:
droploft schema list # all known endpoints
droploft schema list --tag documents # filter by tag
droploft schema get documents.create # full spec of one endpoint
droploft schema search publish # keyword search
droploft api GET /v1/me/navigation # raw call, useful as a fallback
Universal flags
--profile <name>,--server-url <url>--format <json|table|csv|ndjson>,--quiet,--verbose,--no-color--jq <expr>(Layer 3 / list endpoints) — apply a jq-style filter--help,--version