Skip to content

Repository files navigation

Memory Penguin

Memory Penguin app icon

Memory Penguin is a lightweight macOS menu bar app that shows current memory pressure with a small penguin icon. Click the menu bar icon to inspect effective memory use, physical occupancy, swap activity, top memory processes, top CPU processes, and temporary CPU controls for selected high-usage processes.

The app is built with Swift and AppKit. It does not require Electron or any extra runtime.

AI Assistance

Memory Penguin was developed through collaboration between the user and Codex. The code, feature changes, README, and build workflow were assisted by Codex.

The app icon and menu bar icon assets were generated by ChatGPT 5.5 and then integrated into the macOS app bundle.

Acknowledgements

Memory Penguin is inspired by Stats, a macOS menu bar system monitor by Serhiy Mytrovtsiy and contributors.

Icon States

Calm Elevated High
Calm memory pressure icon Elevated memory pressure icon High memory pressure icon
Normal memory pressure Elevated memory pressure High memory pressure

The menu bar uses three pre-generated 48 x 44 transparent PNG assets. The app loads and caches the matching asset for each pressure state; it no longer crops or removes the sprite-sheet background at runtime. The original Resources/memory_icon.png sprite sheet remains in the repository and app bundle as the source artwork.

Features

  • Shows the effective used memory estimate percentage and memory pressure state in the menu bar.
  • Uses three penguin icon states for memory pressure:
    • Calm: short green mark
    • Elevated: medium yellow mark
    • High: long red mark
  • Toggles whether the menu bar percentage is shown.
  • Toggles detailed memory information in the menu.
  • Enables or disables Launch at Login.
  • Displays memory details:
    • Total
    • Effective used estimate
    • Physical occupied
    • Reclaimable estimate
    • Kernel free, including speculative pages
    • Bounded anonymous estimate
    • Bounded file-backed estimate
    • Raw file-backed and anonymous counters
    • Active
    • Inactive
    • Wired
    • Compressed
    • Purgeable
    • Speculative
    • Page-out rate
    • Swap traffic rate
    • Swap used / available / total
  • Displays top memory processes and top CPU processes.
  • Lets you click a top CPU process to add it to a temporary CPU limit list.
  • Supports these CPU limit modes:
    • Background Priority
    • Run 75% of Time
    • Run 50% of Time
    • Run 25% of Time
    • Remove Limit
  • Validates each limited process by PID, owner UID, and microsecond-resolution start time before every control signal.
  • Rejects PID 0/1, other users' processes, Memory Penguin itself, and protected macOS interface or system processes.
  • Uses an independent heartbeat resume guard so a stopped process is resumed if Memory Penguin exits unexpectedly or its main loop stops responding.

Requirements

  • macOS 13 Ventura or later
  • Xcode Command Line Tools
  • Swift 6 toolchain

Install Xcode Command Line Tools:

xcode-select --install

Build

Clone or download the project, then run this from the project root:

chmod +x Scripts/build-app.sh
Scripts/build-app.sh

The app bundle and portable archive will be created at:

dist/MemoryPenguin.app
dist/MemoryPenguin.zip

The archive is created from the clean signed staging bundle and independently extracted and verified by the build script. This prevents Desktop file-provider metadata from being stored inside the distributable app.

Run the app:

open dist/MemoryPenguin.app

For regular use, prefer launching the .app bundle instead of using swift run. The app bundle applies LSUIElement, which lets Memory Penguin run as a Dockless menu bar utility.

Install

Move the built app into /Applications:

cp -R dist/MemoryPenguin.app /Applications/
open /Applications/MemoryPenguin.app

If you want to use Launch at Login, place the app in /Applications first, then enable Launch at Login from the Memory Penguin menu.

The build script ad-hoc signs the local app bundle so macOS can register it as a login item. This is not a notarized release. If you plan to distribute the app publicly, use a proper Developer ID signature and notarization flow.

Development

Run the app directly during development:

swift run

swift run does not fully reproduce the app bundle's LSUIElement behavior. To test the normal menu bar app experience, use:

Scripts/build-app.sh
open dist/MemoryPenguin.app

For each intentional release or user-facing change, add an entry under Unreleased in CHANGELOG.md. When preparing a release, move those entries into a dated version section and update CFBundleShortVersionString in Resources/Info.plist to the same version. Scripts/build-app.sh reads that version and updates the bundled CFBundleVersion to a timestamp build number.

Regenerate the transparent status icons and README previews after changing the source sprite sheet:

swift Scripts/generate-icon-previews.swift

On macOS 14 or later, the generator uses the system Vision foreground mask to preserve the black penguin while removing the dark background.

Tests

Run the core self-tests from the project root:

swift run MemoryPenguinCoreSelfTests

The self-test executable verifies the reusable core logic without launching the menu bar app. It covers effective used, reclaimable, and physical occupancy calculations; activity rates; memory pressure mapping; ps parsing; process sorting; PID reuse detection; owner and protected-process checks; and duty-cycle labels.

Run the resume guard integration test after building the executable:

swift build --product MemoryPenguin
swift Scripts/ResumeGuardIntegrationTest.swift

The integration test creates its own /bin/sleep children, confirms they enter SSTOP, and verifies that both a closed heartbeat pipe and a two-second heartbeat timeout restore them.

CPU Limiting

CPU limiting is session-based. A limit is bound to the selected PID, effective owner UID, and process start time; if the PID exits and is reused, Memory Penguin refuses to signal the replacement process.

Background Priority uses macOS taskpolicy -b. This is a gentle limit that lowers scheduling priority, but it does not guarantee a fixed CPU percentage.

Duty-cycle modes use periodic SIGSTOP / SIGCONT signals to pause and resume the process. Run 50% of Time means the process runs for roughly half of each one-second period; it does not mean an absolute 50% CPU ceiling. A four-worker process that previously consumed about 400% CPU may still average around 200% CPU under this mode.

Each duty-cycle process has a helper mode of the same signed executable watching a heartbeat pipe. If Memory Penguin crashes or is force-quit, the pipe closes and the helper resumes the exact original process. If the app remains alive but stops sending heartbeats, the helper resumes the process after two seconds. Normal removal also resumes the process and removes background priority.

Duty-cycle control can still make GUI, audio, download, compiler, or I/O-heavy applications temporarily unresponsive. Protected system processes and processes owned by another user are not controllable.

CPU Limit Testing

The project includes a CPU stress test utility for testing the top CPU process list and CPU limiting behavior.

Compile it first so the process list shows a clear CPUStressTest process name:

swiftc Scripts/CPUStressTest.swift -o /tmp/CPUStressTest
/tmp/CPUStressTest --workers 2 --seconds 120

You can also run it directly as a Swift script:

Scripts/CPUStressTest.swift --workers 2 --seconds 120

Test flow:

  1. Run CPUStressTest.
  2. Open the Memory Penguin menu.
  3. Find CPUStressTest under Top CPU Processes.
  4. Click CPUStressTest to add it to Limited Processes.
  5. Choose Run 50% of Time or another limit mode from the submenu.
  6. Click the checked top CPU process again, or choose Remove Limit from the Limited Processes submenu, to remove the limit.

Resource Use

When the menu is closed, Memory Penguin updates lightweight memory information every 2 seconds and does not read the process list.

When the menu is open, Memory Penguin updates every 1 second and reads the process snapshot on a background queue to refresh the top memory and top CPU process lists without blocking the menu UI.

Memory data sources:

  • host_statistics64
  • sysctl
  • kern.memorystatus_vm_pressure_level

Process list source:

/bin/ps -axo pid=,rss=,pcpu=,comm=

The app reads a ps snapshot and sorts the processes in app code. Launch failures, nonzero exits, and invalid output are shown as Process list unavailable rather than being presented as an empty process list.

Memory Pressure Model

Activity Monitor's full memory pressure formula is not a public API. Memory Penguin uses macOS kern.memorystatus_vm_pressure_level as its pressure state source and maps it to:

  • Calm
  • Elevated
  • High

The percentage shown in the menu bar is an effective used memory estimate, not Activity Monitor's private memory pressure percentage. macOS memory pressure remains the authoritative health signal.

Current memory model:

  • Physical occupied: total physical memory - kernel free count
  • Kernel free: capped to total physical memory; vm_statistics64 documents that this count already includes speculative pages
  • Non-free file-backed estimate: file-backed memory - speculative memory, floored at zero
  • Reclaimable estimate: non-free file-backed estimate + purgeable memory, capped to physical occupied memory
  • Effective used estimate: physical occupied - reclaimable estimate
  • Anonymous estimate: anonymous counter capped to physical occupied memory
  • File-backed estimate: file-backed counter capped to physical occupied memory

Active/inactive state, anonymous/file-backed backing, and purgeable status are overlapping classification dimensions. Memory Penguin normalizes speculative pages before estimating reclaimable memory and continues to display the raw counters separately for transparency.

Project Structure

Sources/MemoryPenguin/main.swift              App menu, status item, and UI wiring
Sources/MemoryPenguinCore/                    Reusable memory/process/core logic
Tests/MemoryPenguinCoreSelfTests/main.swift   Core self-test executable
Resources/Info.plist                          macOS app bundle metadata
Resources/icon.png                            App icon
Resources/memory_icon.png                     Original menu bar sprite sheet
Resources/Generated/StatusIcons/              Bundled transparent menu bar icons
Scripts/build-app.sh                          Build app bundle
Scripts/CPUStressTest.swift                   CPU stress test utility
Scripts/ResumeGuardIntegrationTest.swift      Resume guard process integration test
Scripts/generate-icon-previews.swift          Status icon and preview generator

License

MIT License. See LICENSE.

Notes

Memory Penguin is a local-use utility. Duty-cycle control sends signals to other processes, so avoid limiting apps that are saving important data or workloads that cannot tolerate temporary pauses.

About

A lightweight macOS menu bar app for monitoring memory pressure, swap activity, top processes, and temporary CPU throttling.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages