An AI character that lives on your screen. It walks, talks, naps, and can assist in whatever you are up to. Pick it up, throw it around, let it nap, or talk to it. Attach the AI harness you already use, and it can do anything that an AI agent can.
Each character has a personality and a life of its own.
An AI harness is optional. Attach the one you already use and it can talk and pitch in with tools; leave it off and the pet still works. It doesn't read your screen without consent and never takes screenshots.
recording-hero.mp4
Try the gestures in your browser: Fidget Cues
- Keeps you company: It walks, naps, and reacts to your open windows. It works offline, with no AI account or subscription, for presence and play; hook it up to an AI and it takes on a life of its own, with full conversation and tool use.
- Pick a built-in character, or build your own: Each character has its own sprites, animation loops, and personality. Edit any character's prompt or behavior using a plain-text personality file and a simple manifest format. Create your own characters, or import and convert one from the Pets Codex and Shimeji Shop galleries.
- Personalize your Fidget's behavior: Write your own text for any fidget's behavior through its Instance Prompt. It holds on top of its Character's personality, and changes how that fidget reacts. See Give It an Instance Prompt for examples.
- Pitches in: Double-click to chat with the agent you already use (Claude Code, Codex, Cursor, or any ACP harness); it acts on your machine and answers in speech and motion.
- Knows what you're up to: It reacts to your open windows for context-aware chatter. It never takes screenshots or reads screen pixels, and it reads window titles and app names only with your consent.
- Gets out of your way when you ask it to: Automatically fades away when in fullscreen, hides at will on hotkey, and comes back when you want it to.
Buddy Bot is the default. Eight Characters ship; each moves and speaks differently. A name links to its full prompt.
![]() Buddy Bot Friendly and curious; he's your helpful assistant. |
![]() Black Mage Cynical spellcaster, cryptic and theatrical. |
![]() BMO Earnest, childlike, delighted to be here. |
![]() Cat Every window is furniture. Never helpful. |
![]() Jotaro Kujo Terse, perpetually bored, tougher than he lets on. |
![]() Nim Sleeps eleven hours a day. Soft-spoken. |
![]() Timber Wolf Patrol mech. Clan warriors don't waste words. |
![]() Trump The desktop is his rally. Bombastic. |
hero.mp4
Characters are packages of art, personality, and tuning. See DEVELOPMENT.md; the format is still evolving.
Fidget runs on macOS (Apple Silicon), Linux (x86_64) and Windows (x86_64). Every build is on the latest Release. The builds are not signed yet, so the first open warns.
On Apple Silicon with Homebrew:
brew install --cask omesser/fidget/fidgetThat taps omesser/homebrew-fidget and installs Fidget.app. Later Releases arrive with brew update and brew upgrade --cask fidget.
Or download Fidget_<version>_aarch64.dmg from the latest Release, drag Fidget.app from the disk image into Applications and open it. Dismiss the Gatekeeper dialog, then System Settings → Privacy & Security → Open Anyway.
macOS may block /Applications/Fidget.app after a Homebrew or download install. Removing its quarantine attribute bypasses a macOS security check. Run the command at your own risk. Never run it on an app you do not trust. Fidget is open source, so you can inspect its code, but that alone does not verify the downloaded app. To remove the quarantine attribute, run:
xattr -d com.apple.quarantine /Applications/Fidget.appDownload Fidget_<version>_amd64.AppImage or Fidget_<version>_amd64.deb from the latest Release, then run the commands from the folder you saved it in.
The AppImage runs without installing and carries its own WebKitGTK. It mounts itself with FUSE, which desktop installs usually have (fuse3 on Debian and Ubuntu):
chmod +x Fidget_*_amd64.AppImage
./Fidget_*_amd64.AppImageWithout FUSE, run it as ./Fidget_*_amd64.AppImage --appimage-extract-and-run.
The .deb is for Debian and Ubuntu, and needs no FUSE. apt installs the WebKitGTK and tray libraries it depends on:
sudo apt install ./Fidget_*_amd64.deb
fidgetAfter that, Fidget is in your app menu. sudo apt remove fidget uninstalls it.
Full support for window Perches and edges via X11/XWayland (the normal Linux desktop path). Pure Wayland sessions without an X server fall back to screen edges only. Linux packages and the AppImage's FUSE dependency are in DEVELOPMENT.md.
Download Fidget_<version>_x64-setup.exe from the latest Release and run it. SmartScreen warns about the unsigned installer: choose More info → Run anyway. It needs no admin rights. It installs Fidget for your user in %LOCALAPPDATA%\Fidget, adds it to the Start menu, and fetches WebView2 if Windows lacks it. Uninstall it from Settings → Apps.
Clone and run from the repo root (macOS, Linux, Windows):
git clone https://github.com/omesser/fidget.git fidget
cd fidget
cargo run -p fidgetDevelopers and CI can override Settings with optional environment variables:
# Optional. Overrides Settings → AI → AI source.
FIDGET_HARNESS=claude cargo run -p fidget
# Optional. Overrides Settings → Character.
# Any of: buddy-bot (default), black-mage, bmo, cat, jotaro-kujo, nim, timber-wolf, trump
FIDGET_CHARACTER=nim cargo run -p fidgetThe full variable list, including FIDGET_DIRECTOR_*, is in harness.md.
It works offline with no key. With nothing configured, Static weights pick idle Behaviors from the Character.
Right-click the fidget, or click the tray icon, and choose Settings….
Settings → Character picks which character it wears. Buddy Bot is the default. The others are in Characters.
Settings → AI chooses who answers. Under AI source, pick Harness · claude or another name from Harness Support. The Harness signs in on its own. Model under Harness names the model it runs on, and blank keeps the Harness's own default. For a Model API, pick Model API in AI source, then set Base URL, Model, and API key under Model / API. Presets fill the Base URL for OpenAI, Anthropic, xAI, and Ollama. Type any other OpenAI-compatible endpoint into Base URL. Apply saves the choice.
Character packages are in DEVELOPMENT.md. Keychain dialogs an unsigned build costs are in harness.md.
- Poke - click once for a react, then it resumes.
- Summon - double-click to open a chat window for that fidget.
- Pick up - click and drag; the pressed point stays under the pointer.
- Throw - release while moving; it flies on an arc and lands.
- Perch - let it settle on a window's top edge; drag slowly to ride, fling to drop.
- Hide - Control-Option-Command-B (the default; change it in Settings) toggles the fidget instantly.
- Fullscreen - fades out for fullscreen apps, fades back when you exit.
Summon opens that fidget's chat window. What you type joins the same conversation that decides what it does on your desktop, so an answer arrives as speech and a Behavior, not only as text. Lines it says unprompted appear here too, labelled with what it was reacting to.
The bar at the bottom says what the fidget is doing and when it next thinks. Advanced opens the ladder: Behavior, Primitive, Animation, State, Facing, and the Director's countdown. Answers need a Director; see Get It.
An Instance Prompt is your own text for one fidget, layered on top of its Character's personality. To write one, double-click the fidget to summon it, open the Prompt tab, and type in the Your own layer box. That box is the Instance Prompt. Paste one of the examples below and edit it to fit. Saving starts a new conversation, and the Instance Prompt stays with that fidget if you switch its Character.
Every example below assumes this setup:
- A Harness is attached. A Model API can't run tools.
- The Harness is allowed to use its own tools.
- The Window and application names consent is on in Settings → Privacy. Fidget then reads app names and window titles only, never pixels, and it never takes screenshots.
| Paste and edit | How it reacts on a wake |
|---|---|
If my editor stays in front for a long stretch, ask me to explain the bug to you, like a rubber duck. |
Sees the editor in front on a wake and asks you to walk it through the bug. |
You're a theatre critic. When you're perched on a window, review that app in one dramatic line. |
Perch it on a window and it reviews the app it's standing on. |
When I ask you to check something on my machine, do it, then report back in one line, in character. |
Does the check with your Harness's tools and reports back in one line, in character. |
A pet first. The AI is the part that makes it someone.
flowchart LR
subgraph always["Always on. No AI needed."]
F["Frame loop"] --> Y(("Your fidget"))
P["You"] --> Y
end
subgraph mind["Optional: the Director"]
C["Personality"] --> D{"Director"}
I["Instance Prompt"] --> D
W["Window titles"] --> D
end
D -- "A Behavior" --> Y
D -- "A line" --> Y
H["Your agent"] -.->|"attach over ACP on stdio"| D
D -.->|"the Harness calls back over MCP"| H
- Frame loop: Walks, falls, lands, perches. Every frame, on your machine.
- You: Poke, throw, drag, summon.
- Personality: Who it is. A plain text file.
- Instance Prompt: Your own twist, on top.
- Window titles: Only if you say yes. Never pixels.
- Director: Wakes now and then and decides what's next.
- A Behavior: nap, prowl, patrol…
- A line: in character.
- Your agent: Attach the one you already use. It can talk and use tools.
- ACP: attach over ACP on stdio.
- MCP: the Harness calls back over MCP.
A sample of an opening wake and a later follow-up, not a live dump:
Opening wake
Personality Prompt: Cat claimed the desktop and treats every window as furniture.
Instance Prompt: You're a theatre critic. When you're perched on a window, review that app in one dramatic line.
Behaviors it may propose: nap, prowl, patrol
This moment: perched on the editor
A later wake
What just happened: you poked it
Recent Behaviors: patrol, nap
Time of day: afternoon
State: Perched
Window titles (allowed): README.md - VS Code
Which Harness you attach changes what Fidget can do with it.
| Harness | Command | Standing |
|---|---|---|
claude |
npx -y @agentclientprotocol/claude-agent-acp@latest |
Zed's adapter over the Claude Agent SDK; no first-party ACP mode. Fresh and resumed sessions both work. |
codex |
npx -y @agentclientprotocol/codex-acp@latest |
Zed's adapter (codex-acp); no first-party ACP mode. Fresh and resumed sessions both work. |
copilot |
copilot --acp |
First-party, GitHub. copilot alone is the interactive TUI. Fresh and resumed sessions both work, smoked on copilot 1.0.88 (#1016). |
cursor-agent |
cursor-agent acp |
First-party. cursor-agent alone is the interactive TUI. Every attach opens a fresh session, because it advertises no loadSession. |
grok |
grok agent stdio |
First-party, Grok Build. grok alone is the interactive TUI. Fresh and resumed sessions both work. |
goose |
goose acp |
First-party, Block. goose alone is the interactive CLI. Fresh and resumed sessions both work, smoked on goose 1.51.0. |
opencode |
opencode acp |
First-party. Fresh and resumed sessions both work. |
hermes |
hermes acp |
First-party. Fresh sessions work; a resume that cannot restore the session reopens (#448). |
pi |
npx -y pi-acp@latest |
Zed-registry adapter (pi-acp); no first-party ACP. Fresh and resumed sessions both work. |
antigravity |
agy_acp_server.par (agy_acp_server.exe on Windows) |
First-party, Google's ACP server; agy itself has no ACP mode. Fresh and resumed sessions both work, smoked on agy_acp_server 1.2.1 (#604). |
| anything else | as typed, split on whitespace | Unnamed, and it works: any command that speaks ACP on stdio attaches. |
Tools each harness keeps under ACP, session and auth behavior, and per-harness setup notes are in docs/harness.md.
Fidget attaches to a Harness over ACP on stdio. The Harness calls back over MCP, on the route the MCP transport column describes. harness.md has the transport details.
Eight tools from crates/core/src/dispatch.rs. The opening turn of the Character Prompt tells the model to use the tools it has, without naming them, so this table stays the only catalog (#917):
| Tool | Category | What it does |
|---|---|---|
speak |
Expression | Make the Character speak dialogue |
play_behavior |
Expression | Play a named Behavior |
list_windows |
Sensing | List visible windows with bounds, and their names under consent |
describe_screen |
Sensing | Describe screen (v1: window metadata only) |
recall |
Memory | Read everything Memory holds |
remember |
Memory | Write one fact under a heading |
list_instances |
Identity | List Character Instances and their names |
whereabouts |
Placement | Which display each Instance is on, the other displays, and its feet in that display. Each display includes its name when the platform has one, its origin, and its size, in logical points |
Three readonly resources (resources/list, resources/read; no write, no subscribe):
| URI | What it is |
|---|---|
fidget://windows |
Visible windows, frontmost first, with the owning application and the title. Empty without the window-names consent, which covers both (ADR-0032). Same excluded applications as list_windows. |
fidget://memory |
The Memory Manifest file every Character Instance shares. |
fidget://action-log |
The current Action Log file only. Rotated siblings are not this resource. A large current file is tailed to complete JSONL lines. |
Explicitly not served: mouse/keyboard/Executor tools (ADR-0003). No click, no type, no input events by design.
Fidget never reads screen pixels. Sensing is OS window metadata: bounds and idle for free, plus the owning application, the title and the frontmost app under one consent (ADR-0032). So describe_screen describes the window layout, not what is on screen. Decline it and the fidget still knows where the windows are, and not what they are. The fidget takes no screenshots, runs no OCR, and embeds no vision model for desktop content. The "Appear in screenshots and screen shares" setting is the other direction: whether the sprite shows up in captures you take.
That bounds Fidget's own code, not the agent you attach to it. An agent that needs to see and act on your desktop still can. The capability comes from the Harness itself, or from a computer-use MCP server you attach to the Harness, never through Fidget, whose MCP serves no input events.
The portable option across the Harnesses above is cua-driver (MIT; macOS, Windows, Linux), attached over stdio MCP. Connect your agent to Cua Driver carries the per-client registration, and MCP tools lists what it exposes. Attach it deliberately: it drives the real desktop with your signed-in sessions, and its permission mode is chosen by the process that owns the driver runtime, not by the agent asking. Some Harnesses bring computer use of their own instead; the Capture decision note has the per-Harness table and the other drivers surveyed.
What works today on each OS.
| Capability | macOS | Linux | Windows |
|---|---|---|---|
| Overlay that never takes focus | yes | yes | yes |
| Click-through off the sprite | yes | yes | yes |
| Grab, Throw and Poke | yes | yes | yes |
| Perch on window edges | yes | yes | yes |
| Dock or panel as a Perch | yes | degraded¹ | degraded² |
| Fade out for a fullscreen app | yes | degraded⁵ | degraded³ |
| Capturable; opt-out in settings | yes | degraded⁴ | yes |
| Settings window | yes | yes | yes |
yes- implemented.degraded- runs in reduced form. A supported mode, not an error.
Degraded cell notes:
- Linux desktop panels: Desktop panels come from each display's work area, as on Windows: a bottom one is the floor, a side one is a wall, and a top one is the ceiling. Under a window manager that publishes no per-monitor work area (xfwm4), a desktop panel on a display that isn't primary is ignored. Tracked in #1300.
- Windows Dock/panel: Taskbar from work area (full-width strip) rather than exact island bounds. Taskbar spans the edge by design; no Windows API equivalent to macOS's
CoreDockGetRect. - Windows fullscreen: Fades for true fullscreen and properly-sized borderless windowed modes. Apps using non-standard fullscreen or leaving gaps may not trigger fade.
- Linux Capturable: Always capturable. Linux has no platform API to exclude windows from capture tools (ADR-0024).
- Linux fullscreen: X11 works for all apps. XWayland under Mutter/KWin: native Wayland fullscreen apps do not trigger fade or move; XWayland clients still trigger correctly. Pure Wayland without XWayland: neither XWayland clients (not present without an X server) nor native Wayland fullscreen apps trigger fade or move (#1369, #1360).
Detailed investigation: docs/research/platform-support-degraded-cells.md.
Linux support is full on normal desktops (X11 or XWayland under GNOME/KDE). Rare pure Wayland sessions without an X server fall back to screen edges only - no window Perches, Grab, Throw, or fullscreen fade. See DEVELOPMENT.md.
No. Without one, your fidget still walks, naps, perches on windows and reacts when you poke or throw it. Attach the agent you already use, like Claude Code, Codex or Cursor, or a Model API key, and it starts talking. A local model you serve through Ollama or MLX works too. Use a Harness for the most powerful experience.
Fidget doesn't read pixels. It takes no screenshots and runs no OCR. With your consent, it reads only window titles and app names, so it can react to what's in front of you with more context. Without your consent, it still knows where windows are, just not what they are. An agentic Harness like Claude Code or Hermes is different. Your permissions and plugin setup there decide what it can do, and that can include computer use and taking screenshots. That is powerful and dangerous, so Fidget leaves it to the Harness on purpose.
Fidget itself never clicks or types. It has no mouse or keyboard tools by design. The agent you attach can still use its own tools, most of the ones it already has in your terminal.
It shouldn't. It never takes window focus unless you type in the quick-message pill or use the chat, and clicks pass through everywhere except the sprite. It fades out for fullscreen apps, and the hotkey Control-Option-Command-B hides it instantly. On macOS and Windows, a setting also keeps it out of screenshots and screen shares.
Fidget is free and MIT licensed. A Harness uses the subscription you already have, so you manage usage there and Fidget just uses it. A Model API bills your own key with your provider. Even with an agent attached or Model API configured, if left alone, Fidget costs very little. It only thinks and speaks now and then, and its banter spends very few tokens compared to most uses. When you actively use it by prompting and talking to it, it will incur usage costs from your AI subscription, just like any session or calls.
Yes, for physical desktop presence and play. Walking, poking, throwing, sleeping, perching and every gesture run locally. Only talking needs an AI, and that can be a local model. So whether you pay, and how much, is up to you.
macOS on Apple Silicon, Windows on x86_64 and Linux on x86_64. On Linux, it's fully supported on normal X11 or XWayland desktops. Pure Wayland sessions without an X server fall back to screen edges only.
It's open source, so you can read every line. I'm diligent with code reviews, security reviews and updates. The builds aren't signed yet, so macOS and Windows warn on first open, and the install steps say what to click. If you'd rather not trust a download, build it from source. You're welcome to report any issue you find on the repository.
Want to help? Open issues welcome bugs, ideas, and PRs. Start with DEVELOPMENT.md for toolchains, hooks, verification, character writing, and imports. See how Fidget compares to other desktop pets in alternatives.md.
Design and decisions:
- GLOSSARY.md - vocabulary
- DESIGN.md - design decisions (the chat window ships; the chat mockups are a Dated page, a frozen proposal, not what ships)
- docs/SPEC.md - v1 scope
- docs/adr/ - ADRs
Harness brand marks identify each Harness and belong to their owners. The Grok
logomark is xAI's own file from their brand guidelines,
used unaltered to refer to Grok, which those guidelines permit and may revoke.
The Nous Research mark (docs/readme/nous.svg) identifies the Hermes Harness.
The Codex row uses the OpenAI mark from
Simple Icons, kept in the repo because the CDN no
longer serves that slug (CC0, trademark reserved to OpenAI).
docs/readme/openai-on-light.svg is that glyph in near-black;
docs/readme/openai-on-dark.svg is the same path in white, so it stays visible
on a dark README. The Goose mark is the Goose icon from
Lobe Icons (MIT), split the same way
(docs/readme/goose-on-light.svg, docs/readme/goose-on-dark.svg); the
trademark stays with Block. Every other mark is served from Simple Icons (CC0, with each
brand's trademark reserved to its owner).
WindowPet (MIT) inspired the Tauri desktop-pet shape. Fidget is a greenfield build, not a fork (ADR-0001). Overlay code is independent; tray, launch-at-login, and updater follow WindowPet's MIT-licensed patterns.
The Chat window's mind mark - the small brain beside what answers - is the
brain glyph from Font Awesome Free 6.x, used
under CC BY 4.0 and inlined as
a path in src/chat.html. The license asks for the credit; this is it.
Character provenance is in each Character Package manifest, under [source], and on the Character Gallery. In short: Buddy Bot and Nim are this project's own art. Timber Wolf derives, with the creator's permission, from MekaRamen's Sketchfab model. BMO is cut from the shimejishop BMO pack. Cat, Jotaro Kujo and Trump are cut from petscodex pets. Black Mage is sliced from GigaGuy's sprite sheet on The Spriters Resource. A package is prose, a manifest and art: the personality and the manifest - animations, Behaviors, Director and cursor tuning - are this project's work and MIT throughout. The art is not always ours. Some characters adapt art that declares no license, and each manifest names what it adapts and whose IP the character is.
MIT.










