A floating pixel mascot that mirrors your terminal & Claude Code activity on macOS and Linux.
A tiny always-on-top pixel dog that reacts to what your terminal is doing. It sniffs when you're building, barks when a dev server is running, sits when you're free, and sleeps when nothing's happening.
It also integrates with Claude Code — the dog knows when Claude is thinking vs waiting for you.
Ani-Mime wouldn't be the same without these wonderful people. Thank you for your time, ideas, and code — you made this project better.
|
thnh-dng |
yanmad27 |
thanh-dong |
setnsail |
QuangHo0911 |
cuongtranba |
| Status | Dot | Mascot | Meaning |
|---|---|---|---|
| Free | Green | Sitting | Terminal idle, ready for commands |
| Working | Red (pulse) | Sniffing | Running a task (build, git push, etc.) |
| Service | Blue | Barking | Dev server launched (vite, metro, etc.) |
| Searching | Yellow (pulse) | Idle | Waiting for connection |
| Sleep | Gray | Sleeping | Terminal closed or 10s of inactivity |
- Pixel Art Mascot — animated sprite sheet dog above the status pill
- Custom Sprites — upload your own PNG sprite sheets via manual import or smart extraction with chroma-key background removal
- Frame Range Expressions — specify frames as ranges like
1-5or41-55,57,58when importing custom sprites - Display Scale — resize your mascot with Tiny / Normal / Large / XL presets
- Peer Visits — discover other Ani-Mime users on your local network via Bonjour/mDNS; right-click to send your pet to visit theirs
- Manual Tagging — zsh hooks classify commands as
taskorservice - Heartbeat + OS Scan — hooks drive state transitions; a 2s libproc scan auto-discovers every live shell and cleans up zombies
- Session Dropdown — click the status pill to see every open terminal grouped by project path, with the foreground command (
claude,bun, etc.), and click any row to jump straight to that tab (see Session List & Click-to-Focus) - Claude Code Hooks — tracks when Claude is actively working vs waiting
- Claude Code Management UI — view and manage your Claude Code configuration from Settings → Claude Code: list installed plugins with enable/disable toggles, inspect global and per-project MCP servers, browse and delete custom slash commands, and review/remove hooks
- MCP Server — Claude Code can talk to your pet: trigger speech bubbles, play reaction animations, and check pet status via MCP tools
- Multi-Session — handles multiple terminals, priority: busy > service > idle
- Auto-Setup — first launch configures zsh hooks and Claude Code hooks via native macOS dialogs
- All Workspaces — visible on every macOS Space/desktop
- Menu Bar Tray Icon — always-visible tray icon with right-click menu; left-click toggles mascot visibility
- Hide from Dock — optional setting to remove the app from Dock and Cmd+Tab, running as a menu bar-only app
- Low Footprint — Rust + Tauri, minimal CPU and RAM
![]() |
![]() |
![]() |
| General settings | Customize your favorite Mime | Shadow Clone feature |
![]() |
![]() |
![]() |
| Show on menu bar | One-click import & export your Mime | Claude Code management UI |
Click the status pill to open a dropdown listing every open terminal, grouped by working directory:
Click any row and Ani-Mime brings that terminal to the front. For apps with scripting support it jumps to the specific tab; for the rest it just activates the app. The walk up the process tree uses pidpath + a ps-based ppid map, so it works even across root-owned ancestors like /usr/bin/login.
| App | Activate | Tab-precise focus | How |
|---|---|---|---|
| iTerm2 | ✅ | ✅ | AppleScript: matches the tty property on every session |
| Terminal.app | ✅ | ✅ | AppleScript: matches the tty property on every tab |
| VS Code | ✅ | System Events + window title contains the workspace folder name (can't target individual panes — Electron) | |
| Cursor | ✅ | Same approach as VS Code | |
| tmux (inside any host) | ✅ | ✅ | tmux select-pane -t + select-window + switch-client matched by pane_tty; host app also activated |
| Warp | ✅ | ❌ | No public scripting API for tabs — activation only |
| WezTerm | ✅ | ❌ | Has a wezterm cli pane API but no pid→pane mapping from outside |
| Alacritty / kitty / Hyper / Ghostty | ✅ | ❌ | No inter-app scripting exposed — activation only |
| ssh session | ✅ | ❌ | Remote shells resolve to the local ssh ancestor — activate the local terminal |
The first time Ani-Mime tries to script another app, macOS will prompt:
- iTerm / Terminal — Automation permission. Grant once; subsequent clicks target the exact tab.
- VS Code / Cursor — Accessibility permission (required by System Events to raise windows). Find Ani-Mime under System Settings → Privacy & Security → Accessibility and enable it.
Without these permissions, the click still brings the app to the front via open -a (Launch Services, no permission needed) — you just lose the precise tab / window targeting.
brew tap vietnguyenhoangw/ani-mime
brew install --cask ani-mimeOpen the app. On first launch, Ani-Mime will:
- Ask to add a hook to your
~/.zshrc(required for terminal tracking) - Ask to configure Claude Code hooks (optional)
Open a new terminal tab and the mascot starts reacting.
The MCP server is also auto-configured so Claude Code can interact with your pet directly (see MCP Server below).
Download the bundle for your distro and arch from the Releases page:
# Debian / Ubuntu
sudo apt install ./ani-mime_X.Y.Z_amd64.deb # or _arm64.deb on ARM
# Fedora / RHEL / openSUSE
sudo rpm -i ani-mime-X.Y.Z-1.x86_64.rpm # or .aarch64.rpm
# AppImage (any distro)
chmod +x ani-mime_X.Y.Z_amd64.AppImage && ./ani-mime_X.Y.Z_amd64.AppImageRuntime deps (installed automatically by apt/rpm; required manually for AppImage):
sudo apt install libwebkit2gtk-4.1-0 libayatana-appindicator3-1 zenity xdg-utilsInstall the Linux .deb inside your WSL2 distro. Always-on-top works via a WSLg-specific SetWindowPos(HWND_TOPMOST) shim — no extra setup required.
git clone https://github.com/vietnguyenhoangw/ani-mime.git
cd ani-mime
bun install
bun tauri devOn Linux you also need the build deps:
sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev \
librsvg2-dev libxdo-dev libglib2.0-dev libsoup-3.0-dev libjavascriptcoregtk-4.1-dev \
xdg-utils pkg-config build-essential zenityThen source the shell script for your shell (terminal-mirror.zsh, .bash, or .fish):
echo 'source "/path/to/ani-mime/src-tauri/script/terminal-mirror.zsh"' >> ~/.zshrc
source ~/.zshrc- macOS (Intel or Apple Silicon) — full feature set
- Linux (x86_64 or aarch64) — runs with shell hooks; some click-to-focus integrations are macOS-only
- WSL2 / WSLg — runs as a Linux build with a WSLg-aware always-on-top shim
- Shell — zsh / bash / fish (hooks provided for each)
- Claude Code (optional) — for Claude activity tracking
| Feature | macOS | Linux | WSL2 |
|---|---|---|---|
| Mascot + speech bubbles | ✅ | ✅ | ✅ |
| Shell hook tracking (zsh/bash/fish) | ✅ | ✅ | ✅ |
| Claude Code hooks + MCP server | ✅ | ✅ | ✅ |
| Always-on-top over full-screen apps | ✅ | ✅ | ✅ |
| Peer discovery (mDNS / Bonjour) | ✅ | ✅ | |
| Session list dropdown | ✅ | ✅ | ✅ |
| Click-to-focus terminal tabs | ✅ | ❌ | ❌ |
| Auto shell discovery (libproc scan) | ✅ | ❌ | ❌ |
| Homebrew cask install | ✅ | — | — |
Auto-install update via brew |
✅ | — | — |
Linux and WSL2 fall back to the shell-hook based path for terminal tracking — you get the full mascot + Claude Code + MCP experience, just without the macOS-only auto-discovery and tab-precise focus.
- Frontend: React 19, TypeScript, Vite
- Backend: Rust, Tauri v2, tiny_http
- Shell: zsh hooks (preexec / precmd)
- Sprites: CSS sprite sheet animation (128×128 pixel art, scalable)
- Testing: Vitest (unit), Playwright (e2e)
# Unit tests
bun run test
# E2E tests (requires dev server on :1420)
npx playwright test --config=e2e/playwright.config.tsThe e2e suite covers app startup, status transitions, speech bubbles, scenario mode, settings, custom sprite upload (including frame range expressions), sprite display sizing, and custom sprite editing.
Ani-Mime instances on the same local network automatically discover each other via mDNS (Bonjour). Right-click your mascot to see nearby peers and send your pet to visit them.
- Both machines on the same WiFi / LAN subnet
- macOS Local Network permission — allow when prompted on first launch (or enable in System Settings > Privacy & Security > Local Network)
If peers can't find each other:
- Check that both machines are on the same network (
192.168.x.xsubnet) - Verify Local Network permission is enabled for ani-mime on both machines
- Run
dns-sd -B _ani-mime._tcp local.in Terminal — you should see both instances - Run
curl http://127.0.0.1:1234/debugto check the registered IP and peer list - If sharing the app via DMG without a Developer ID, the recipient must run:
xattr -cr /Applications/ani-mime.app
See docs/peer-discovery.md for the full protocol reference.
Ani-Mime includes an MCP (Model Context Protocol) server that lets Claude Code interact with your pet during conversations.
| Tool | Description |
|---|---|
pet_say |
Make your pet say something via a speech bubble |
pet_react |
Trigger a reaction animation (celebrate, nervous, confused, excited, sleep) |
pet_status |
Check what your pet is doing, who's visiting, nearby peers, and uptime |
The MCP server is automatically configured during first-launch setup (when you accept Claude Code hooks). If you need to set it up manually:
claude mcp add ani-mime -- node ~/.ani-mime/mcp/server.mjsThe server script is updated automatically on every app launch.
Claude Code <--stdio--> MCP Server (Node.js) <--HTTP--> Ani-Mime :1234 --> Pet UI
Claude Code calls MCP tools during conversations. The MCP server translates them to HTTP requests to the local Ani-Mime server, which emits Tauri events to the frontend. The pet reacts with speech bubbles or animation changes.
# Build the Tauri app
bun run tauri build
# Re-sign with entitlements and re-create the DMG
# (required because Tauri doesn't embed entitlements for ad-hoc signing)
bash src-tauri/script/post-build-sign.shThe signed DMG is output to src-tauri/target/release/bundle/dmg/.
Without the post-build sign step, the app will run on the build machine but peer discovery (mDNS) and the HTTP server will silently fail on other machines due to missing network entitlements.
If the recipient sees "app is damaged", they need to remove the quarantine attribute:
xattr -cr /Applications/ani-mime.appbun run tauri buildProduces all three bundle formats under src-tauri/target/release/bundle/{deb,rpm,appimage}/. No post-build signing step required on Linux.
Tag pushes (v*) trigger .github/workflows/release.yml, which runs a 4-job matrix:
| Job | Runner | Target | Artifact |
|---|---|---|---|
| macOS aarch64 | macos-latest |
aarch64-apple-darwin |
.dmg |
| macOS x86_64 | macos-latest |
x86_64-apple-darwin |
.dmg |
| Linux aarch64 | ubuntu-22.04-arm |
aarch64-unknown-linux-gnu |
.deb + .rpm + .AppImage |
| Linux x86_64 | ubuntu-22.04 |
x86_64-unknown-linux-gnu |
.deb + .rpm + .AppImage |
Each release publishes 8 artifacts total.
- Fork the repo
- Create a feature branch (
git checkout -b feature/amazing) - Commit your changes (
git commit -m 'Add amazing feature') - Push (
git push origin feature/amazing) - Open a Pull Request
Contributions for new pixel art sprites, Rust logic improvements, or UI enhancements are welcome.
MIT. See LICENSE for details.








