Better-PaaS
Guides

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.com or http://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:

On your laptop
go install github.com/sumon-ohid/better-paas/backend/cmd/paas@latest

Pin 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@main

Make sure Go's bin directory is on your PATH (usually ~/go/bin):

export PATH="$PATH:$(go env GOPATH)/bin"
paas version

Requires 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):

On your laptop
cd better-paas/backend/cmd/paas
go install .

Connect (browser flow)

Run one command with your dashboard URL:

Production
paas connect https://paas.example.com
Local dev
paas connect http://localhost:8080
# or
paas connect http://localhost:3000

What 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 status

Copy 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 setup

This configures MCP for Cursor (~/.cursor/mcp.json) and Claude Code (~/.claude/settings.json). Restart your editor, then ask in plain English:

MCP tools available today

ToolWhat it doesParameters
paas_statusConnection info + app summary-
paas_list_appsList deployed apps-
paas_list_projectsList multi-service projects-
paas_get_appApp detailsapp (name or ID)
paas_get_logsRuntime logsapp, lines? (default 100)
paas_deployDeploy from Gitname, gitRepo, branch?
paas_redeployRebuild existing appapp (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 toolWhat it will do
paas_stop_app / paas_start_appStop or start an app
paas_delete_app / paas_rollbackDelete or roll back
paas_update_appChange env vars, memory, CPUs
paas_get_build_logs / paas_get_metricsBuild logs and resource usage
paas_list_addons / paas_create_addon / paas_attach_addonDatabases and caches
paas_db_queryRun SQL against an addon
paas_list_servers / paas_server_infoTarget servers
paas_run_cron / paas_create_backup / paas_list_backupsCron and backups
paas_execRun a command inside the app container
paas_add_domain / paas_scan_vulns / paas_prune_dockerDomains, 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.

ProfileBest forCan doCannot do
ObserverMonitoring, read-only assistantsList apps, read logs and metricsDeploy, stop, delete, manage addons
DeployerAI coding tools, CI on a dev machineObserver + deploy, redeploy, stop/start appsDelete apps, manage addons/backups/servers
OperatorFull local automationDeployer + addons, cron, backups, servers, notificationsCreate/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 setup

Check connection and list apps

paas status

Prints the connected instance, your agent name/profile, and a table of deployed apps (name, status, ID, URL).

Remove local credentials

paas disconnect

Deletes ~/.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 help

All CLI commands

CommandPurpose
paas connect <url>Browser authorization; saves ~/.paas/config.json
paas setupWrite MCP config for Cursor and Claude Code
paas statusList apps in the terminal
paas envPrint export PAAS_API_URL=… / PAAS_TOKEN=… for shell agents
paas mcpMCP server (spawned by your editor - do not run manually)
paas disconnectRemove local credentials
paas versionPrint CLI version

URL discovery

You only pass one URL - your dashboard address. The CLI finds the API automatically.

How it works

  1. Well-known manifest - the CLI fetches /.well-known/better-paas.json from the URL you provide.
  2. Same-origin fallback - if the manifest is missing but /api/health responds on that URL (common when Caddy proxies /api on the same domain), the CLI uses that URL for both dashboard and API.
  3. Local dev - http://localhost:8080 maps the dashboard to http://localhost:3000 automatically.

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:

frontend/.env
NEXT_PUBLIC_API_URL=http://203.0.113.10:8080

Optionally pin the public dashboard URL:

NEXT_PUBLIC_PAAS_UI_URL=https://paas.example.com

On 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):

/etc/systemd/system/better-paas-backend.service
Environment=PAAS_UI_URL=https://paas.example.com

After 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 --legacy

Or pass the admin token explicitly (avoid in shared shells):

paas connect https://paas.example.com --legacy --admin-token "$ADMIN_TOKEN"

Flags:

FlagPurpose
--legacySkip browser; use terminal admin-token flow
--admin-token <token>Admin token for legacy mode
--profile observer|deployer|operatorScope profile (legacy only)
--name "My CI"Agent display name (legacy only)
--ui <url>Override dashboard URL (rare; discovery usually finds it)

Environment variables:

VariablePurpose
PAAS_ADMIN_TOKENAdmin token for legacy mode (alternative to --admin-token)
PAAS_UI_URLDefault 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.

Read token from config (jq required)
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 disconnect only 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/health returns JSON (directly or via reverse proxy).
  • For split-host setups, confirm NEXT_PUBLIC_API_URL is 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.json and /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.


Next steps

On this page