CLI
anyport is the terminal client. It talks to the same API the dashboard uses, so the two always agree about what exists.
Install
curl -sfL https://anyport.dev/cli.sh | sh
macOS and Linux, on Intel and ARM. The script verifies the download against the release checksums and installs to /usr/local/bin; set ANYPORT_INSTALL_DIR to put it somewhere else. Windows binaries are on the release page.
Add --init to run anyport init as soon as the install finishes, so setting up is a single command:
curl -sfL https://anyport.dev/cli.sh | sh -s -- --init
It needs a terminal to ask its questions. In a script or a CI job the flag is skipped with a note, and the install still succeeds.
Check it worked:
anyport version
Log in
anyport auth login
This opens your browser and you sign in the way you normally do. The CLI starts a one-shot listener on 127.0.0.1, and the session token is handed back to that local port, so it never travels anywhere else. It is stored in ~/.anyport/config.yaml with 0600 permissions.
There are no API tokens to create or rotate. anyport auth logout revokes the session, and anyport auth whoami shows who you are signed in as.
If you belong to more than one organization, pick one once:
anyport org ls
anyport org use acme
That choice is saved, so no later command needs --org.
Everyday commands
Almost everything is scoped to a project, passed as --project or -p. The cluster is worked out from the project, the same way the dashboard hides it.
anyport project ls
anyport app ls -p demo
anyport app get api -p demo
anyport logs api -p demo
anyport logs streams from the running pods and colours each pod differently, so a rollout with two replicas is readable. --tail sets how much history to show first, --no-follow prints that history and exits, and --timestamps includes the container runtime's own timestamps.
Deploy an image
anyport app deploy api -p demo --image ghcr.io/acme/api:v2
This does what the dashboard does: it writes a draft and then publishes it. If someone has an unpublished draft open in the console, the deploy builds on top of that draft rather than discarding their edit, and it says so. --no-publish stops after the draft.
Secrets
anyport secret ls -p demo
anyport secret set app-config API_URL=https://api.example.com -p demo
anyport secret set app-config --unset OLD_KEY -p demo
Keys you do not mention are preserved. Values are never printed back, by any command, including --json.
Two refusals worth knowing about. Secrets that are not Opaque, such as registry credentials, are managed from the console form that owns their structure. And a secret whose values came back redacted is refused rather than written, because writing redacted values back would blank every key in it.
Domains
anyport domain add app.example.com -p demo
anyport domain verify app.example.com -p demo
anyport domain ls -p demo
domain add prints the exact DNS records the server checks for, rather than guessing at them, because the routing target depends on how your cluster is published. Once the records resolve, binding the domain to an app's port is done in the console.
Open a terminal
anyport shell api -p demo
You get an interactive shell in the app's running container, with your local window size and resizing as you resize the terminal. It is the same session machinery as the console's terminal tab, which means the same rules: every session is recorded, sessions count against your organization's limits, and they end on the same idle and duration timeouts.
The shell that runs is chosen by the server, bash falling back to sh. It is not a command you pass in, because the argv is what gets written to the audit record.
Managed services are reachable the same way, which is the quickest route to a psql prompt against your own database:
anyport service ls -p demo
anyport shell postgres-main -p demo --service
Pick a specific replica with --pod, or a sidecar with --container. For a distroless image, or a container that is crash-looping and therefore has no shell to enter, --debug attaches an ephemeral debug container instead:
anyport shell api -p demo --debug
Kubernetes cannot remove an ephemeral container once it is added. It stays in the pod's spec until the pod is replaced.
Point your own tools at a cluster
anyport shell gets you a prompt inside the cluster. anyport port-forward does the opposite — it brings something in the cluster to your machine, so the tools already on your laptop can reach it:
anyport port-forward postgres-main 5432 --service -p demo
That works against a cluster with no public address and no inbound firewall rule, because the traffic goes over the connection the agent already holds open. There is nothing to expose and no VPN to join.
Take a different local port when the obvious one is occupied, and use --print-url to hand the connection straight to a client:
anyport port-forward postgres-main 15432:5432 --service -p demo
psql "$(anyport port-forward postgres-main 5432 --service --print-url -p demo)"
Apps forward the same way, without --service:
anyport port-forward api 8080 -p demo
The listener binds loopback only and there is no flag to change that: binding every interface would publish a production database to whatever network your laptop is on. A forward is the same grant as a shell — unrestricted access to whatever is listening — so it is recorded, counts against your organization's session limits, and ends on the same idle and duration timeouts.
Scripting
--json works on any read command and prints the decoded payload instead of a table. Empty lists come back as [] rather than null, so a jq pipeline does not break on an organization with nothing in it.
anyport app ls -p demo --json | jq -r '.[].metadata.name'
anyport shell exits with the remote command's exit code, so it composes with && and set -e like any other command.
Tab completion comes from anyport completion <shell> for bash, zsh, fish and PowerShell. On top of the command names, project, app, secret, service, domain and organization names complete by querying the API, along with pod and container names for anyport shell. Each lookup gives up after three seconds, so a shell never hangs on TAB.
Serve it to an AI agent
anyport mcp exposes the same read-only view over the Model Context Protocol, so an agent can answer questions about what you have deployed:
claude mcp add anyport -- anyport mcp
It reuses this CLI's session and cannot write anything. See MCP server.
Configuration
Settings resolve in this order: flag, then environment variable, then ~/.anyport/config.yaml, then the built-in default.
| Flag | Environment | Default | |
|---|---|---|---|
| API | --endpoint | ANYPORT_ENDPOINT | https://server.anyport.dev |
| Console | --web-url | ANYPORT_WEB_URL | https://app.anyport.dev |
| Organization | --org | ANYPORT_ORG | whatever anyport org use saved |
| Session | ANYPORT_TOKEN | the stored login |
These are two different hosts. The API endpoint serves the GraphQL API, and the console URL is only used to open the browser at login. Pointing --endpoint at the console returns a web page instead of JSON, and the CLI says so rather than failing obscurely.
Next steps
- Apps — what a deploy actually changes
- Managed services — what you can open a shell into
- Logs & metrics — the searchable history behind
anyport logs - MCP server — the same view, served to an AI agent