Pure Go · No cgo · Runs on a Pi

A tiny anime companion who lives on your screen.

Onidia walks along the bottom of your display, blinks, stretches, naps on schedule, and answers you out loud. Pick her up, throw her, talk to her — or let your apps talk to her for you. All of it in a few megabytes of Go, with an idle CPU of roughly zero.

0% idle CPU ~3 MB resident 16 expressions 1 binary, no toolkit
onidia — live canvas live

Expression

drag to move her · click beside her and she walks over
So, what is it?

A friend for your desktop,
not another app to manage.

You go about your day. She stays at the bottom of the screen, doing her own thing — wandering, stretching, napping. Every now and then she says something. If you have something to ask, she listens, thinks, and talks back.

01
🐧

She lives there

A small always-on-top window with per-pixel transparency — only Onidia and her speech cloud are visible. No taskbar entry, no window decorations, no desktop clutter. She walks back and forth, blinks, sways her tail, and bobs gently. Double-click and she hops. Grab her and carry her around.

02
💬

She talks back

Type at her and she answers in comic speech bubbles, in her own voice, with a face that matches the mood of what she says. Speak into your mic and she transcribes it. Four AI backends, from a local Ollama model to Gemini, Bedrock or OpenRouter — your call, switchable with one flag.

03
🚀

She does things

Celebrations, confetti, hearts, a lightbulb over her head, a disco ball, a guitar, a jump rope, a skateboard, a hovercar, an iron-man suit-up. She naps on your schedule, reacts when you throw her, and parachutes down if you drop her from the top of the screen.

💻

For your tools, too

Any program on your machine can write one line to her speech pipe and she'll say it — a build finished, a deploy shipped, a server down. Build a green and she celebrates; a failure and she gets genuinely upset about it.

💻️

Whichever character you like

Onidia is the teal-haired chibi girl. Kama is the boy in the red hoodie. Both have their own palette, art and phrase list, selectable at launch. And because a character is just a Go package, making your own is a weekend, not a rewrite.

⚡

Light as air

No Electron. No Qt. No GTK. No cgo. Onidia talks to the X server directly over the wire protocol and draws every pixel of herself in code. That's why she costs a few megabytes of RAM and essentially nothing while sitting idle.

Sixteen moods

She has a face for
every feeling.

Happy, wink, sad, thinking, anxious, angry, surprised, sleepy, fear, disgust, contempt, confused, skeptical, embarrassed, adore — plus her neutral smile. She picks the right one on her own from what happens to her and what she's saying. Browse the library below and tap any shot — she'll wear it.

Celebrations & performances

Tap a button.
Watch her react.

These are the real event and action names the desktop pet understands — trigger any of them and the pet above will do the same thing, up on your screen.

🎉

Events — pure cosmetics

Short overlays that never drag her around. Any process can fire one through the command pipe or petctl, and the AI can pick one for her mid-sentence.

🥴

Actions — she performs them

Actions drive her whole pose, so she keeps doing them even while walking — skipping rope becomes skipping along. One at a time; re-triggering restarts. The desktop pet ships these and more; the ones below are what this canvas port shows.

Also in the Go build: skip, juggle, eat, work, guitar, sneeze, 6-7, basketball, drive, kitten, plus the ride skateboard and the chute parachute.

The other half

Give her a brain
and a voice.

Onidia is the body. chat-app is the mind: a tiny chat window, also pure Go on raw X11, that talks to a real language model — then hands every answer to the pet so she says it out loud with a matching expression.

Ask anything. She answers twice.

The reply appears in the chat bubble and is spoken by the pet, in sync with the audio. The call runs on its own goroutine, so the window never freezes — it just shows a ... bubble while it thinks. The last 20 turns stay as context, and the model is invited to tag each answer with a mood so her face matches.

# you type in the chat window you › what should I do about the build?
# the model answers, tagged with a mood bot › [happy] all green - nice one!
# chat-app forwards it to the pet's speech pipe pet → [happy] all green - nice one!
# ...and Onidia says it, out loud, smiling
Gemini Amazon Bedrock Ollama (local, no key) OpenRouter / any OpenAI-compatible
chat window with a conversation conversation
the About dialog with Onidia's portrait about
the settings dialog settings
a thinking cloud above the reply thinking cloud
🎙

Speaks & listens

Replies play through the Typecast API. The mic button records a take, transcribes it (Amazon Transcribe or local faster-whisper) and drops the words in the box for you to edit before sending.

🖼

Pictures too

Ask about a place or a thing and she fetches a real photo from Pixabay or Wikipedia, or has Gemini generate an illustration — and it shows up inside her speech bubble, too.

🤖

Pluggable agents

She can call real abilities: play a song, play a movie, read a story, or animate the pet. Drop in a folder with an agent.json and she can use it. No rebuild.

🧠

Checks itself first

Before the window opens, a preflight gate verifies your backend is really reachable and the environment is sane — and tells you exactly what to fix instead of failing mysteriously later.

Under the hood

No toolkit.
No cgo. Just Go and X11.

Most desktop toys drag in a GUI framework measured in hundreds of megabytes. This one doesn't. It speaks the X11 wire protocol directly, and every pixel of Onidia is drawn by code at runtime.

Youtype, or speak into the mic
→
chat-apppure Go, raw X11
UI thread never blocks
→
The modelGemini / Bedrock
Ollama / OpenRouter
→
Speech pipea named FIFO per display
/tmp/desktop-pet--0.say
→
Onidiaspeaks it, with the
matching expression
~0%IDLE CPU
~3 MBRESIDENT MEMORY
0IMAGE ASSETS
0CGO DEPENDENCIES
112×160AUTHORING GRID
5×7BITMAP FONT

How a frame is made

A tiny state machine — idle, walk, hop, drag, throw — runs a few physics steps a frame and produces a pose: bob, leg swing, foot lift, blink, arm flags, expression. The pose is rendered procedurally onto a supersampled canvas and downsampled for smooth edges, the speech bubble is composed above it, and the whole image is uploaded with a single PutImage. The window itself just moves to follow her.

Because the character is code and not a sprite sheet, adding a personality means writing a Go package: its own palette, drawing functions and phrase list, registered at startup and picked with -character. Two characters can never collide, because they share nothing but the pose contract.

XShape is deliberately not used: under XWayland, shrinking a shaped window's region can stop updates from being presented, so the plain transparent window composites correctly everywhere instead.

Worth knowing

characters/One self-contained package per personality — onidia, kama, and a template for yours.
behavior.goThe buddy brain: idle / walk / hop / drag / throw FSM plus the throw and parachute physics.
bubble.goComic speech-bubble rendering, word wrapping, and the scene layout that reserves headroom for the cloud.
events*.goThe celebration framework: hearts, confetti, floating Zs, the lightbulb, the robot suit-up.
internal/fxShared supersample compositing, the built-in bitmap font, alpha and easing maths.
single instanceA kernel flock per display, so a second launch exits and names the pid holding it.
Get her onto your desktop

Three commands.
That's the install.

There's no package to download and no runtime to set up. Clone, build, run. Pick whichever half you want — the pet on its own, the chat window on its own, or both talking to each other.

Start with just Onidia. She chats with herself, walks around and reacts to anything you write to her speech pipe — no API key, no network, no account.

terminal
# Go 1.21+ and an X11 display (Xorg or XWayland)
git clone https://github.com/portege/onidia.git
cd onidia
make build        # builds ./onidia, petctl and petui
make run          # ...or just ./onidia

# a few flags worth knowing
./onidia -scale 1.5          # sprite size (0.15 - 4)
./onidia -speed 160          # walk speed in px/s
./onidia -character kama     # the boy in the red hoodie
./onidia -demo               # roam + chatter instead of staying planted
./onidia -debug              # dump sample frames to pet_*.png

The chat window on its own. Grab a free key from Google AI Studio — or point it at a local Ollama and skip the key entirely.

terminal
# 1. a free key: https://aistudio.google.com/apikey
export GEMINI_API_KEY="your-key"

# ...or run fully local, no key at all
ollama pull qwen2:1.5b
./chat-app -provider ollama -model qwen2:1.5b

# build & run
git clone https://github.com/portege/onidia-chat.git
cd onidia-chat
make build
make run

# check everything works BEFORE the window opens
make preflight

# see the UI with no display at all
make preview      # writes chat_ui_*.png and exits

Start the pet first — it creates the named pipe the chat window writes into. Then start the chat window and she'll start speaking every answer.

two terminals
# terminal 1 - the body. It logs the pipe path on startup.
cd onidia && make run
[buddy] speech: talk to the buddy with:
  echo "hello buddy!" > /tmp/desktop-pet--0.say

# terminal 2 - the brain
cd onidia-chat
export GEMINI_API_KEY="your-key"
./chat-app

# ...now let any program talk to her, from anywhere
echo "deploy finished, great job!" > /tmp/desktop-pet--0.say
echo "[angry] the build failed again!!" > /tmp/desktop-pet--0.say

This page is a single self-contained file — no server, no build step, no dependencies. Save it and open it.

no install required
# the character engine in onidia/onidia.html runs the same
# way: open the file, talk to her, done.
xdg-open onidia/onidia.html

# this page, likewise
xdg-open web/index.html
1
Go 1.21 or newerto build the binaries. Developed against 1.24.
2
An X11 displayNative Xorg, or XWayland on a Wayland session. $DISPLAY must be set.
3
A compositorDefault on modern desktops. Without one the transparency is a black box.
4
Audio (optional)aplay, paplay or ffplay on PATH for the spoken replies.
Get in touch

Questions, ideas,
or a new character?

Found a bug, want a feature, or fancy writing your own personality? The repositories are the fastest way in — and issues are genuinely read. If you'd rather just say hello, the form works too.