Skip to content

Create a desktop pet that won’t nag you

Roam is a Mac desktop pet I’m developing. I’ve set one rule for it: the pet only reflects its environment and past events; it doesn’t judge you or ask you to do anything. Following this rule, I’ve removed daily check-ins, feeding, unlocking, and system notifications, and I’ve changed how visit durations and Do Not Disturb work.

Filed under
Products
Reading Time
11 min read
Published on
2026.09.11

In short

When deciding whether to include companion-style features, I ask myself if they might make people feel even a hint of guilt or a sense of obligation. If they do, I don’t include them. Consequently, we’ve removed daily check-ins, pet-raising mechanics, progress bars, and system notifications. You can leave messages even when your friend isn’t online, but there are no unread counts or badge notifications. Progress is tracked only by what has happened—we don’t show how much is left to achieve. Since it’s rare for both people to be sitting at their computers at the same time, we prioritize gameplay that doesn’t require simultaneous online presence.

🐾 Creating a Desktop Pet That Doesn’t Rush You

Rules I Set for Roam, My Mac Desktop Pet—What I Cut, Changed, and Added

I originally planned to create an unlock system for the desktop pet. The more friends the pet makes, the more accessories it can wear—a pretty common design that isn’t hard to implement.

This pet is called Roam, a little Mac app I’ve been working on lately. It’s a computer-generated slime on the screen—no art assets were used—that usually wanders around the desktop, sleeps when it’s tired, and can be dragged or clicked. Once you add friends, it can pop over to their desktop for a visit, stay for a while, and then come back.

Roam’s two slime pets: a friend’s orange pet comes to visit; when the owner taps their own teal pet, it bounces once and grows a tuft of hair

The GIF was rendered off-screen using Roam’s own rendering code; the animations were scripted—no screen recording was used.

I didn’t end up implementing the unlock feature. On September 8, I set a rule for Roam, and once I applied it, I couldn’t get past the unlock stage.

When it comes to a specific feature, I ask myself just one question: Will it make people feel even a hint of guilt, or make them feel like they owe it something? If so, I don’t do it.

✂️ Testing It Against the Rule

The unlock gets stuck here. “Made 4 friends” is a simple record, but if you change it to “Make 1 more friend to unlock an accessory,” it becomes a task. The number stays the same, but the second sentence adds a gap waiting to be filled. I kept the “accumulation” part, but removed the unlock mechanism, the progress bar, and the “how many more to go” prompt.

I cut a few other things that same day. I didn’t hesitate much about the Pomodoro timer and focus tracker—desktop pets that start bossing people around just annoy everyone. The “virtual pet” feeding mechanic also didn’t work for me—when the pet gets hungry, it waits for you to feed it. That flips the dynamic; it becomes the pet begging you for something. Coming back from a week-long business trip to find your pet nearly starving to death—that’s not companionship.

The daily check-in feature gave me the most pause. Every day when I turned on my computer, the pet would remember how many days I’d been there—which in itself was pretty harmless. But if I skipped a day, a message would pop up on the screen saying, “You haven’t let your pet go out to play for 7 days,” and the moment I booted up, I’d suddenly have one more thing on my mind that I hadn’t taken care of. Out of all these features, I found this one the most insidious, because it looked the most like companionship.

🔁 Rethinking System Notifications and Visit Duration

System notifications were removed in a later update. In the original permissions, there was a setting called notify that allowed system notifications to pop up. The intention behind it was practical: I wanted to know when friends had stopped by while I wasn’t at my computer. But notifications are just a way to demand your attention. I deleted that entire setting and replaced it with the pet carrying that piece of information the next time you see it. If you see it, you’ll know who’s been there; if you don’t, there won’t be a little red dot waiting for you in the corner.

The duration of visits has also been adjusted once. Originally, the visitor would request 30 seconds, after which they’d automatically leave. Now, the default is still 30 seconds, but the host can right-click on the guest and select “Stay a Little Longer” to add 30 seconds at a time, up to a maximum of 5 minutes. They can also click “Please Leave.”Control over the timing remains firmly in the owner’s hands, and anti-harassment measures haven’t been relaxed at all. However, there’s a huge difference in how “allowing guests to stay” and “forcing guests to leave when time’s up” actually play out.

🌱 Features Added According to the Rules

Just cutting features isn’t enough—a desktop pet needs to have some reason for people to keep it around. On the evening of September 8, I added a few more features following the same principle.

👆 Response to Being Touched

Previously, visits were one-way—my pet would wander around your desktop, and you could only watch. Now, when you click on a visiting pet, I’ll see it react on my end too.

Here, I chose a more roundabout approach. When you click, your local screen just displays a very subtle “bump”—the actual reaction is calculated by the engine on my computer and then synchronized back to your screen along with the pet’s posture. Rendering it directly on your end would be simpler, and the visuals would be nearly identical—but then the reaction you’d see would be generated by your own computer.

🌿 Visiting Even When They’re Away

Even when a friend isn’t at their computer, a pet can still pay a visit, leave a small item, or deliver a message. When they return, their pet will be carrying this item. With a single tap, the pet tells them who stopped by.

This feature could easily turn into an inbox if not handled carefully, so I’ve added a few restrictions.

I also tweaked the “Do Not Disturb” setting. Previously, if the other person had “Do Not Disturb” enabled, the pet would be immediately turned away. Now, whether they have “Do Not Disturb” on or are in full-screen mode, the pet will leave a message before leaving—so the trip isn’t wasted. If the cooldown hasn’t ended, or if the other person hasn’t granted permission at all, the pet leaves nothing behind. In the former case, the other person is simply unavailable at the moment; in the latter, the visit wasn’t appropriate to begin with.

Messages are handled via CloudKit, using the online signaling system for logging. I’ve tested the entire process using two instances, A and B, under a valid signature.

  1. Completed: A 留下一片 🌿

    B 此时不在

  2. Completed: B 收到

    东西落到本地

  3. Completed: B 重启

    宠物身上还带着它

  4. Completed: 点一下宠物

    它说出是谁来过

  5. Completed: 清掉

    看过就没了,不留记录

🧮 Only Records What Has Happened

This section covers the remaining parts from the unlocking and disassembly process described at the beginning. The pet keeps track of how many times it has visited others, been visited, been petted, and petted others. These counts only affect two very subtle cosmetic changes: the walking frequency changes slightly, and a stray hair grows when it’s been petted. The “About This Pet” page only records what has actually happened.

🌙 Generally Follows the Computer’s Status

It goes to sleep early at night; when its battery drops below 20%, its movements slow down, and occasionally, with a 10% chance, it’ll go out for a long walk. The struct in the code that describes the environment is called PetEnvironment ; none of its fields are related to your performance—it doesn’t track focus duration, activity levels, or usage statistics. The day it starts evaluating how well you’re doing, it’ll just turn into another lecturing tool.

🎮 Two-player mini-games are on hold for now

I’ve considered chase games, catch, and tug-of-war. P2P direct connections use UDP, the latency is acceptable, and it wouldn’t be hard to implement.

I didn’t do it because it would simultaneously consume both players’ online time and attention. Desktop pets are mostly things you glance at out of the corner of your eye; very few people would sit down to play with one. I figure people would get bored after playing it twice, but maintenance would be an ongoing cost.

Any gameplay that requires both players to be online at the same time hits this limit—the more resource-intensive it is, the less worthwhile it becomes. That’s why “playable even when you’re not there” takes priority over all synchronous gameplay.

🧭 Quick Reference for Trade-offs

FeatureResultWhy
Daily Check-insCutMissing a single day turns it into an unfinished task
Pet Care & RaisingCutPets will end up asking you for things
Pomodoro Timer, Focus TrackingCutTrying to manage people just makes you unpopular
Unlock-Based ProgressRemove the unlock mechanism; keep the progressRecords can stay, but tasks must go
System Notifications notifyRemove this categoryChange it so the pet brings up that task when it sees you
Visit DurationLet the owner set itGuests can be invited to stay
Do Not DisturbChange from blocking to leaving a message“Busy” just means temporarily unavailable
Reaction to Being PetAddReactions come from the engine on the other player’s computer
Can visit even when offlineAddedDoes not require both players to be online at the same time
Two-player mini-gamesNot implemented for nowTakes up both players’ online time and attention simultaneously

📦 If you’d like to give it a try

Roam 0.1.0 has been released. It’s been signed with a Developer ID and notarized. Download the ZIP file, unzip it, and drag it into “Applications” to launch it. The source code is in a private repository; download it from CassianFlorin/Roam-app.

Both players must have the app installed to play online. Click the paw print icon in the menu bar to copy your pairing string and send it to the other person. They can then click “Add Friend” and paste it in. You can now visit each other’s spaces—when you come to mine, I can go to yours, and there will be two of each on both screens. You can only visit one home at a time, but you can host multiple visitors.

Keep reading