Metadata-Version: 2.4
Name: painapple-code
Version: 1.0.0rc6
Summary: WebUI wrapper for Claude Code with auto journal - PWA frontend, REST + WebSocket API
Author-email: Michal Booth-Wrotkowski <michal@boothw.com>
License-Expression: AGPL-3.0-or-later
Project-URL: Homepage, https://github.com/wrotek/painapple-code
Project-URL: Source, https://github.com/wrotek/painapple-code
Project-URL: Issues, https://github.com/wrotek/painapple-code/issues
Keywords: claude,claude-code,websocket,bridge,pwa,ipad,remote,ai
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Web Environment
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastapi>=0.104.0
Requires-Dist: uvicorn[standard]>=0.24.0
Requires-Dist: websockets>=12.0
Requires-Dist: duckdb>=1.0.0
Requires-Dist: pytz
Requires-Dist: pyyaml>=6.0
Requires-Dist: Pillow>=10.0
Requires-Dist: python-multipart>=0.0.6
Requires-Dist: cryptography>=41.0
Requires-Dist: httpx>=0.28.0
Requires-Dist: httpcore>=1.0
Requires-Dist: questionary>=2.1
Requires-Dist: claude-agent-sdk<0.3,>=0.2.111
Dynamic: license-file

# pAInapple Code

**Claude Code, from any browser.** A self-hosted bridge that runs the [Claude Code](https://github.com/anthropics/claude-code) CLI on your machine and serves a fast, installable web UI on top — streaming chat, interactive permission cards, a real terminal, git tools, and an automatic journal of every turn.

No cloud middleman: your machine, your Claude account, your data.

**[Documentation](https://wrotek.github.io/painapple-code/)** · [Install](https://wrotek.github.io/painapple-code/getting-started/install-pip/) · [Features](https://wrotek.github.io/painapple-code/features/) · [Security](https://wrotek.github.io/painapple-code/getting-started/security/)

![pAInapple Code with the file explorer and git widget open over a session](docs-site/assets/overview.png)

The desktop browser is the primary target, but it installs as a PWA on iOS and Android too — roughly a third of this app was written from a phone, and most of the rest from an iPad with a hardware keyboard.

## Before you start

pAInapple Code hands a browser tab full control of a Claude Code instance on your machine. That's the point — but it deserves three honest paragraphs before the quick start.

**You stay in the loop.** By default the bridge drives Claude through the official **Agent SDK** in **Ask mode**: every tool call pauses on an approve/deny card — with a readable preview of the edit or command — until you decide. From there you can loosen per session as trust grows: **Accept Edits**, **Auto** (Claude's own classifier gates each call), **Plan** (read-only), or full bypass when you're sandboxed and feeling brave. Permission mode and model switch live, mid-turn, without restarting the session. → [Permissions guide](https://wrotek.github.io/painapple-code/guides/permissions-and-thinking/)

**Isolate the autonomous modes.** The embedded terminal is a real PTY, and anything Claude is approved to run executes as the user who started the server — prompt injection and poisoned packages are real risks for *any* coding agent. Approval cards keep the interactive modes reasonable, but if you want Claude working autonomously, run the bridge in a container or VM. `painapple docker` (below) makes that the easy path.

**Network defaults are conservative.** The server binds `127.0.0.1` over plain HTTP; non-loopback binds auto-enable TLS with a self-signed cert. Auth is a single-password gate — fine on a home network or VPN, but for anything public put your own reverse proxy in front. → [Security notes](https://wrotek.github.io/painapple-code/getting-started/security/)

## What it is, and what it isn't

**It is** a thin wrapper around Claude Code — every prompt streams through the official CLI/Agent SDK, and any session you start here can be resumed in the plain CLI with `claude --resume <id>`. It doesn't rewrite your prompts, inject planning steps, or change Claude's behavior.

**It is not** a hosted service. You run it, on your hardware, with your own Claude account.

**It is not (yet) zero-config "code from anywhere".** It works well as a PWA on a phone or iPad, but the networking between them is yours to wire up. The comfortable path: keep the default `127.0.0.1` bind and add a reverse proxy (Caddy, nginx) or a VPN for remote access — self-signed certs on mobile browsers are a rougher ride.

## Requirements

- **Direct install:** Python 3.12+ and the [Claude Code CLI](https://github.com/anthropics/claude-code), installed and authenticated. (The Docker image bundles both.)
- **Client:** any modern browser with network access to the server.

## Quick start

### pipx (recommended)

```bash
pipx install painapple-code
painapple --workspace /path/to/your/project
```

Open `http://localhost:8765/`. The first run prints a bootstrap URL with the password embedded as `?tkn=…` — open it once and a cookie keeps you logged in.

That's the whole install. Plain `pip install painapple-code` into a venv works too — see the [pip/pipx guide](https://wrotek.github.io/painapple-code/getting-started/install-pip/).

### Containers: `painapple docker`

Prefer isolation? (For the autonomous modes, you should.) The same package ships a container front-end with an interactive setup wizard — workspace, credentials, network, all arrow keys, back navigation, and a review screen:

```bash
pipx install painapple-code
painapple docker            # first run opens the setup wizard
painapple docker up -d      # start the bridge detached
```

The image bundles Python, Node, and the Claude Code CLI; state persists in named volumes and your project is bind-mounted. Docker and Podman are auto-detected. In a hurry, `painapple docker quick` skips the wizard and serves the current directory. Raw `docker run` / compose / Podman recipes and source builds: [Docker install guide](https://wrotek.github.io/painapple-code/getting-started/install-docker/).

### Desktop app (in development)

The same setup wizard is on its way into a native desktop app — clickable instead of terminal-based: pick a folder, click through, get a running containerized bridge. Watch the [releases](https://github.com/wrotek/painapple-code/releases).

### More ways to run it

- **GitHub Codespaces / Dev Containers** — one line in `devcontainer.json` boots every Codespace with the bridge installed, started, and port-forwarded → [Dev Container Feature](https://wrotek.github.io/painapple-code/getting-started/install-devcontainer/)
- **From source** — `git clone`, `venv/bin/pip install -e .`, run with `venv/bin/painapple` → [source install](https://wrotek.github.io/painapple-code/getting-started/install-pip/#from-a-source-checkout)

## Authentication

Every HTTP and WebSocket request needs a password. The server generates one on first start, stores it in `~/.config/painapple-code/config.yaml` (inside the container that's under `/home/app/`; mode 0600 either way), and logs a bootstrap URL with the token embedded as `?tkn=…` — open it once, the cookie does the rest.

```bash
# Reveal the password
awk '/^password:/ {print $2}' ~/.config/painapple-code/config.yaml
# …or when running in a container
docker exec painapple-code awk '/^password:/ {print $2}' \
    /home/app/.config/painapple-code/config.yaml

# Rotate: delete the config, restart, and a new password is generated
rm ~/.config/painapple-code/config.yaml   # then restart the server
# …or when running in a container
docker exec painapple-code rm /home/app/.config/painapple-code/config.yaml \
    && docker restart painapple-code
```

Three auth paths: the `bridge_auth` cookie (set automatically after first login), `?tkn=<password>` in any URL, or `Authorization: Bearer <password>` for `curl` and scripts.

## Server options

The flags you'll actually reach for:

| Flag | Default | Description |
|------|---------|-------------|
| `--host` / `--port` | `127.0.0.1` / `8765` | Bind address and port |
| `--workspace` | `.` | The directory Claude operates in (`--cwd` is an alias) |
| `--workspace-root` | = `--workspace` | Directory scanned for sibling projects on the welcome screen |
| `--instance-name`, `--accent` | — | Label + accent color, so DEV and STABLE don't look alike |
| `--tls` | `auto` | Self-signed TLS, auto-enabled on non-loopback binds |
| `--default-provider` | `claude-sdk` | `claude-sdk` (interactive permission cards, live switching) or `claude` (classic line protocol) |

`painapple --help` prints the full list; every flag, environment variable, and accent-color preset is in the [server CLI reference](https://wrotek.github.io/painapple-code/reference/server-cli/).

## Highlighted features

The full tour lives in the [feature docs](https://wrotek.github.io/painapple-code/features/) — these are the bits people ask about.

### Interactive permissions

Every tool call can pause on an approve/deny card with a human-readable preview — Write shows the file and content, Edit an old→new diff, Bash the command. Deny with a typed reason and it's fed back to the model as guidance. Cards surface the engine's own "always allow" suggestions, and permission mode + model switch **live**, mid-turn, over the Agent SDK control plane — no session restart. The Stop button interrupts gracefully and keeps the process warm. → [Permissions guide](https://wrotek.github.io/painapple-code/guides/permissions-and-thinking/)

### Shadow Git with auto-journal

After each turn, a background Haiku fork summarizes what happened and commits all file changes to a per-project shadow git repo (respecting `.gitignore`). Summaries are parsed into structured fields — work done, decisions, learnings, problems solved — and stored in a local DuckDB, so future sessions can query the project's own history. The optional `shadow-git-helper` agent does exactly that: write *"consult shadow-git-helper about X"* and a sub-agent digs through the past without bloating your main thread. Not a backup — a memory.

<img src="docs-site/assets/shadow-journal.png" alt="Journal widget showing per-turn Haiku summaries, files changed and cost, grouped by session" width="500">

### Per-turn summary bar

Context usage, token delta, files changed with diff stats, tool counts, duration, cost, and which model ran — inline after every turn. File pills open diffs and previews directly.

![Collapsed per-turn summary bar with file pills, tool counts, cost and duration](docs-site/assets/turn-summary-bar.png)

### Comments stash

Click the bubble next to any paragraph, add a note, and it attaches — quote included — to your next prompt.

![Selecting a paragraph, adding a note, and the stash attaching itself to the next prompt](docs-site/assets/comments-stash.gif)

### Embedded terminal

A real PTY via xterm.js (`` Ctrl+` ``). On mobile there's a Termius-style key bar with Ctrl/Alt/arrows above the keyboard, and a virtual d-pad joystick on touch-and-hold.

![Embedded terminal running ls, git status and the project test suite](docs-site/assets/terminal.gif)

### Prompt history + favorites

Search every prompt you've ever sent, across all sessions and projects, with phrase, exclusion, date, and content filters (`Alt+P` or `Ctrl+R`). Heart the good ones; reuse or fork into a new session from any result.

<img src="docs-site/assets/prompt-history.png" alt="Prompt history explorer with search filters, a favorited prompt, and reuse actions" width="700">

### And more

Multi-session tabs, git widget, cost analytics, file explorer with rendered previews and in-place markdown editing, a sandboxed browser widget, `#` snippets and agent triggers, paste-to-annotate screenshot editor, discussion threads forked from any text selection, and switchable density modes. → [All features](https://wrotek.github.io/painapple-code/features/)

## Optional helpers

A `shadow-git` CLI, a `shadow-query` DuckDB wrapper, and the `shadow-git-helper` Claude agent ship with the package — the Docker image installs all three at build time. On a host install:

```bash
src/painapple_code/tools/install-helpers.sh   # --update / --uninstall / --dry-run
```

No `sudo`, no `$PATH` edits — targets `~/.local/bin` and `~/.claude/agents/`. Details: [optional helpers reference](https://wrotek.github.io/painapple-code/reference/optional-helpers/).

## Data storage

Everything lives under `~/.painapple-code/` (or `$PAINAPPLE_CODE_HOME`; `/data` in Docker): per-project sessions, shadow git repos, the DuckDB turn store, and logs. Auth config sits apart in `~/.config/painapple-code/config.yaml` (mode 0600), so wiping the data directory doesn't rotate your password. Full layout: [data & storage reference](https://wrotek.github.io/painapple-code/reference/data-storage/).

## Known weaknesses

This is an MVP — there are tradeoffs.

1. **Windowing system** — works, but doesn't support multiple instances of the same widget and could use a rethink.
2. **Code editor** — currently a notepad with syntax highlighting. The plan is a review-driven workflow rather than a VSCode-grade editor; the markdown inline editor is the exception and works well for plan/doc tweaks.
3. **GUI for OS-level features** (git widget, file explorer) — exists but the maintainer prefers the embedded terminal for `grep`/`sed`/`find`/`du`, so these widgets have not been a priority.

## License

AGPL 3.0 — see [`LICENSE`](LICENSE).
