Skip to main content

publishkey — press one key, ship your web app

publishkey looks at your project, figures out what web framework it is (FastAPI, Flask, Streamlit, or Django), works out the right production start command, and deploys it to a cloud host — all from one command (and, soon, one keystroke inside VS Code).

This package is the engine: a small, zero-dependency Python core. Two "faces" sit on top of it — a CLI (in this package) and a VS Code extension (separate) — so the deploy logic is written once and shared.

        publishkey (Python engine)          ← this package
        detect framework · deploy
              ▲                 ▲
        CLI face          VS Code extension  ← the two UIs

Install

pip install publishkey            # once published
# or, for local development:
cd publishkey && pip install -e .

You also need the CLI of whichever provider you deploy to — e.g. Railway:

npm i -g @railway/cli && railway login

Use it

publishkey detect       # what framework is this folder?
publishkey init         # write a .publishkey.json for the project
publishkey providers    # which deploy targets are installed & logged in?
publishkey deploy       # detect → pre-flight checks → confirm → ship
publishkey deploy --yes # skip the confirmation prompt (for scripts/hotkeys)

Typical first run:

$ publishkey deploy
Project: .
  framework      fastapi  (high confidence)
  entry file     main.py
  start command  uvicorn main:app --host 0.0.0.0 --port $PORT

Deploy this fastapi to railway? [y/N] y
Deploying to railway ...
✓ Deploy started on Railway (wrote Procfile). Track it with `railway logs`.

What it detects

Framework Signal Start command it generates
FastAPI FastAPI( + import fastapi uvicorn <module>:<app> --host 0.0.0.0 --port $PORT
Flask Flask( gunicorn <module>:<app> --bind 0.0.0.0:$PORT
Streamlit import streamlit streamlit run <file> --server.port $PORT
Django manage.py + wsgi.py gunicorn <project>.wsgi --bind 0.0.0.0:$PORT

Detection is heuristic but deterministic — same folder in, same answer out. Override anything in .publishkey.json.

Configuration (.publishkey.json)

{
  "provider": "railway",
  "hotkey": "cmd+shift+p",
  "framework": "fastapi",
  "start_command": "uvicorn main:app --host 0.0.0.0 --port $PORT",
  "providers": { "railway": { "service": "web" } }
}

Everything is optional — with no config, publishkey auto-detects and uses Railway.

Providers

Providers are pluggable adapters over a real deployment CLI:

Provider CLI Notes
FastAPI Cloud fastapi FastAPI-native: fastapi login then fastapi deploy. FastAPI apps only, no Procfile.
Railway railway Any framework. Auto-creates the service; writes a Procfile for the start command.
Fly.io flyctl / fly Needs a fly.toml first (fly launch once); then fly deploy.
Render render Deploys an existing service — set providers.render.service (srv-...) in config.
Streamlit git Streamlit Community Cloud (no deploy CLI); opens share.streamlit.io/deploy for your GitHub repo. Streamlit apps only.

"not installed" next to a provider just means that provider's CLI isn't on your PATH — e.g. railway needs npm i -g @railway/cli. publishkey shells out to each provider's own CLI.

Adding another (Render, AWS App Runner, ...) is a small file — implement is_installed, is_authenticated, and deploy against the injectable command runner, then register it in providers/__init__.py. That runner is why the whole engine is unit-testable without ever spawning a real deploy. Buildpack hosts share the base class's ensure_procfile helper, so a new adapter is often just the CLI-specific glue.

Set the provider (and per-provider options) in .publishkey.json:

{ "provider": "fly", "providers": { "fly": { "app": "my-app" } } }

Design principles

  • Zero required dependencies — pure standard library, Python 3.8+.
  • Deterministic & testable — every shell-out goes through an injectable Runner; tests use a FakeRunner that scripts responses.
  • One engine, many faces — the CLI and the VS Code extension call the same functions; deploy logic lives in exactly one place.

Run the tests

python -m unittest discover -s tests

Publishing to PyPI

Releases go out via GitHub Actions using Trusted Publishing (OIDC) — no tokens stored. Bump version in pyproject.toml, then run the "Publish publishkey to PyPI" workflow from the Actions tab. One-time PyPI setup is documented in .github/workflows/publish-publishkey.yml.

Roadmap

  • VS Code extension face (native keybinding → the "publish key" experience).
  • More providers: Fly.io, Render, AWS App Runner.
  • Deploy history + one-click rollback (premium tier).
  • Env-var / secrets management UI (premium tier).

Metadata

Release files for publishkey 0.4.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 publishkey 0.4.0
File Size Uploaded
publishkey-0.4.0.tar.gz 23.7 kB Details

Built distribution (wheel)

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

Total release size: 47.5 kB

Release files / publishkey-0.4.0.tar.gz

Download URL publishkey-0.4.0.tar.gz
Size 23.7 kB
Tags Source
SHA-256 checksum
How to use checksums
1a4e94ae9a4d70cf3bee6ce6f9431c96b6d8ab1b6aae05be135ecb3cedef1507
BLAKE2b-256 checksum
How to use checksums
cb8d08fdc1a6c2fad4160d55df0ee274f0f0959316e83da56b4b5e9b9feb9428
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.

Transparency log

Release files / publishkey-0.4.0-py3-none-any.whl

Download URL publishkey-0.4.0-py3-none-any.whl
Size 23.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0e0c5937e0bd5c32da4a5567a071f36943b9e3c8e5d4e3c04e81fd807ad0737c
BLAKE2b-256 checksum
How to use checksums
5cc6bfdaf0ea15e1c10a7a674205d35bda486ae51105d66c007fbdf796966159
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

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