PaaS CLI - Connect from Your Machine
Install the paas CLI, authorize via browser, and manage your instance with scoped agent tokens - no curl or admin token on your laptop.
The paas CLI is the recommended way to connect AI coding assistants (Cursor, Claude Code, Codex), local scripts, and your laptop to a Better-PaaS instance. You run one command, approve access in the browser, and a scoped agent token is saved locally - your admin token never leaves the server.
This replaces the manual curl + admin-token workflow for day-to-day use.
You can still create tokens via the Agent Access API
if you prefer full control over scopes.
What you need
- A Better-PaaS instance with the dashboard and API running (see Quickstart if you haven't installed yet).
- The dashboard URL - the same address you open in your browser, e.g.
https://paas.example.comorhttp://YOUR_SERVER_IP:3000. - Go 1.22+ on your local machine (to build the CLI once).
Install the CLI
Remote install (recommended) - no clone required:
go install github.com/sumon-ohid/better-paas/backend/cmd/paas@latestPin a specific release:
go install github.com/sumon-ohid/better-paas/backend/cmd/[email protected]Track the latest main branch:
go install github.com/sumon-ohid/better-paas/backend/cmd/paas@mainMake sure Go's bin directory is on your PATH (usually ~/go/bin):
export PATH="$PATH:$(go env GOPATH)/bin"
paas versionRequires Go 1.22+. The CLI is a standalone module - you do not need to clone the Better-PaaS repo to install it.
From a clone (when developing Better-PaaS itself):
cd better-paas/backend/cmd/paas
go install .Connect (browser flow)
Run one command with your dashboard URL:
paas connect https://paas.example.compaas connect http://localhost:8080
# or
paas connect http://localhost:3000What happens
The CLI checks that your instance is reachable and discovers where the API and dashboard live (see URL discovery below).
It starts a tiny callback server on 127.0.0.1 and opens your browser to the
Authorize CLI page (/connect/agent).
You sign in with your admin token (same as the dashboard login).
Choose an agent name and permission profile, then click Authorize CLI.
The browser redirects back to the CLI. A scoped bpagt_… token is saved to
~/.paas/config.json (file mode 0600). Your admin token is not saved
locally.
Example output:
Connecting to https://paas.example.com …
Opening browser to authorize the CLI…
Waiting for authorization in the browser…
Connected successfully.
URL: https://paas.example.com
Profile: deployer
Agent: my-macbook CLI
Config: /Users/you/.paas/config.json
Try: paas statusCopy the link if the browser doesn't open
If your terminal can't launch a browser, paste the printed URL manually. You have 5 minutes to complete authorization before the session expires.
Use with AI tools (Cursor, Claude Code, Codex)
After paas connect, run one more command:
paas setupThis configures MCP for Cursor (~/.cursor/mcp.json) and Claude Code
(~/.claude/settings.json). Restart your editor, then ask in plain English:
- "List my Better-PaaS apps"
- "Show logs for better-paas"
- "Redeploy better-paas"
- "Deploy https://github.com/me/repo as my-api"
MCP tools available today
| Tool | What it does | Parameters |
|---|---|---|
paas_status | Connection info + app summary | - |
paas_list_apps | List deployed apps | - |
paas_list_projects | List multi-service projects | - |
paas_get_app | App details | app (name or ID) |
paas_get_logs | Runtime logs | app, lines? (default 100) |
paas_deploy | Deploy from Git | name, gitRepo, branch? |
paas_redeploy | Rebuild existing app | app (name or ID) |
The MCP server reads ~/.paas/config.json - no extra env vars needed. What you
can do depends on your connect profile (Observer, Deployer, or
Operator).
MCP tools coming soon
These are on the roadmap; use the REST API or
eval "$(paas env)" + curl until they ship:
| Planned tool | What it will do |
|---|---|
paas_stop_app / paas_start_app | Stop or start an app |
paas_delete_app / paas_rollback | Delete or roll back |
paas_update_app | Change env vars, memory, CPUs |
paas_get_build_logs / paas_get_metrics | Build logs and resource usage |
paas_list_addons / paas_create_addon / paas_attach_addon | Databases and caches |
paas_db_query | Run SQL against an addon |
paas_list_servers / paas_server_info | Target servers |
paas_run_cron / paas_create_backup / paas_list_backups | Cron and backups |
paas_exec | Run a command inside the app container |
paas_add_domain / paas_scan_vulns / paas_prune_docker | Domains, security, cleanup |
Terminal fallback (no MCP)
eval "$(paas env)"Exports PAAS_API_URL and PAAS_TOKEN for shell-based agents that use curl.
Permission profiles
When you authorize, you pick one of three built-in profiles. Each maps to a fixed set of API scopes - you don't need to know scope names unless you use the raw API.
| Profile | Best for | Can do | Cannot do |
|---|---|---|---|
| Observer | Monitoring, read-only assistants | List apps, read logs and metrics | Deploy, stop, delete, manage addons |
| Deployer | AI coding tools, CI on a dev machine | Observer + deploy, redeploy, stop/start apps | Delete apps, manage addons/backups/servers |
| Operator | Full local automation | Deployer + addons, cron, backups, servers, notifications | Create/delete agents, view audit logs |
The default in the browser is Deployer - a good balance for Cursor or Claude Code managing deploys without full admin access.
Daily commands
Wire up AI tools
paas setupCheck connection and list apps
paas statusPrints the connected instance, your agent name/profile, and a table of deployed apps (name, status, ID, URL).
Remove local credentials
paas disconnectDeletes ~/.paas/config.json on this machine. The agent token still exists on
the server until you delete it via the admin API - see
Agent Access.
Help
paas helpAll CLI commands
| Command | Purpose |
|---|---|
paas connect <url> | Browser authorization; saves ~/.paas/config.json |
paas setup | Write MCP config for Cursor and Claude Code |
paas status | List apps in the terminal |
paas env | Print export PAAS_API_URL=… / PAAS_TOKEN=… for shell agents |
paas mcp | MCP server (spawned by your editor - do not run manually) |
paas disconnect | Remove local credentials |
paas version | Print CLI version |
URL discovery
You only pass one URL - your dashboard address. The CLI finds the API automatically.
How it works
- Well-known manifest - the CLI fetches
/.well-known/better-paas.jsonfrom the URL you provide. - Same-origin fallback - if the manifest is missing but
/api/healthresponds on that URL (common when Caddy proxies/apion the same domain), the CLI uses that URL for both dashboard and API. - Local dev -
http://localhost:8080maps the dashboard tohttp://localhost:3000automatically.
Example manifest:
{
"apiUrl": "https://paas.example.com",
"uiUrl": "https://paas.example.com"
}When the dashboard and API are on different hosts (e.g. dashboard at
https://paas.example.com, API at http://203.0.113.10:8080), the frontend
build must expose the API URL in the manifest. Set at frontend build time:
NEXT_PUBLIC_API_URL=http://203.0.113.10:8080Optionally pin the public dashboard URL:
NEXT_PUBLIC_PAAS_UI_URL=https://paas.example.comOn the backend, set PAAS_UI_URL so the API's own manifest points clients
to the right dashboard (useful when someone connects via the raw API URL):
Environment=PAAS_UI_URL=https://paas.example.comAfter changing env vars, rebuild/restart the frontend and restart the backend, then verify:
curl https://paas.example.com/.well-known/better-paas.json
curl https://paas.example.com/connect/agent # should not 404
curl https://paas.example.com/api/health # should return {"status":"healthy",...}See Configuration for all environment variables.
Legacy mode (terminal admin token)
If you cannot use a browser (headless CI, SSH-only server), use legacy mode.
This prompts for your admin token in the terminal and creates an agent via the
API directly. The admin token is not saved - only the resulting agent token
is written to ~/.paas/config.json.
paas connect https://paas.example.com --legacyOr pass the admin token explicitly (avoid in shared shells):
paas connect https://paas.example.com --legacy --admin-token "$ADMIN_TOKEN"Flags:
| Flag | Purpose |
|---|---|
--legacy | Skip browser; use terminal admin-token flow |
--admin-token <token> | Admin token for legacy mode |
--profile observer|deployer|operator | Scope profile (legacy only) |
--name "My CI" | Agent display name (legacy only) |
--ui <url> | Override dashboard URL (rare; discovery usually finds it) |
Environment variables:
| Variable | Purpose |
|---|---|
PAAS_ADMIN_TOKEN | Admin token for legacy mode (alternative to --admin-token) |
PAAS_UI_URL | Default dashboard URL when discovery can't infer it |
Using the token elsewhere
After paas connect, the agent token in ~/.paas/config.json works with any
HTTP client - curl, GitHub Actions, or custom scripts. For AI editors, prefer
paas setup (built-in MCP) over hand-rolled curl.
TOKEN=$(jq -r .token ~/.paas/config.json)
URL=$(jq -r .url ~/.paas/config.json)
curl -H "Authorization: Bearer $TOKEN" "$URL/api/apps"For the full API surface, see the AI Agent API Guide.
Security notes
- Admin token stays on the server during browser connect - you paste it in
the dashboard page, but only the scoped
bpagt_token is saved locally. - Revoke anytime - delete the agent via the admin API;
paas disconnectonly removes the local copy. - Audit trail - every action the agent takes is logged. See Agent Access & Audit Logs.
- Least privilege - prefer Observer or Deployer over Operator unless the tool truly needs addon/backup/server management.
Troubleshooting
"could not reach PaaS at …"
- Check the URL in a browser - the dashboard should load.
- Ensure
/api/healthreturns JSON (directly or via reverse proxy). - For split-host setups, confirm
NEXT_PUBLIC_API_URLis set and the frontend was rebuilt.
Browser opens localhost:3000 on production
- Update to the latest Better-PaaS release (discovery fallback was fixed).
- Redeploy frontend with
/.well-known/better-paas.jsonand/connect/agent. - As a temporary workaround:
paas connect https://paas.example.com --ui https://paas.example.com
/connect/agent returns 404
The authorize page is part of the dashboard. Redeploy the frontend from a current Better-PaaS release.
"timed out waiting for browser authorization"
The 5-minute window expired. Run paas connect again and complete authorization
faster. Don't close the terminal while waiting.
"exchange failed" after authorizing
- Ensure the CLI can reach the API URL (not just the dashboard).
- Check backend logs for connect-session errors.
- Try legacy mode to isolate browser/callback issues.
"Forbidden: missing scope …"
The agent profile doesn't include the scope needed for that API call. Disconnect, delete the agent on the server, and reconnect with a higher profile - or create a custom-scoped token via the API.