An always-on agent computer for the harnesses you already use.
Ghost publishes native AMD64 and ARM64 images. Choose the container runtime installed on your host.
docker run --detach \
--name pantalk-ghost \
--shm-size 1g \
--publish 127.0.0.1:6902:6901 \
ghcr.io/pantalk/ghost:latestpodman run --detach \
--name pantalk-ghost \
--shm-size 1g \
--publish 127.0.0.1:6902:6901 \
ghcr.io/pantalk/ghost:latestApple's container tool requires Apple
silicon and macOS 26 or later. Start its service once, then run Ghost with
enough memory for the desktop and agent harness:
container system start
container run --detach \
--name pantalk-ghost \
--memory 4g \
--shm-size 1g \
--publish 127.0.0.1:6902:6901 \
ghcr.io/pantalk/ghost:latestApple exposes macOS host-folder mounts as fixed, root-owned shares. When Ghost
detects those mounts, it runs as root inside that container's isolated Linux VM
so its workspace and configuration remain writable. Named volumes and
ownership-mutable Docker or Podman storage continue to run as ghost.
Open http://127.0.0.1:6902. This is the Ghost computer itself, presented through KasmVNC rather than a separate dashboard. Open Setup from the desktop menu and sign in to Codex, Claude Code, or Kimi Code.
The standalone image starts with Pantalk's local connector. To connect the authenticated harness to a real chat system, use one of the deployment recipes.
This short command is for trying Ghost. Its state directories use anonymous volumes, so replacing the container loses their association and leaves the old volumes behind on disk. Use named volumes for a computer you intend to keep.
For a long-lived Ghost, add a restart policy and name every persistent volume:
docker run --detach \
--name pantalk-ghost \
--restart unless-stopped \
--shm-size 1g \
--publish 127.0.0.1:6902:6901 \
--volume pantalk-ghost-workspace:/workspace \
--volume pantalk-ghost-config:/home/ghost/.config/pantalk \
--volume pantalk-ghost-state:/home/ghost/.local/share/pantalk \
--volume pantalk-ghost-codex:/home/ghost/.codex \
--volume pantalk-ghost-claude:/home/ghost/.claude \
--volume pantalk-ghost-kimi:/home/ghost/.kimi \
ghcr.io/pantalk/ghost:latestPodman accepts the same command with podman in place of docker. With
Apple's tool, use container in place of docker, remove
--restart unless-stopped, and add --memory 4g. Apple container preserves
the named volumes and stopped container but does not expose a Docker-style
restart policy; restart it with container start pantalk-ghost.
Pantalk configuration and history, runtime credentials, and workspace files then survive container recreation and image upgrades.
Create another container with a different name and volume prefix when each agent needs its own identity, credentials, browser sessions, workspace, and lifecycle.
From this directory, build and start the local image:
make upThe Makefile selects linux/amd64 or linux/arm64 from the host. Override it
explicitly with PLATFORM=linux/arm64 make up when building for another
architecture.
Open http://127.0.0.1:6902. To select another port or initial resolution:
PORT=8080 RESOLUTION=1600x900 make upThe default port binds only to 127.0.0.1. Do not change BIND_ADDRESS
unless the no-password environment is intentionally being exposed.
Useful development and lifecycle commands:
make check
make build
make run
make recreate
make test
make logs
make status
make size-report
make stopOpenClaw and Hermes have made the always-on agent easy to understand: give an agent a persistent computer, keep it running, and reach it from chat whenever work needs doing. Ghost belongs in that category, but makes a different architectural choice. Ghost is not another agent runtime. It turns the agentic harnesses you already trust - Codex, Claude Code, Goose, Kimi Code, or another Pantalk-compatible harness - into the agent.
The split is deliberate:
- Ghost provides the computer: a persistent Linux workspace, browser desktop, terminal, saved harness credentials, Pantalk daemon, and a stable place to run continuously.
- Your harness provides the agent: its reasoning loop, model access, tools, skills, approval policy, configuration, and the behavior you already know.
- Pantalk provides the reach: it connects that harness to Mattermost, Slack, Discord, IRC, SMS, and other chat systems without teaching the harness about any of them.
The current image includes Pantalk, Codex, Claude Code, and Kimi Code. Codex and Claude Code are already registered in the starter config; Kimi Code is ready to attach through Pantalk's ACP driver. Goose and other command or ACP harnesses fit the same model once installed. Ghost does not ask you to abandon a mature harness for a thinner built-in agent just to gain persistence and chat access.
Boot the computer, authenticate the harness you already use, and connect a
deployment. A few minutes later that harness is working from a real chat
server, with a durable workspace and its normal tools. Changing which harness
answers is one driver: line; changing the chat system does not change the
harness at all.
Ghost also demonstrates one subscription, whole team. Authenticate Codex or Claude Code once inside Ghost, and everyone reaches that single install from the chat client they already have open - no per-person local setup and nobody else needing a terminal. Pantalk keys sessions by user, channel, and thread, so each teammate still gets an isolated conversation.
The desktop itself remains a single-tenant, trusted-host environment. What the team shares is the harness through chat, not the desktop. Run Ghost somewhere you control, keep its desktop private, and let Pantalk be the front door. See Harness authentication for the security model.
Mattermost, Slack, Discord, IRC, SMS, or another chat system
|
v
Pantalk deployment
connector + routing + sessions
|
v
Pantalk Ghost
persistent workspace + credentials + Linux desktop
|
v
Codex, Claude Code, Kimi Code, Goose, or another
command/ACP agentic harness
Messaging servers stay outside the image. A deployment supplies the connector configuration, while the same Ghost image and harness definitions work across providers. Pantalk maintains chat-side routing and session isolation; the selected harness continues to own reasoning, tools, permissions, model access, and execution.
Underneath, Ghost is a deliberately small fork of the original CBK sandbox desktop: an Openbox environment, Tint2 panel, Triste-Crimson theme, Kitty terminal, and on-demand Cortile tiling. The browser UI is a KasmVNC view of that real Linux desktop, which lets both the operator and the harness use the same browser, terminal, filesystem, and display.
pantalkandpantalkdfrom the pinned Pantalk release;- Codex, Claude Code, and Kimi Code as installed harnesses;
- starter Codex and Claude Code agent definitions, with Kimi Code ready to attach through ACP;
- support for Goose and other command or ACP harnesses once installed;
- Google Chrome on AMD64 or Chromium on ARM64, plus Kitty, Git, GitHub CLI, Docker CLI, Python, Node.js, pnpm, Ranger, htop, and common development tools;
- persistent paths for Pantalk state, harness authentication, and
/workspace; - the Openbox, Tint2, KasmVNC, and Cortile browser-desktop stack; and
- a Makefile for local build, lifecycle, validation, and size-report workflows.
VS Code and messaging servers are deliberately absent. Messaging systems are composed around the unmodified image through deployment recipes, keeping Ghost transport-neutral.
Deployments are where the pluggability becomes visible. Each one combines the same unmodified Ghost image with a different messaging system, on that system's official images. Nothing about Ghost changes between them - only the Pantalk configuration mounted over the starter.
The initial Mattermost deployment starts
Mattermost Team Edition, PostgreSQL, and Ghost; provisions codex and
claude bot accounts; and supports both the published Ghost image and a local
Dockerfile build.
cd deployments/mattermost
make upThe Ergo deployment starts an external Ergo IRC server, The Lounge browser client, and Ghost:
cd deployments/ergo
make upTwo deployments, two protocols, one image, both harnesses available in each. Deployment recipes do not publish modified messaging-server images. See the deployment index.
The harness CLIs still require their normal local authentication. Their
configuration is persisted in the pantalk-ghost-codex,
pantalk-ghost-claude, and pantalk-ghost-kimi Docker volumes. Open
Setup in the desktop menu to launch a guided login flow without leaving
Ghost.
Authenticate any runtime you intend to use. Which one ends up answering a given conversation is decided later, in Pantalk config, and can be changed without repeating the runtime logins.
Kimi Code is installed but is not part of the starter agent definitions. Its
Setup action opens Kimi Code; run /login there, then add an acp agent with
command: kimi acp when you want to use it.
The base image does not contain a messaging server or client. Use a deployment recipe to connect the authenticated harnesses to Mattermost, Ergo, or another supported messaging system.
Ghost deliberately assumes a trusted local environment:
- KasmVNC has no browser password.
- Codex may write within
/workspacewithout interactive approval. - Claude uses its noninteractive
acceptEditspermission mode. - Codex runs with
sandbox_mode = "danger-full-access". Its sandbox uses bubblewrap, which cannot create a user namespace inside the container, so no sandbox mode is enforceable here regardless of what is configured — installing the distro package only adds a second binary that fails identically. The setting is declared so the configuration states what is actually true instead of implying a boundary that does not exist. The boundary is the container. Override withGHOST_CODEX_SANDBOX_MODE, or set it empty to omit the setting.
Do not publish port 6901 or change BIND_ADDRESS on an untrusted host.
KasmVNC is started with browser authentication and TLS disabled. The password file created at boot only satisfies a KasmVNC startup check; it is not an access-control layer.
The default loopback bind is therefore the only boundary until an external access layer is added. If Ghost must be reachable beyond the host, put it behind the identity-aware proxy, TLS termination, session controls, and audit policy already used by that environment. Treat exposing Ghost without such a layer as publishing an unauthenticated privileged workstation.
The image pins Pantalk to the release declared in the Makefile. Override the build argument when a different release is needed:
PANTALK_VERSION=VERSION make buildOn first boot, Ghost creates ~/.config/pantalk/config.yaml with a local
connector plus Codex and Claude Code agent definitions. It does not connect to
an external messaging service. Each deployment mounts its provider-specific
Pantalk configuration over this starter - the agent definitions carry across
unchanged, which is exactly the property Ghost is meant to demonstrate.
When upgrading an untouched image that still has the bundled IRC starter,
Ghost saves it as config.yaml.ghost-irc.bak and installs the
transport-neutral starter. Customized Pantalk configurations are never
replaced.
Disable automatic daemon startup with:
PANTALK_AUTOSTART=false make recreateIf the remote desktop feels slow, enable the KasmVNC encoder statistics:
VNC_STATS=true make recreate
make vnc-logThis raises the log level of KasmVNC's EncodeManager writer only, which
reports framebuffer update counts, rect counts, pixel volumes, and compression
ratios per encoding.
Statistics accumulate only while a browser is connected, and the summary is
written when that browser disconnects - so connect, use the desktop, then close
the tab before reading the log. KasmVNC writes them to its own session log
inside the container rather than to the container log, which is why make logs
does not show them.
As a baseline, a settled idle desktop reports roughly four framebuffer updates and about 90 KiB of traffic for a thirty second session, most of it the single full-screen paint sent when the client connects. Substantially more than that means something on the desktop is repainting continuously.
The browser-side view of the same picture lives in the KasmVNC control panel: enable performance statistics to see CPU, network, and FPS.
Run make size-report after a build to measure how much of the image belongs
to the graphical package closure and to list its largest layers. The desktop
remains because it makes the environment inspectable, supports runtime login,
and supplies a Chromium-family browser, screen capture, and input control for
computer-use workflows. See IMAGE-SIZE.md for the rationale
and trimming details.
Right-click the background to open the original application menu:
- Terminal
- Ranger file manager
- htop task manager
- Browser (Google Chrome on AMD64, Chromium on ARM64)
- Setup, with guided Codex, Claude Code, and Kimi Code login actions
- Pantalk daemon and KasmVNC logs
- Cortile tiling controls
The desktop starts in floating mode. Press Ctrl+Shift+T or use the menu to
toggle tiling. The panel reports whether pantalkd is running, and Ranger
opens in /workspace with W and H bookmarks for the workspace and home.
The harness opens in /workspace, the same directory the chat-side agents use,
and that directory is recorded as trusted for Codex and Claude Code at boot so
neither stops on a per-directory trust prompt. That grants no access the chat
path does not already have; set GHOST_TRUST_WORKSPACE=false to keep the
prompts.
Press Ctrl+Shift+G, or click the Pantalk ghost in the lower-left corner, to open
the harness you last signed in to. Signing in through Setup is what selects it,
so there is no separate preference to keep in sync. The ghost is drawn by your
browser rather than the remote desktop, so it costs the session nothing; only
the ghost itself takes clicks, and the rest of that corner still belongs to the
desktop underneath.
Ghost pins the tools that are downloaded during a build so rebuilding the same source does not silently install a different agent runtime:
| Component | Version |
|---|---|
| Pantalk | 0.0.12 |
| agent-browser | 0.33.0 |
| GitHub Copilot | 1.0.75 |
| Codex | 0.145.0 |
| ChatBotKit CLI | 1.38.0 |
| Kimi Code | 0.29.1 |
| Claude Code | 2.1.220 |
make check verifies that the Makefile and Dockerfile pins stay synchronized.
Ghost releases are driven by the VERSION file. A successful CI run on
main creates the matching tag, publishes the versioned image and stable
latest tag to GitHub Container Registry, and creates a GitHub Release.
See RELEASES.md for the release procedure and package visibility requirements.