Capso Screenshot Macos

reason-machines/trending-skills/skills/capso-screenshot-macos

by reason-machines2384a003145aNo license83 starsListed Oct 8, 2026Updated Oct 8, 2026Repository updated 3 months ago

Expert skill for Capso, the open-source macOS screenshot and screen recording app built with Swift 6 and SwiftUI — covers architecture, building from source, package APIs, and contributing.

Instructions onlySoftware Development
AI-generated overview

Reference guide to Capso, an open-source macOS screenshot and screen recording app, its Swift packages and APIs.

What it does
This skill documents Capso, a native macOS screenshot and screen recording app built with Swift 6 and SwiftUI, covering its modular SPM package architecture. It explains how to install or build the app from source and how to embed individual packages such as CaptureKit, AnnotationKit, OCRKit, RecordingKit, CameraKit, ExportKit and SharedKit in another app. It provides API usage examples, SwiftUI integration patterns, required entitlements and Info.plist keys, test commands and troubleshooting notes.
When to use it
Use it when adding screenshot, screen recording, annotation, OCR or webcam picture-in-picture features to a macOS app, or when building Capso from source. It also suits developers who want to contribute to the Capso open-source project.
Requirements
Requires macOS 15.0 or later, Xcode 16 or later and XcodeGen for building from source; the documented packages depend on ScreenCaptureKit, AVFoundation, Vision and Carbon. Screen recording, camera and microphone permissions must be granted, and network access is needed to clone the repository or download releases. The skill ships instructions only, with no scripts.

Capso Screenshot & Screen Recording Skill

Skill by ara.so — Daily 2026 Skills collection.

Capso is a fully native, open-source macOS screenshot and screen recording app — a free alternative to CleanShot X. Built with Swift 6.0 and SwiftUI targeting macOS 15.0+. Its key strength for developers is a modular SPM architecture: 8 independent packages (CaptureKit, AnnotationKit, OCRKit, etc.) you can embed individually in your own app.


Installation

Download Pre-built App

bash
# Homebrew (recommended)brew tap lzhgus/tapbrew install --cask capso

Or download the signed DMG from GitHub Releases.

Build from Source

Requirements: Xcode 16+, macOS 15.0+, XcodeGen

bash
brew install xcodegen
git clone https://github.com/lzhgus/Capso.gitcd Capsoxcodegen generateopen Capso.xcodeproj# Press Cmd+R to build and run

CLI build:

bash
xcodegen generatexcodebuild -project Capso.xcodeproj \  -scheme Capso \  -configuration Release \  build

Project Architecture

Capso/├── App/                     # Thin SwiftUI + AppKit shell│   ├── CapsoApp.swift       # @main entry point│   ├── MenuBar/│   ├── Capture/│   ├── Recording/│   ├── Camera/│   ├── AnnotationEditor/│   ├── OCR/│   ├── QuickAccess/│   └── Preferences/├── Packages/│   ├── SharedKit/           # Settings, permissions, utilities│   ├── CaptureKit/          # ScreenCaptureKit wrapper│   ├── RecordingKit/        # Screen recording engine│   ├── CameraKit/           # AVFoundation webcam capture│   ├── AnnotationKit/       # Drawing/annotation system│   ├── OCRKit/              # Vision framework OCR│   ├── ExportKit/           # Video/GIF/image export│   └── EffectsKit/          # Cursor effects, click highlights└── project.yml              # XcodeGen project definition

The app shell is intentionally thin — all logic lives in packages. This means you can pull individual packages into your own app via SPM.


Using Capso Packages in Your Own App

Add a package as a local or remote SPM dependency in your Package.swift:

swift
// Package.swiftlet package = Package(    name: "MyApp",    platforms: [.macOS(.v15)],    dependencies: [        // Remote (once published to a registry or via exact path)        .package(path: "../Capso/Packages/CaptureKit"),        .package(path: "../Capso/Packages/AnnotationKit"),        .package(path: "../Capso/Packages/OCRKit"),    ],    targets: [        .target(            name: "MyApp",            dependencies: [                "CaptureKit",                "AnnotationKit",                "OCRKit",            ]        ),    ])

Package API Examples

CaptureKit — Screen Capture

CaptureKit wraps ScreenCaptureKit for area, fullscreen, and window capture.

swift
import CaptureKit
// Area capturelet captureManager = CaptureManager()
// Fullscreen captureTask {    let image: NSImage = try await captureManager.captureFullscreen()    // use image}
// Window capture — pass SCWindow from ScreenCaptureKitTask {    let content = try await SCShareableContent.excludingDesktopWindows(false, onScreenWindowsOnly: true)    if let window = content.windows.first {        let image: NSImage = try await captureManager.captureWindow(window)    }}
// Area capture with a selection rectTask {    let rect = CGRect(x: 100, y: 100, width: 800, height: 600)    let image: NSImage = try await captureManager.captureArea(rect)}

RecordingKit — Screen Recording

swift
import RecordingKit
let recorder = ScreenRecorder()
// Configure recordingvar config = RecordingConfiguration()config.includesSystemAudio = trueconfig.includesMicrophone = falseconfig.outputFormat = .mp4   // or .gifconfig.quality = .maximum    // .social, .web
// Start recording a regionTask {    let outputURL = URL(fileURLWithPath: "/tmp/recording.mp4")    try await recorder.startRecording(        region: CGRect(x: 0, y: 0, width: 1920, height: 1080),        to: outputURL,        configuration: config    )}
// Pause / resumerecorder.pause()recorder.resume()
// Stop and get final URLTask {    let finalURL = try await recorder.stopRecording()    print("Saved to \(finalURL)")}

CameraKit — Webcam PiP

swift
import CameraKit
let cameraManager = CameraManager()
// Request permission and start previewTask {    let granted = await cameraManager.requestPermission()    guard granted else { return }        // Get AVCaptureVideoPreviewLayer for embedding in a view    let previewLayer = try await cameraManager.startCapture()        // Set PiP shape    cameraManager.pipShape = .circle      // .circle, .square, .portrait, .landscape}
// Stop capturecameraManager.stopCapture()

AnnotationKit — Drawing & Annotation

swift
import AnnotationKit
// Create an annotation canvas over an NSImagelet sourceImage = NSImage(named: "screenshot")!let canvas = AnnotationCanvas(image: sourceImage)
// Add annotations programmaticallylet arrow = ArrowAnnotation(    from: CGPoint(x: 50, y: 50),    to: CGPoint(x: 200, y: 200),    color: .red,    strokeWidth: 3)canvas.addAnnotation(arrow)
let rect = RectangleAnnotation(    frame: CGRect(x: 100, y: 100, width: 300, height: 150),    color: .blue,    strokeWidth: 2,    filled: false)canvas.addAnnotation(rect)
let text = TextAnnotation(    text: "Look here!",    position: CGPoint(x: 110, y: 110),    fontSize: 18,    color: .white)canvas.addAnnotation(text)
// Undo / redocanvas.undo()canvas.redo()
// Export annotated imagelet result: NSImage = canvas.renderToImage()

Screenshot Beautification (AnnotationKit)

swift
import AnnotationKit
let beautifier = ScreenshotBeautifier(image: rawImage)beautifier.backgroundColor = .systemBlue   // or gradient/custombeautifier.padding = 40beautifier.cornerRadius = 12beautifier.shadowRadius = 20beautifier.shadowOpacity = 0.4
let beautified: NSImage = beautifier.render()

OCRKit — Text Recognition

swift
import OCRKit
let ocrEngine = OCREngine()
// Instant OCR on an NSImage — returns plain textTask {    let text: String = try await ocrEngine.recognizeText(in: image)    print(text)    // Copy to clipboard    NSPasteboard.general.clearContents()    NSPasteboard.general.setString(text, forType: .string)}
// Visual OCR — returns bounding boxes + text for each blockTask {    let blocks: [OCRTextBlock] = try await ocrEngine.recognizeBlocks(in: image)    for block in blocks {        print("Text: \(block.text), Bounds: \(block.boundingBox)")    }}

ExportKit — Video & GIF Export

swift
import ExportKit
let exporter = MediaExporter()
// Export recorded video with quality presetTask {    let inputURL = URL(fileURLWithPath: "/tmp/raw_recording.mp4")    let outputURL = URL(fileURLWithPath: "/tmp/final.mp4")        try await exporter.exportVideo(        from: inputURL,        to: outputURL,        quality: .social   // .maximum, .social, .web    )}
// Export as GIFTask {    let inputURL = URL(fileURLWithPath: "/tmp/raw_recording.mp4")    let outputURL = URL(fileURLWithPath: "/tmp/output.gif")        try await exporter.exportGIF(        from: inputURL,        to: outputURL,        fps: 15,        scale: 0.75    )}

SharedKit — Permissions & Settings

swift
import SharedKit
// Check and request screen recording permissionlet permissionManager = PermissionManager()
Task {    let hasScreen = await permissionManager.requestScreenRecordingPermission()    let hasCamera = await permissionManager.requestCameraPermission()    let hasMic = await permissionManager.requestMicrophonePermission()}
// Access shared app settingslet settings = CapsoSettings.sharedsettings.screenshotShortcut = "⌘⇧4"settings.defaultSaveLocation = URL(fileURLWithPath: "/Users/me/Screenshots")settings.showCountdownBeforeRecording = truesettings.countdownSeconds = 3

SwiftUI Integration Pattern

Embed a capture button in a SwiftUI view:

swift
import SwiftUIimport CaptureKitimport AnnotationKit
struct ContentView: View {    @State private var capturedImage: NSImage?    @State private var showAnnotationEditor = false    private let captureManager = CaptureManager()
    var body: some View {        VStack {            if let img = capturedImage {                Image(nsImage: img)                    .resizable()                    .scaledToFit()                    .frame(maxWidth: 600)                                Button("Annotate") {                    showAnnotationEditor = true                }            }
            Button("Capture Fullscreen") {                Task {                    capturedImage = try? await captureManager.captureFullscreen()                }            }        }        .sheet(isPresented: $showAnnotationEditor) {            if let img = capturedImage {                // Hypothetical SwiftUI wrapper around AnnotationCanvas                AnnotationEditorView(image: img) { annotated in                    capturedImage = annotated                    showAnnotationEditor = false                }            }        }    }}

Running Package Tests

Each package is independently testable:

bash
swift test --package-path Packages/SharedKitswift test --package-path Packages/CaptureKitswift test --package-path Packages/AnnotationKitswift test --package-path Packages/OCRKitswift test --package-path Packages/RecordingKitswift test --package-path Packages/CameraKitswift test --package-path Packages/ExportKitswift test --package-path Packages/EffectsKit

Required Entitlements & Info.plist

Your app using Capso packages needs these permissions:

xml
<!-- Info.plist --><key>NSScreenCaptureUsageDescription</key><string>Required for screenshot and screen recording.</string>
<key>NSCameraUsageDescription</key><string>Required for webcam PiP during screen recording.</string>
<key>NSMicrophoneUsageDescription</key><string>Required to capture microphone audio during recording.</string>
xml
<!-- App.entitlements --><key>com.apple.security.device.camera</key><true/><key>com.apple.security.device.microphone</key><true/><!-- Screen capture is runtime-only via TCC, no entitlement needed -->

Common Patterns

Pin Screenshot to Screen (Always-on-Top)

swift
import AppKit
func pinScreenshot(_ image: NSImage) {    let window = NSPanel(        contentRect: NSRect(x: 100, y: 100, width: image.size.width, height: image.size.height),        styleMask: [.nonactivatingPanel, .titled, .closable, .resizable],        backing: .buffered,        defer: false    )    window.level = .floating           // Always on top    window.isFloatingPanel = true    window.hidesOnDeactivate = false    window.contentView = NSImageView(image: image)    window.makeKeyAndOrderFront(nil)}

Global Keyboard Shortcut (via SharedKit pattern)

swift
import Carbonimport AppKit
// Register a global hotkey for area capturefunc registerCaptureHotkey() {    NSEvent.addGlobalMonitorForEvents(matching: .keyDown) { event in        // Check for ⌘⇧4        if event.modifierFlags.contains([.command, .shift]),           event.keyCode == 21 { // keyCode 21 = '4'            NotificationCenter.default.post(name: .startAreaCapture, object: nil)        }    }}
extension Notification.Name {    static let startAreaCapture = Notification.Name("startAreaCapture")}

Troubleshooting

xcodegen generate fails

  • Ensure XcodeGen ≥ 2.40: brew upgrade xcodegen
  • Check project.yml is not modified with invalid YAML syntax
  • Run xcodegen generate --spec project.yml for explicit path

"Screen Recording permission denied" at runtime

  • Go to System Settings → Privacy & Security → Screen Recording and enable Capso
  • For your own app using CaptureKit, you must trigger the permission prompt first via PermissionManager.requestScreenRecordingPermission()

Build errors with Swift 6 concurrency

  • Capso targets Swift 6 strict concurrency. Ensure all closures that touch UI are @MainActor
  • Add @preconcurrency import for ScreenCaptureKit if you see warnings in Xcode 16

GIF export is slow

  • Lower the fps (e.g. fps: 10) and scale (e.g. scale: 0.5) in ExportKit
  • Use .web quality preset for faster encoding

Camera not showing in PiP

  • Verify camera permission is granted in System Settings
  • Call CameraManager.requestPermission() before startCapture()
  • Ensure your entitlement includes com.apple.security.device.camera

License Note

Capso uses Business Source License 1.1:

  • ✅ Personal use, internal company use, forking, modifying
  • ❌ Selling a competing screen-capture product based on this code
  • ✅ Automatically becomes Apache 2.0 in 2029 per release

When embedding packages in your own non-competing app, you are permitted under BSL 1.1.


Key Links

Source and attribution

Source:reason-machines/trending-skillsinskills/capso-screenshot-macosat commit2384a00

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal