A Linux-first local desktop companion runtime for AI-assisted work.
Inspired by Codex Pets. Not affiliated with OpenAI. Built as a local Linux-first exploration of AI desktop companions.
Early experimental release. Tested primarily on Pop!_OS/X11. Wayland support is not the focus yet.
The app runs a transparent, always-on-top PyQt6 companion on X11. It can walk around the desktop, react to drag/drop, show Codex session status in an animated thought bubble, accept replies, launch worktree-backed Codex task terminals, and run optional provider bridges for Codex, Claude, Slack, and GitHub.
This public repo is the reusable engine and template kit. It intentionally ships with a neutral starter-buddy demo pet instead of a personal character pack.
git clone https://github.com/theRadicalSoftware/AIDesktopCompanion.git
cd AIDesktopCompanion
python3 -m pip install -r requirements.txt
python3 run.py run starter-buddy --scale 1.1 --codex-session currentOn Pop OS or other systemd-based Linux desktops, launch it as a user service:
./launch-companion.shStop it with:
./stop-companion.sh- Linux desktop
- Python 3
- PyQt6
- Pillow
- X11 recommended
xdotoolfor Codex approval buttons from the thought bubble- Optional: Codex CLI for Codex work/session status
- Optional: Anthropic API key for Claude provider support
- Optional: Slack token for Slack messaging support
- Optional: Git + SSH key for GitHub actions
Check local dependencies:
python3 run.py doctor- Runs a local desktop companion pet from a modular pet pack.
- Supports fixed-cell
192x208sprite atlases. - Shows a thought bubble for Codex work, waiting replies, and provider status.
- Lets you reply to known waiting Codex sessions from the bubble.
- Can answer visible Codex terminal approval prompts through X11/
xdotool. - Accepts file/folder drops for safe Codex work.
- Can stream Claude responses into the thought bubble when configured.
- Can send and poll Slack messages when configured.
- Can run guarded GitHub actions such as push and merge/push through local Git/SSH.
- Can spawn additional companion pets as separate local processes, each with its own pet pack, Codex session selector, and optional pet-owned Codex terminal.
Use either a bundled pet id or an absolute path to a pet folder:
python3 run.py run starter-buddy --scale 1.1
python3 run.py run /path/to/my-pet-pack --scale 1.1 --codex-session currentThe launcher uses PET=starter-buddy by default:
PET=/path/to/my-pet-pack ./launch-companion.sh
PET=starter-buddy CODEX_SESSION=off ./launch-companion.shPet manifests can expose a right-click Companions submenu. Each entry starts another pet as a detached process, so it keeps its own runtime state, transcripts, work output, and thought bubble:
{
"runtime": {
"companions": {
"enabled": true,
"entries": [
{
"label": "Pink Sidekick",
"pet": "pink-sidekick",
"scale": 1.0,
"speed": 0.9,
"codexSession": "terminal",
"codexTerminal": {
"enabled": true,
"title": "Pink Sidekick Codex",
"cwd": ".",
"sandbox": "workspace-write",
"approvalPolicy": "untrusted",
"noAltScreen": true
}
}
]
}
}
}Use codexSession: "off" for a fresh independent companion that can still run its own Ask Codex and file-drop work without a visible terminal. Use codexSession: "terminal" to open a new Codex terminal and start the spawned pet against a private pointer: file under that pet's runtime folder. Terminal sessions are recorded in ~/.codex/ai-desktop-companion/session-owners.json, so pets using broad current or latest selectors skip sessions owned by another pet. A terminal-scoped pet can set runtime.codexBubble.exitOnTerminalClose to true to disappear when its owned Codex terminal closes. Use an explicit Codex session id or rollout-*.jsonl path only when you want that pet to monitor and reply to one known existing terminal session.
Right-click a running companion and choose Worktree Tasks -> New Worktree Task... to create a Git worktree from the current repository HEAD, launch a Codex terminal in that isolated checkout, and bind the terminal to the pet. If the manifest has companion entries enabled, the first companion can become the visible task owner; otherwise the current pet opens the scoped terminal itself.
Task records live under ~/.codex/ai-desktop-companion/worktree-tasks.json, with generated checkouts under ~/.codex/worktrees/ai-desktop-companion/ by default. The menu can show task summaries, open task terminals and folders, launch the Review / Handoff pane, and remove a task only when its worktree is clean. Use Worktree Tasks -> Review / Handoff... to pick from active tasks; if there are none, the pet will say so in its bubble.
The review pane shows changed files, full diffs, staged/unstaged views, hunk controls, commit controls, branch creation, branch push, pull-request opening, and safe handoff back to the main checkout. Handoff requires a clean main checkout; it creates a checkpoint commit in the worktree, writes a patch backup under the local repo's .git/ai-desktop-companion-review-backups/, then cherry-picks the checkpoint locally.
CLI equivalents:
python3 run.py worktree-task-create "Fix the failing tests" --cwd . --open-terminal
python3 run.py worktree-task-list
python3 run.py worktree-task-status <task-id>
python3 run.py worktree-task-terminal <task-id>
python3 run.py worktree-task-diff <task-id>
python3 run.py worktree-task-stage <task-id> <path>
python3 run.py worktree-task-commit <task-id> -m "Commit message"
python3 run.py worktree-task-handoff <task-id> -m "Handoff checkpoint"
python3 run.py worktree-task-remove <task-id>Worktree tasks are detached by default to keep the main checkout clean and avoid checking out the same branch in two places. Use --branch <name> at creation time or worktree-task-branch <task-id> <branch> when the work should become a normal branch.
Start with these docs:
The fastest path is to give this repo to Codex and ask it to follow CODEX_START_HERE.md. The template prompts under templates/pet-pack/prompts/ describe the required and optional animation rows.
Useful starting files:
pets/starter-buddy/pet.json: runnable demo manifesttemplates/pet-pack/pet.template.json: fuller manifest template with provider rowsexamples/secrets.example.json: local secret-file shapeexamples/slack-contact.example.json: Slack contact configuration shape
AI Desktop Companion uses a richer manifest for Linux desktop behavior, but it can also exchange pets with the official Codex app custom-pet package shape.
Check whether a rich pet can be exported:
python3 run.py check-codex-pet starter-buddyExport the first 9 rows as an official Codex app pet package:
python3 run.py export-codex-pet starter-buddyThat writes:
${CODEX_HOME:-~/.codex}/pets/starter-buddy/
pet.json
spritesheet.webp
Import or run an official Codex pet package through the richer Linux runtime:
python3 run.py import-codex-pet starter-buddy
python3 run.py run starter-buddy --scale 1.1
python3 run.py run-codex-pet starter-buddy --scale 1.1Official exports keep only the Codex app's fixed 8x9 atlas. Extra AI Desktop Companion rows remain part of the native richer runtime format and are not written into the official package.
Provider secrets should be environment variables or local ignored config. Do not put keys in pet.json.
Claude:
export ANTHROPIC_API_KEY='<anthropic-api-key>'Slack:
export SLACK_BOT_TOKEN='<slack-bot-token>'
export SLACK_USER_TOKEN='<slack-user-token>' # optionalGitHub:
ssh-add ~/.ssh/id_ed25519
git remote set-url origin git@github.com:owner/repo.gitSee Provider Config and Security.
This repo should stay reusable:
- Include engine code, docs, templates, and permissive demo assets.
- Do not commit personal pet packs, private character art, API keys, Slack IDs, runtime logs, or local transcripts.
- Keep real/custom pets in a separate private repo or an ignored local folder when needed.
MIT. See LICENSE.