Skip to content

I Built, My Own Screenshot App for macOS (No More Clunky Screenshots)

How I got fed up with macOS native screenshot chaos, missed Greenshot from my Windows days, and built a lightweight menu bar screenshot app using Swift and Claude.

By Ajay Walia · May 8, 2026 · 8 min read

Share: LinkedIn
A frustrated developer staring at a macOS screenshot toolbar in indie comic style
On this page

It was a Tuesday evening. I had just taken my fourteenth screenshot of the day — a mix of Cmd+Shift+4, accidental desktop saves, files named Screenshot 2026-05-06 at 11.43.22 PM.png scattered across my Downloads folder like confetti after a party nobody enjoyed.

Panel 1 – The Screenshot Graveyard

I opened Finder. Forty-seven PNGs. Forty-seven. Some blurry. Some with my other windows bleeding in at the edges. Some cropped wrong because I’d sneezed mid-drag.

There had to be a better way.


The Ghost of Greenshot Past

Back in my Windows days — and I spent a lot of years in Windows, running datacentres, managing Wintel estates, building VDI platforms — I had Greenshot. If you’ve never used it, Greenshot is a free, lightweight screenshot tool that lives in your system tray. Press PrtSc, draw a box, done. Instant annotation. Instant clipboard. Instant sanity.

When I moved to macOS full-time, I expected something better. Apple builds beautiful hardware. Their software is generally excellent. And their screenshot workflow is… fine. Technically fine. But when you’re taking screenshots all day for documentation, Slack messages, architecture diagrams, and blog posts — “fine” isn’t good enough.

The native flow is: Cmd+Shift+4, drag imprecisely, file saves somewhere, you hunt for it, you paste it, you realise the crop was off, you do it again.

Panel 2 – The Ghost of Greenshot

I Googled “Greenshot for Mac” approximately eleven times over the past year. The answers: CleanShot X (paid, subscription), Shottr (good but someone else’s decisions), or just “get used to it.”

I couldn’t get used to it. So I did what any reasonable enterprise architect does at 10pm on a Tuesday.

I decided to build it myself.


Fine. I’ll Build It.

The plan was simple: a lightweight macOS menu bar app. Lives in the status bar. One click or a hotkey and you’ve got a clean area capture, a window capture, or a full-screen grab. Auto-saves with a sensible filename. Copies to clipboard. Makes a satisfying shutter sound. Stays out of your way.

The twist: I’d build it the same way I built this blog — with Claude as my pair programmer and VS Code as the editor. I’m an architect and technologist, not a Swift developer. But that was the whole point.

I opened a new conversation, described what I wanted in plain English, and we got to work.


What AJShot Is

Panel 3 – The “AJ” badge appears in the menu bar

AJShot is a native macOS menu bar app — background-only, no Dock icon, no bloat. It sits quietly in your menu bar with a small AJ badge. Left-click opens your last screenshot. Right-click opens the action menu.

Memory footprint: around 50 MB at idle. Compare that to some Electron-based tools that idle at 300 MB just saying hello.

The right-click menu looks like this:

📷 Capture Area          ⌘⇧3
🖥  Capture Window        ⌘⇧4
🖥  Capture Fullscreen    ⌘⇧5
─────────────────────────────
📂 Open Last Screenshot
📁 Open Screenshots Folder
─────────────────────────────
⚙️  Preferences
ℹ️  About
✕  Quit

The keyboard shortcuts are global — they work even when AJShot is in the background. You’re deep in a Zoom call, you need a quick capture, you hit Cmd+Shift+3, draw the box, done. The screenshot is already in your designated folder and on your clipboard before you’ve even let go of the mouse.


Core Features

Panel 4 – Area selection crosshair in action

Capture Modes

Area Capture (⌘⇧3) — the workhorse. Full-screen overlay appears, cursor becomes a crosshair, you draw a box. Precise. Consistent. No more dragging the wrong direction and getting a sliver of your taskbar.

Window Capture (⌘⇧4) — click a window, capture just that window. No background bleed, no accidental desktop icons photobombing your documentation.

Fullscreen Capture (⌘⇧5) — captures everything. Supports multi-display setups with a “capture all” or “ask each time” behaviour you configure once.

Preferences That Actually Make Sense

Panel 5 – The Preferences panel, organised and calm

Open Preferences and you get a clean panel with the options you’d actually want to configure:

SettingDefaultWhat it does
Launch at loginOnAJShot is always ready, even after restart
Play capture soundOnSatisfying shutter click confirms the capture
Show thumbnail previewOnFloating preview appears — click to open in editor
Auto-copy to clipboardOnScreenshot lands in your clipboard automatically
Save folder~/Pictures/AJShotYour own designated screenshot home
File formatPNGOr JPG with a quality slider
Filename templateAJShot_{date}_{time}Consistent, sortable, sane filenames

The filename templating engine handles the sanitisation itself — no illegal characters, no trailing dots, no 240-character filenames. Files come out like AJShot_2026-05-09_22-14-37.png. You can find them instantly. You can sort them. Your Downloads folder stays clean.

Post-Capture Flow

After every capture, AJShot runs through a quick sequence:

  1. Auto-saves to your configured folder with the filename template applied
  2. Copies to clipboard (if enabled) — so you can paste immediately
  3. Plays the shutter sound — audio confirmation that the capture happened
  4. Shows a floating thumbnail in the corner — click it to open in the editor

You can also configure the post-capture action to always ask, always edit, always save, or always copy. Once you’ve decided how you work, it remembers.


The Real Problem It Solves

Here’s the honest comparison:

Native macOSAJShot
Start captureCmd+Shift+4, wait for toolbarCmd+Shift+3, instant overlay
File locationDesktop or last used folderAlways ~/Pictures/AJShot
FilenameScreenshot 2026-05-09 at 10.14.22 PM.pngAJShot_2026-05-09_22-14-22.png
Clipboard copyManual extra stepAutomatic
EditorPreview.app detourBuilt-in (annotation tools in progress)
Memory useSystem process~50 MB dedicated
Works in backgroundPartialFull global hotkeys
Shutter soundYesYes (configurable)

The editor is where things get even more interesting. The annotation scaffolding is already built — the tools are there in the codebase: arrows, blur, text, highlights, shapes, step-number callouts. They’re not wired to the UI yet, but they’re coming. That’s the next milestone.


Tech Stack — What’s Actually Under the Hood

Panel 6 – The Swift codebase, compact and organised

This is a native macOS app built entirely in Swift 5.9+, targeting macOS 12 (Monterey) and later. The UI is a hybrid of SwiftUI and AppKit — SwiftUI for the Preferences panel and modern views, AppKit where you need fine-grained control over system behaviour (status bar items, window management, capture overlays).

Dependencies (both by Sindre Sorhus, the prolific open-source developer behind half the macOS indie tool ecosystem):

  • KeyboardShortcuts — global hotkey registration that plays nicely with macOS security
  • Defaults — a type-safe, SwiftUI-friendly wrapper around UserDefaults

Capture pipeline: uses CGPreflightScreenCaptureAccess and CGRequestScreenCaptureAccess from CoreGraphics for the permission preflight, then ScreenCaptureKit for the actual pixel capture. The permission flow has a proper retry loop — if you’ve granted permission but haven’t restarted the app, it tells you exactly that and offers a one-click restart.

Build and distribution: Swift Package Manager for dependencies, Xcode 15 for the build, and a build-dmg.sh script that produces a signed AJShot-1.0.0.dmg for distribution. The DMG is already built. You can drag it to Applications and run it today.

Security considerations (because I work in security and these things matter):

  • Screenshot folder is set to 0700 permissions — only you can read it
  • Individual screenshot files are 0600 — same
  • Filename template engine strips illegal characters and control characters at the source
  • Code signing and notarization stubs are already in the README for when distribution goes wide

The architecture is clean: AppAppDelegateStatusBarControllerCaptureManagerScreenshotStorage. Each module does one thing. The FilenameTemplateEngine is a pure static function. The ThumbnailPresenter is decoupled from capture. Claude helped me keep it disciplined.


The Honest Struggles

No developer story is complete without the bit where things go sideways.

Screen Recording permissions nearly broke me on the first build. macOS 12+ requires explicit Screen Recording permission in System Settings, and you can’t force-trigger the dialog more than once per session. I had to build the multi-stage fallback: first launch triggers Apple’s native dialog, subsequent denials open System Settings directly, and if you’ve granted permission but not restarted, it detects that state and offers a restart button. It took longer to get that right than the actual capture code.

Swift Package Manager vs Xcode had a brief disagreement about the resource bundle for shutter.aiff. The sound file lives in AJShot/Sounds/ and has to be declared as a .process("Sounds") resource in Package.swift. Simple when you know it. Less simple at 11pm when it just silently fails to play.

The LaunchAtLogin manager required writing a LaunchAgent plist to ~/Library/LaunchAgents/. Straightforward on paper. In practice, macOS is protective of that folder in ways that aren’t well-documented, and the error messages when something goes wrong are the kind that send you to Stack Overflow threads from 2019.

That’s the thing about building a native macOS app — the platform is powerful and the APIs are solid, but the surface area of “things that can quietly not work” is larger than you’d expect. Claude helped me navigate most of it. The frustration was real and so was the progress.


What’s Next

Panel 7 – “It just works.” The menu bar icon glows.

The annotation editor is the next major milestone — the scaffolding is already there. Arrow tool, blur tool, text tool, highlight, shapes, step-number callouts. When that’s wired up, AJShot becomes a complete Greenshot replacement for macOS: capture, annotate, save, share.

After that: GitHub release with a public DMG, code signing, notarization, and probably a product page here on CuriousBit.

If you’re a macOS user who’s been putting up with the native screenshot workflow out of habit — you don’t have to. And if you’re a developer (or aspiring one) who thinks you can’t build a native app without being a full-time Swift engineer — you can. You really can.


Try It / Share What You Use

The GitHub repo is coming soon — I’ll post the link here when it’s public. In the meantime, if you’re curious about the architecture, the Swift source, or want to follow along as the editor gets built, keep an eye on this blog.

And I’m genuinely curious: what screenshot tool do you use on macOS? Are you a CleanShot loyalist? A Shottr person? Still using the native tools and somehow thriving? Drop a note — I’d love to know.

Because the best tools are the ones built out of genuine frustration with the alternative. And I was very genuinely frustrated.

Ajay Walia

About the Author

Ajay Walia

AI {IT Architect} focusing on local-first multi-agent AI engineering, zero-data-egress systems. Ideator, Creator and Executor on Curious Bit.

Don't stop now

Keep Reading