A pixel cat that lives in your menu bar and chases your cursor β forever.
Native macOS app. Metal GPU rendering. 120 Hz. No Electron. No bloat.
In 1989, a Japanese programmer put a tiny cat on the desktop that chased the cursor.
It became one of the most beloved pieces of software ever written.
OnekoMac brings that cat back β as a proper native macOS app, rebuilt from scratch:
- Runs as a floating overlay above every window, every Space, every full-screen app
- Rendered with Metal at up to 120 Hz (ProMotion-aware)
- Follows your cursor with the original
oneko.jsanimation logic, 1:1 ported - Idles, scratches the wall, falls asleep if you leave it alone
- Lives quietly in your menu bar
No Dock icon. No subscriptions. No tracking. Just a cat.
| Classic | Dog | Tora | Maia | Vaporwave |
|---|---|---|---|---|
Switch between skins at any time from the settings panel.
- Go to Releases
- Download
OnekoMac.dmg - Drag to Applications
- Launch β the cat appears immediately
The app will ask for no permissions. If your cursor is moving, the cat follows it.
brew install --cask hellov3an/tap/onekomacgit clone https://github.com/hellov3an/OnekoMac
cd OnekoMac
xcodegen generate
open OnekoMac.xcodeprojRequires Xcode 15+, macOS 13+ SDK, and xcodegen.
- Metal GPU renderer β CAMetalLayer + CVDisplayLink + triple-buffered command queue
- 120 Hz β frame-synced to ProMotion displays, smooth on 60 Hz too
- oneko.js logic β 8-directional movement, idle states, scratch, sleep
- 5 pixel-art skins β sourced from kyrie25/spicetify-oneko
- Floating settings panel β skin picker with live previews, FPS counter
- Auto-update checker β checks GitHub Releases, one click to update
- Zero CPU at idle β CVDisplayLink only renders when needed
- Universal Binary β Apple Silicon and Intel
The cat runs a 100 ms logic tick (matching the original JavaScript timing):
- Compute distance to cursor
- If far β pick 8-directional movement animation β move by 10 pts/tick
- If near β idle, then scratch, then sleep
Sprites come from a 256Γ128 px GIF atlas (8Γ4 grid of 32Γ32 px frames).
The Metal shader converts top-left screen coordinates to NDC in one pass.
Skins are 256Γ128 px GIF files arranged as an 8-column Γ 4-row sprite sheet β the same format as the original oneko.js.
col β 0 1 2 3 4 5 6 7
row 0 [nwl][nwl][slp][slp][scW][scS][scS][scS]
row 1 [nwl][nwl][slp][slp][scW][ SE][ SW][ S ]
row 2 [NE ][NE ][E ][trd][W ][SE ][SW ][S ]
row 3 [NE ][NE ][E ][idl][W ][SE ][SW ][alt]
Each cell is 32Γ32 px. The idle frame is at col 3, row 3.
- Canvas: exactly 256 Γ 128 px
- Each cell: 32 Γ 32 px (pixel art, no anti-aliasing)
- Name it
oneko-<id>.gif(e.g.oneko-ghost.gif) - Keep the same animation grid as the originals β copy one of the bundled GIFs as a starting point
Drop your GIF in Resources/Sprites/, then add its ID to SkinManager.skinIDs in Skins/SkinManager.swift:
static let skinIDs = ["classic", "dog", "tora", "maia", "vaporwave", "ghost"]Build and run β your skin appears in the picker immediately.
- Fork this repo
- Put your GIF in
Marketplace/(create the folder if needed) - Add an entry to
.github/marketplace/manifest.json:
{
"id": "ghost",
"name": "Ghost",
"author": "yourGitHubHandle",
"bundled": false,
"url": "https://raw.githubusercontent.com/hellov3an/OnekoMac/main/Marketplace/oneko-ghost.gif"
}- Open a Pull Request β once merged, the skin appears in every user's Marketplace panel without an app update
Tip: for the
urlfield in your PR, use your fork's raw URL first so the skin can be previewed before merge.
PRs welcome β skins, bug fixes, new features, translations.
Bug reports β Issues
- Original oneko β Masayuki Koba, 1989
- Sprite artwork β kyrie25/spicetify-oneko
- Built with Swift + Metal by @hellov3an
If this made you smile, hit the β β it helps more people find the cat.
