Skip to main content

appliku

PyPI version License: MIT Python 3.10+

Python CLI and SDK for the Appliku platform.

This package gives you:

  • a CLI for common Appliku workflows
  • a Python SDK for scripting and integrations

Install uv

This project uses uv for local development and is easiest to use with uv for both the CLI and SDK examples below.

macOS and Linux:

curl -LsSf https://astral.sh/uv/install.sh | sh

Windows PowerShell:

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

After installation, restart your shell or verify:

uv --version

Install appliku

For CLI usage, install the package as a tool:

uv tool install appliku

Then verify:

appliku --help

For SDK usage inside a Python project:

uv add appliku

If you prefer pip, this also works:

pip install appliku

Claude Code Skill

If you use Claude Code, install the Appliku skill to give the agent full knowledge of every CLI command, SDK method, and common workflow — automatically loaded in every session:

npx skills add appliku/skill -g -a claude-code

Source: github.com/appliku/skill

Authentication

The CLI supports two login methods:

  1. Browser-based device flow:
appliku login
  1. Direct token login:
appliku login --token YOUR_API_TOKEN

Useful auth commands:

appliku whoami
appliku logout

The SDK resolves credentials in this order:

  1. Appliku(token="...")
  2. APPLIKU_TOKEN environment variable
  3. ~/.config/appliku/config.toml

Example environment variable setup:

export APPLIKU_TOKEN=YOUR_API_TOKEN

CLI Quick Start

List your teams:

appliku teams list

Inspect one team:

appliku teams get my-team

List applications in a team:

appliku apps list --team my-team

Show the latest deployment for an app:

appliku deployments latest --team my-team --app 42

List domains for an app:

appliku domains list --team my-team --app 42

List datastores for an app:

appliku datastores list --team my-team --app 42

Every list-style command also supports JSON output:

appliku apps list --team my-team --output json

CLI Command Reference

teams

Manage your Appliku teams.

appliku teams list
appliku teams get my-team

apps

Manage applications and fetch logs.

# List apps in a team
appliku apps list --team my-team

# Create from GitHub or GitLab. Select exactly one server or cluster target.
appliku apps create github acme/example -t my-team -n example -b main --server 12
appliku apps create gitlab group/example -t my-team -n example -b main --cluster 7

# Create from custom Git. Read credentials from files instead of command arguments.
appliku apps create custom -t my-team -n example -b main --server 12 \
  --git-url-file repository-url.txt --private-key-file ~/.ssh/example_deploy_key

# Deploy (clone + build + release), or restart without a build.
appliku apps deploy --team my-team --app 42
appliku apps restart --team my-team --app 42
appliku apps restart --team my-team --app 42 --check   # is a restart possible now?

# Fetch logs — one command for any deployment mode, one or more processes.
# With no --process it returns logs for all of the app's processes.
appliku apps logs --team my-team --app 42
appliku apps logs --team my-team --app 42 --process web --process celery --tail 200

# `apps service-logs` is deprecated — use `apps logs -p <service>` instead.
# `apps delete-config-var` is deprecated — use `config unset KEY` instead.

# Fetch nginx access logs for a domain
appliku apps nginx-logs --team my-team --app 42 --domain example.com --tail 100

# Fetch load balancer logs for a domain
appliku apps load-balancer-logs --team my-team --app 42 --domain example.com --tail 100

Application creation requires exactly one positive --server or --cluster ID. Add --static-site for a static site and --output json for one sanitized JSON object. For custom Git, use --git-url-file - to read a credential-bearing URL from standard input. The command never prints the URL or private key.

Create makes the application and starts the initial appliku.yml inspection. It does not deploy. Run appliku apps deploy --team TEAM --app ID after setup is complete.

config

Manage an application's environment variables, Heroku style.

Heroku Appliku
heroku config appliku config list -t TEAM -a APP
heroku config --json appliku config list -t TEAM -a APP -o json
heroku config --shell appliku config list -t TEAM -a APP -o shell
heroku config:get KEY appliku config get KEY -t TEAM -a APP
heroku config:set A=1 B=2 appliku config set A=1 B=2 -t TEAM -a APP
heroku config:unset A B appliku config unset A B -t TEAM -a APP
appliku config list -t my-team -a 42             # table: name, value, source, mode
appliku config list -t my-team -a 42 -o json     # {"NAME": "value", ...}
appliku config list -t my-team -a 42 -o shell    # NAME='value' lines (POSIX shell syntax)
appliku config get DATABASE_URL -t my-team -a 42 # prints the value only
appliku config set DEBUG=false URL='p://a?b=c' -t my-team -a 42
appliku config set DEBUG=false -t my-team -a 42 --deploy   # save, then start a deployment
appliku config set DEBUG=false -t my-team -a 42 --restart  # save, then restart without a build
appliku config unset OLD_VAR OTHER -t my-team -a 42
  • Changes take effect on the next deployment or restart. Nothing restarts on save. Pass --deploy (a full build) or --restart (no build: the running image starts again with the new values), or run appliku apps deploy / appliku apps restart. Use --deploy for variables read during the build (for example NEXT_PUBLIC_*): a restart keeps their old values. The two flags cannot be combined, and neither runs when nothing was written.
  • set merges: variables you do not name are left alone. Values are split on the first =.
  • set refuses an empty value (on Appliku that would delete the variable — use unset), the same name twice, and, for now, values with leading or trailing whitespace (the API would strip it).
  • Variables defined in appliku.yml cannot be changed here. Database- or domain-linked variables are only replaced with a static value when you pass --replace-links.
  • These checks before writing are advisory: they use the state at the time of the check. The API's answer is verified, and a key the API did not apply makes the command fail, but a variable that someone links to a database between the check and the write is replaced without warning.
  • unset skips names that are not set, with a warning.
  • get exits 1 when the variable is not set (Heroku prints an empty line).
  • set and unset need an API token with both env_vars read and update permissions; --deploy and --restart also need deployments create.
  • list shows values as they resolve now. It does not show volume variables (<NAME>_ROOT, <NAME>_URL) added at deployment time.
  • -o shell output is for eval in a POSIX shell. It is not a dotenv format.

deployments

Inspect deployments and their logs.

# List deployments for an app
appliku deployments list --team my-team --app 42

# Show the latest deployment
appliku deployments latest --team my-team --app 42

# Fetch logs for a specific deployment
appliku deployments logs --team my-team --id 1234

domains

Manage custom domains.

appliku domains list   --team my-team --app 42
appliku domains create --team my-team --app 42 --domain example.com
appliku domains delete --team my-team --app 42 --id 7
appliku domains check-dns --team my-team --app 42 --domain example.com

datastores

Manage attached datastores (databases, caches, etc.).

appliku datastores list    --team my-team --app 42
appliku datastores start   --team my-team --app 42 --id 5
appliku datastores stop    --team my-team --app 42 --id 5
appliku datastores restart --team my-team --app 42 --id 5
appliku datastores delete  --team my-team --app 42 --id 5

volumes

Manage persistent volumes.

appliku volumes list   --team my-team --app 42
appliku volumes delete --team my-team --app 42 --id 3

crons

Manage cron jobs.

appliku crons list   --team my-team --app 42
appliku crons delete --team my-team --app 42 --id 8

clusters

Manage Docker Swarm clusters.

appliku clusters list   --team my-team
appliku clusters delete --team my-team --id 2

clusters list reports a Ready column: a cluster can host a new application only when its primary manager has finished setup.

servers

Inspect servers.

appliku servers list --team my-team
appliku servers get  --team my-team --id 10

Both report a Ready column — a server is ready when it is active and its setup finished. apps create refuses a target that is not ready, so pick the ID from here:

appliku servers list --team my-team --output json | jq '[.[] | select(.ready)]'

invites

Manage team invitations.

appliku invites list   --team my-team
appliku invites delete --team my-team --id 4

migrations

Manage and inspect database migrations.

appliku migrations list --team my-team
appliku migrations logs --team my-team --id 99

SDK Quick Start

Create a client using a saved token or APPLIKU_TOKEN:

from appliku import Appliku

client = Appliku()

Or pass the token explicitly:

from appliku import Appliku

client = Appliku(token="YOUR_API_TOKEN")

List teams:

from appliku import Appliku

client = Appliku()

for team in client.teams.list():
    print(team.team_path, team.plan)

Get one team and list its apps:

from appliku import Appliku

client = Appliku()
team = client.teams.get("my-team")
apps = client.apps.list("my-team")

print(team.name)
for app in apps:
    print(app.id, app.name, app.last_deployment_status)

Get the latest deployment and fetch its logs:

from appliku import Appliku

client = Appliku()
latest = client.deployments.latest("my-team", 42)
logs = client.deployments.logs("my-team", latest.id)

print(latest.status)
for entry in logs:
    print(entry.log)

Work with domains and datastores:

from appliku import Appliku

client = Appliku()

domains = client.domains.list("my-team", 42)
datastores = client.datastores.list("my-team", 42)

print([d.domain for d in domains])
print([db.name for db in datastores])

apps restart starts the images of the running deployment again with the current environment variables and process settings. It pulls no new code, builds nothing and does not run the release command. Variables used during the build (for example NEXT_PUBLIC_*, or anything the build command reads) keep the values baked into the image; run apps deploy to change them. --check only asks whether a restart is possible now and prints the reason when it is not (exit 1). The command needs the backend with the restart endpoint (it works once that is on production), and the first restart of an application needs one full deployment made with that backend. Static sites have nothing to restart.

SDK Reference

All resources are accessed as properties on the Appliku instance.

apps

client.apps.list("my-team")
client.apps.get("my-team", app_id=42)
client.apps.create_from_github(
    "my-team", "acme/example", name="example", branch="main", server=12
)
client.apps.create_from_gitlab(
    "my-team", "group/example", name="example", branch="main", cluster=7
)
client.apps.create_from_custom_git(
    "my-team",
    "git@example.com:team/example.git",
    name="example",
    branch="main",
    server=12,
    private_key=private_key_contents,
)
client.apps.update("my-team", app_id=42, branch="develop")
client.apps.delete("my-team", app_id=42)
client.apps.restart("my-team", app_id=42)               # {success, deployment_id}
client.apps.restart_availability("my-team", app_id=42)  # {available, reason, source_number_id}
client.apps.deploy("my-team", app_id=42)

# Config vars. get returns {"env_vars": [...]}; set takes a flat mapping.
vars = client.apps.get_config_vars("my-team", app_id=42)

# Merges: vars not named here are left alone. An empty ("" or None) value
# DELETES that variable rather than blanking it.
client.apps.set_config_vars("my-team", app_id=42, vars={"DEBUG": "false"})
client.apps.set_config_vars("my-team", app_id=42, vars={"DEBUG": ""})  # deletes DEBUG

# Logs — get_logs takes a list of processes (None = all), works on any mode.
logs = client.apps.get_logs("my-team", app_id=42, processes=["web", "celery"], tail=100)
print(logs)

# get_service_logs is a deprecated shim that delegates to get_logs.
logs = client.apps.get_service_logs("my-team", app_id=42, service="web", tail=100)

# Nginx / load balancer logs
logs = client.apps.get_nginx_logs("my-team", app_id=42, domain="example.com", tail=100)
logs = client.apps.get_load_balancer_logs("my-team", app_id=42, domain="example.com", tail=100)

deployments

client.deployments.list("my-team", app_id=42)
client.deployments.get("my-team", app_id=42, deployment_id=1234)
client.deployments.latest("my-team", app_id=42)
client.deployments.logs("my-team", deployment_id=1234)

domains

client.domains.list("my-team", app_id=42)
client.domains.get("my-team", app_id=42, domain_id=7)
client.domains.create("my-team", app_id=42, domain="example.com")
client.domains.delete("my-team", app_id=42, domain_id=7)

result = client.domains.check_dns("my-team", app_id=42, domain="example.com")
print(result.status)

datastores

client.datastores.list("my-team", app_id=42)
client.datastores.get("my-team", app_id=42, datastore_id=5)
client.datastores.create("my-team", app_id=42, name="mydb", kind="postgresql")
client.datastores.delete("my-team", app_id=42, datastore_id=5)
client.datastores.start("my-team", app_id=42, datastore_id=5)
client.datastores.stop("my-team", app_id=42, datastore_id=5)
client.datastores.restart("my-team", app_id=42, datastore_id=5)

volumes

client.volumes.list("my-team", app_id=42)
client.volumes.get("my-team", app_id=42, volume_id=3)
client.volumes.create("my-team", app_id=42, name="uploads", mount_path="/app/uploads")
client.volumes.update("my-team", app_id=42, volume_id=3, mount_path="/app/media")
client.volumes.delete("my-team", app_id=42, volume_id=3)

cron_jobs

client.cron_jobs.list("my-team", app_id=42)
client.cron_jobs.create("my-team", app_id=42, schedule="0 * * * *", command="python manage.py clearsessions")
client.cron_jobs.update("my-team", app_id=42, cron_id=8, schedule="30 2 * * *")
client.cron_jobs.delete("my-team", app_id=42, cron_id=8)

clusters

client.clusters.list("my-team")
client.clusters.get("my-team", cluster_id=2)
client.clusters.create("my-team", name="prod-cluster")
client.clusters.delete("my-team", cluster_id=2)

servers

client.servers.list("my-team")
client.servers.get("my-team", server_id=10)

invites

client.invites.list("my-team")
client.invites.create("my-team", email="colleague@example.com")
client.invites.delete("my-team", invite_id=4)

migrations

client.migrations.list("my-team")
client.migrations.run("my-team", app_id=42, command="python manage.py migrate")
client.migrations.logs("my-team", migration_id=99)

Error Handling

The SDK raises typed exceptions:

from appliku import Appliku, AuthenticationError, NotFoundError

client = Appliku()

try:
    client.teams.get("missing-team")
except AuthenticationError:
    print("Invalid or missing token")
except NotFoundError as exc:
    print(exc)

Main exception types:

  • AplikuError
  • AuthenticationError
  • AuthorizationError
  • NotFoundError
  • ValidationError
  • RateLimitError
  • ServerError

Every exception carries status_code and response, the decoded JSON body. The body is whatever the API sent, so it may be a dict, a list of messages, or a string; str(exc) is always a readable message regardless of which.

On the command line these are printed as a single line and exit with status 1:

$ appliku apps load-balancer-logs --team my-team --app 42 --domain example.com
Error: Load balancer logs are only available for cluster-mode applications. This
application runs on a single server; use application logs or nginx logs instead.

Only unexpected failures print a traceback, so a traceback from the CLI is worth reporting as a bug.

Development

Create or sync the local environment:

uv sync

Run tests:

UV_CACHE_DIR=/tmp/uv-cache uv run pytest

Run the CLI from the repo:

UV_CACHE_DIR=/tmp/uv-cache uv run appliku --help

Regenerate models and generated client code from the OpenAPI schema:

./scripts/codegen.sh

License

MIT

Metadata

Release files for appliku 0.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for appliku 0.7.0
File Size Uploaded
appliku-0.7.0.tar.gz 279.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for appliku 0.7.0
File Interpreter ABI Platform
appliku-0.7.0-py3-none-any.whl Python 3 none any Details

Total release size: 932.0 kB

Release files / appliku-0.7.0.tar.gz

Download URL appliku-0.7.0.tar.gz
Size 279.8 kB
Tags Source
SHA-256 checksum
How to use checksums
cb5da96d40f4741730da2bf45645e5381d7d0f0568890b43024977d640575878
BLAKE2b-256 checksum
How to use checksums
8bbd8be0e76ebb19223a869d2a62d6bd435669e0dec5a914a1be6d4eecce38bf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"44","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / appliku-0.7.0-py3-none-any.whl

Download URL appliku-0.7.0-py3-none-any.whl
Size 652.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6a03da4a510c71e7db0b0a26bc55cd0612cc64228b77909452e503a779556519
BLAKE2b-256 checksum
How to use checksums
0348fefd7763c4f3c08e3ae45423287f0a713f55aac0d74f95f6012dfbce56dc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"44","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.7.0 This release

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page