This guide describes the current Pkwn CLI. Provider behavior and consumer-account terms remain vendor-controlled.

Make your coding-agent sessions durable.

Pkwn is a local or VPS-hosted runtime that exposes direct Claude, Codex, and Gemini coding-plan connections through a terminal UI, persistent hub-style sessions, and an OpenAI-compatible API.

3 providersClaude, Codex, Gemini
2 SQLite storescredentials and transcripts
3 permission tierssafe, edit, full

Quick start

Pkwn requires Node 22.5 or newer because it uses the built-in node:sqlite module. Install the punakawan package, initialize its home, then authenticate only the backends you need.

npm install -g punakawan
pkwn init

# choose a backend. Gemini requires the environment setup below first.
pkwn auth login claude
pkwn auth login codex
# after setting PKWN_GEMINI_OAUTH_CLIENT_ID and _SECRET:
pkwn auth login gemini

# start the terminal UI; it self-starts the daemon if needed
pkwn

First successful session: run /connect in the TUI, choose a logged-in backend and a project directory, then type your first request. The session is created lazily at that first message.

Authenticate providers

Pkwn runs its own authorization-code + PKCE flow. It stores its credentials locally and does not read or write a vendor CLI's credential files.

BackendAccount pathLogin behavior
ClaudeClaude Pro / Max OAuthOpen the printed URL and paste the CODE#STATE displayed after approval.
CodexChatGPT Plus / Pro OAuthThe localhost callback completes automatically.
GeminiGoogle AI Pro / Ultra OAuthSet the Gemini OAuth client environment variables, then complete a local callback.

Gemini OAuth environment

Before Gemini login or daemon startup, provide the Google OAuth client values. The CLI README identifies the equivalent constants in Gemini CLI's Code Assist implementation.

export PKWN_GEMINI_OAUTH_CLIENT_ID="...apps.googleusercontent.com"
export PKWN_GEMINI_OAUTH_CLIENT_SECRET="GOCSPX-..."
pkwn auth login gemini
pkwn auth status

Daemon and configuration

The daemon defaults to 127.0.0.1:8787. Credentials and session databases live beneath ~/.pkwn/ unless PKWN_HOME changes it. Both databases use WAL mode so the daemon and one-off CLI commands can safely access them together.

{
  "port": 8787,
  "bindHost": "127.0.0.1",
  "defaultTurnTimeoutMs": 1200000,
  "maxTurnRetries": 2,
  "backends": {
    "claude": {},
    "codex": { "maxConcurrency": 1 },
    "gemini": {}
  }
}

Environment variables override the file: PKWN_HOME, PKWN_PORT, PKWN_BIND_HOST, PKWN_API_KEY, PKWN_TURN_TIMEOUT_MS, and PKWN_MAX_RETRIES.

Remote bind requires authentication. When bindHost is not 127.0.0.1, Pkwn refuses to start without PKWN_API_KEY. Prefer an SSH tunnel or authenticated TLS reverse proxy over exposing the daemon directly.

VPS deployment

sudo mkdir -p /opt/pkwn /etc/pkwn
sudo npm install --prefix /opt/pkwn punakawan
echo 'PKWN_API_KEY=change-me' | sudo tee /etc/pkwn/pkwn.env
sudo chmod 600 /etc/pkwn/pkwn.env
sudo cp /opt/pkwn/node_modules/punakawan/systemd/pkwn.service /etc/systemd/system/pkwn@$(whoami).service
sudo systemctl enable --now pkwn@$(whoami)

Sessions and terminal UI

The Ink terminal UI is the human interface. It starts with no active conversation; the last backend/model choice for the current directory can be preselected, but resuming an old conversation is always explicit.

/connect [backend] [cwd] [model]

Pick a backend, model, and working directory; create nothing until the first message.

/model [model-id]

Browse connected providers and their available models, or set the current model directly.

/permission [safe|edit|full]

Set the active session's approval tier.

/mock [on|off]

Opt into placeholder image/video generation for data-less UI work.

/resume [session-id]

Reattach to a stored conversation; omit the id for the picker.

/search <text>

Search persisted transcript text, tool calls, results, and diffs.

Use /sessions to list sessions, /stop to abort an in-flight turn, /new for a fresh conversation with the current setup, and /rm to delete a session.

/skills lists global and project-local skills; /schedule, /schedules, and /unschedule manage automations; /help shows the full command list. /clear removes every session only after confirmation, while /exit and /quit detach from the UI without stopping the daemon.

Roles and subagents

Every backend can use the same isolated child-session primitive. spawn_subagent sends a self-contained task to a persisted child session and returns only that child's final answer to the parent. Children inherit the parent's working directory and permission unless narrowed, are visible in the session list, and cannot spawn their own children.

The related delegate tool runs that child as one of Pkwn's built-in roles: planner, advisor, coder, tester, designer, or reviewer. A role may use a different provider/model from the lead, but its requested permission can only narrow the lead's tier. Inspect available personas at GET /v1/roles or create a session with a role field.

OpenAI-compatible API

Use a model in the form <backend>:<model-id>. The colon is required; the model id may be empty to select the backend default. Responses return pkwn_session_id; pass it back as session_id to continue the persisted conversation.

curl http://127.0.0.1:8787/v1/chat/completions \
  -H "authorization: Bearer $PKWN_API_KEY" \
  -H 'content-type: application/json' \
  -d '{
    "model": "claude:",
    "cwd": "/home/me/my-project",
    "messages": [{"role":"user","content":"add a health check endpoint"}]
  }'

Set stream to true for OpenAI-style SSE chunks. Set ephemeral to true to avoid retaining a session after the turn. The permission field accepts safe, edit, or full.

Session API

# create a durable session
curl -X POST http://127.0.0.1:8787/v1/sessions \
  -d '{"backend":"codex","cwd":"/srv/app","permission":"edit"}'

# send a turn, then inspect or stop it
curl -X POST http://127.0.0.1:8787/v1/sessions/<id>/messages \
  -d '{"text":"run the test suite and fix failures"}'
curl http://127.0.0.1:8787/v1/sessions/search?q=healthz
curl -X POST http://127.0.0.1:8787/v1/sessions/<id>/stop

Raw control and adapter verification

# Stream raw JSON AgentEvents from a session over WebSocket
pkwn sessions attach <id>
pkwn sessions list
pkwn sessions search <text>
pkwn sessions stop <id>
pkwn sessions rm <id>

# Test one direct provider turn without the daemon or persisted session
pkwn verify claude "list the files in this directory" ~/some-project

verify streams normalized events from one real adapter turn and finishes with OK or FAILED. Use it after a provider changes a server-side contract and before wiring that backend into production.

Telegram gateway

The optional Telegram process is a client of the daemon API, not a second process with direct database access. Each approved chat binds to a session created lazily on its first message.

export PKWN_TELEGRAM_BOT_TOKEN="123456:ABC-your-bot-token"
export PKWN_TELEGRAM_BACKEND="claude"
export PKWN_TELEGRAM_CWD="/home/me/my-project"
pkwn gateway telegram

It is deny-by-default: without PKWN_TELEGRAM_ALLOWED_CHAT_IDS, every sender is refused and shown its numeric chat id. Set that comma-separated allowlist, then restart the gateway. In-chat commands include /new, /id, /model, /permission, and /mock.

For systemd production use, install /opt/pkwn/node_modules/punakawan/systemd/pkwn-gateway-telegram.service alongside the daemon unit; the gateway self-starts the daemon for interactive use when none is available.

Schedules and automation

Schedules run inside the daemon on a five-field UTC cron expression. Each schedule receives one persistent session, created on first fire and reused later, so the result is a normal inspectable conversation rather than a disposable job.

curl -X POST http://127.0.0.1:8787/v1/schedules \
  -H 'content-type: application/json' \
  -d '{
    "cron": "0 8 * * *",
    "prompt": "check overnight CI runs and summarize any failures",
    "backend": "claude",
    "cwd": "/home/me/my-project"
  }'

pkwn schedules list
pkwn schedules run <id>
pkwn schedules rm <id>

The TUI equivalents are /schedule, /schedules, and /unschedule. Optional schedule fields include model, permission, sessionId, and notifyTelegramChatId.

Cron syntax is minute hour day-of-month month day-of-week, with *, lists, ranges, and steps. Times are always UTC; there is no per-schedule timezone or DST conversion.

Skills and mock assets

Skills

Pkwn reads the open agentskills.io format from <pkwnHome>/skills/<name>/SKILL.md and <cwd>/.pkwn/skills/<name>/SKILL.md. Project-local skills win on a name collision. Every turn receives the lightweight name/description manifest; the model reads a full skill only when it needs it.

---
name: debug-flaky-e2e-tests
description: Use this skill when an end-to-end test fails intermittently.
---

1. Rerun the test several times before assuming the failure is deterministic.
2. Check shared ports, files, and global singletons.

Mock-asset mode

/mock on enables an opt-in, per-session tool for filling data-less UI with placeholder media. It requires edit or full permission and writes only inside the session's working directory.

  • Images use the Gemini Nano Banana image model and require a logged-in Gemini credential in the session's credential home.
  • Video uses an external authenticated wan CLI on PATH. Install it separately before requesting video generation.

For video, install and authenticate Wan first—for example npm install -g @wan-ai/cli followed by wan auth login. Image and video generation use their respective provider quota; prefer images and use video only for genuine hero or background motion.

Provider and security notes

Pkwn intentionally makes direct connections on behalf of your subscription accounts. This is a material tradeoff, not an API-service substitute. Provider consumer terms can restrict third-party OAuth/token use or building API-like services on top of consumer accounts; traffic requirements can also change without notice.

Operate conservatively. Review the current provider terms, avoid exposing a shell-capable daemon to the public internet, use a dedicated API key for non-loopback access, and select the lowest permission tier that completes the task. Do not point it at an account you cannot afford to have restricted.

Codex refresh tokens are unsafe to refresh concurrently, so Pkwn serializes Codex turns by default. Independent credential homes with independently logged-in accounts are the route to intentional isolation.

Every turn on one session is serialized. Transient failures use bounded exponential backoff; rate limits surface immediately instead of spending further retries. Interrupted sessions remain identifiable after a daemon restart, and the persisted history is replayed into the next backend turn.

Ready to work?

Start the TUI, choose a backend, and make the first session. Keep this guide open when you move from local use to a VPS, a gateway, or an API integration.

Return to product overview