A wrapper for implementing macOS-exclusive SwiftUI features and native behaviors.

Install

mkdir -p .claude/skills/macos && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/13420" && unzip -o skill.zip -d .claude/skills/macos && rm skill.zip

Installs to .claude/skills/macos

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Implementa funcionalidades específicas de macOS em apps SwiftUI — Scenes (Settings, MenuBarExtra, WindowGroup, Window, UtilityWindow, DocumentGroup), estilos de janela e toolbar, NavigationSplitView, Inspector, Commands, HSplitView, Table, operações de arquivo, drag-drop entre apps, e interop AppKit. Use quando o usuário precisar de qualquer API exclusiva ou com comportamento diferenciado no macOS.
401 charsno explicit “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Intermediate

Key capabilities

  • Implement macOS-specific SwiftUI scenes (Settings, MenuBarExtra, WindowGroup, Window, UtilityWindow, DocumentGroup)
  • Configure window styles, sizing, and Inspectors
  • Integrate NavigationSplitView and Commands/keyboard shortcuts
  • Utilize HSplitView/VSplitView and Table views
  • Perform file operations and drag-drop between apps
  • Enable AppKit interop using NSViewRepresentable/NSViewControllerRepresentable

How it works

The skill provides expertise and code examples for implementing macOS-specific SwiftUI APIs, ensuring they are guarded with `#if os(macOS)` in multi-platform projects.

Inputs & outputs

You give it
Desired macOS aspect to implement (scenes, window, or views)
You get back
SwiftUI code examples and guidance for implementing macOS-specific features

When to use macos

  • Implementing macOS toolbar styles
  • Creating native macOS windows
  • Integrating drag-and-drop on Mac
  • Adding app menu items

About this skill

Skill: macOS

Você é um especialista em APIs SwiftUI específicas do macOS.
Regra obrigatória: todas as APIs exclusivas de macOS DEVEM estar dentro de #if os(macOS) em projetos multiplataforma.


Identificação do Modo

Se $ARGUMENTS não especificar o modo, pergunte:

"Qual aspecto macOS você quer implementar?

  • scenes — configurar cenas do app (Settings, MenuBarExtra, Window…)
  • window — estilos de toolbar/janela, Inspector, NavigationSplitView, Commands
  • views — HSplitView, Table, arquivos, drag-drop, NSViewRepresentable"

Modo: scenes

Antes de criar

  1. Leia o @main App atual para entender as cenas existentes.
  2. Identifique qual cena adicionar ou ajustar.
  3. Wrap sempre em #if os(macOS) quando o projeto é multiplataforma.

Referência de Cenas

CenaDisponibilidademacOS-only?Uso
WindowGroupmacOS 11.0+NãoMúltiplas janelas, tabs, Window menu automático
WindowmacOS 13.0+NãoJanela singleton; app sai quando fecha (se for única)
UtilityWindowmacOS 15.0+SimPaleta flutuante; recebe FocusedValues da janela ativa
SettingsmacOS 11.0+SimJanela de preferências (Cmd+,)
MenuBarExtramacOS 13.0+SimÍcone/menu persistente na barra de menus
DocumentGroupmacOS 11.0+NãoMenus File automáticos; múltiplos documentos

Settings

#if os(macOS)
Settings {
    TabView {
        Tab("General", systemImage: "gear") { GeneralSettingsView() }
        Tab("Advanced", systemImage: "star") { AdvancedSettingsView() }
    }
    .scenePadding()
    .frame(maxWidth: 350, minHeight: 100)
}
#endif

Abrir programaticamente (macOS 14.0+):

struct OpenSettingsButton: View {
    @Environment(\.openSettings) private var openSettings

    var body: some View {
        Button("Preferências") { openSettings() }
    }
}

SettingsLink (macOS 14.0+):

SettingsLink {
    Label("Preferências", systemImage: "gear")
}

MenuBarExtra

Estilo menu (dropdown):

#if os(macOS)
MenuBarExtra("MyApp", systemImage: "hammer") {
    Button("Ação") { /* ... */ }
    Divider()
    Button("Sair") { NSApplication.shared.terminate(nil) }
}
#endif

Estilo window (painel popover):

#if os(macOS)
MenuBarExtra("Status", systemImage: "chart.bar") {
    DashboardView()
        .frame(width: 240)
}
.menuBarExtraStyle(.window)
#endif

App somente na barra de menus:

  • Use MenuBarExtra como única cena
  • Adicione LSUIElement = YES no Info.plist para ocultar o ícone no Dock
  • O app se encerra automaticamente se o usuário remover o ícone da barra

Visibilidade controlável:

@AppStorage("showMenuBarExtra") private var showMenuBarExtra = true

MenuBarExtra("Status", systemImage: "bolt", isInserted: $showMenuBarExtra) { ... }

WindowGroup (macOS)

@main
struct MyApp: App {
    var body: some Scene {
        // Janela principal (suporta múltiplas instâncias + tabs)
        WindowGroup {
            ContentView()
        }

        // Janela de dados tipados — aberta programaticamente
        WindowGroup("Detalhe", for: Item.ID.self) { $itemID in
            ItemDetailView(itemID: itemID)
        }
    }
}

// Abrir programaticamente
struct OpenButton: View {
    var item: Item
    @Environment(\.openWindow) private var openWindow

    var body: some View {
        Button("Abrir Detalhe") {
            openWindow(value: item.id)
        }
    }
}

Window (singleton)

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup { ContentView() }

        // Janela singleton suplementar
        Window("Connection Doctor", id: "connection-doctor") {
            ConnectionDoctorView()
        }
    }
}

// Abrir — traz ao frente se já aberta
struct OpenDoctorButton: View {
    @Environment(\.openWindow) private var openWindow

    var body: some View {
        Button("Connection Doctor") {
            openWindow(id: "connection-doctor")
        }
    }
}

Prefira WindowGroup para a cena principal. Use Window apenas para janelas suplementares singleton.


UtilityWindow (macOS 15.0+)

Paleta flutuante que recebe FocusedValues da janela principal ativa.

#if os(macOS)
UtilityWindow("Informações", id: "photo-info") {
    PhotoInfoViewer()
}
#endif

// Dentro da UtilityWindow — reflete seleção da janela ativa
struct PhotoInfoViewer: View {
    @FocusedValue(PhotoSelection.self) private var selectedPhotos

    var body: some View {
        if let photos = selectedPhotos {
            Text("\(photos.count) fotos selecionadas")
        } else {
            Text("Sem seleção").foregroundStyle(.secondary)
        }
    }
}

DocumentGroup

DocumentGroup(newDocument: MyDocument()) { config in
    ContentView(document: config.$document)
}
struct MyDocument: FileDocument {
    static var readableContentTypes: [UTType] { [.plainText] }
    var text: String = ""

    init() {}
    init(configuration: ReadConfiguration) throws {
        text = String(data: configuration.file.regularFileContents ?? Data(),
                      encoding: .utf8) ?? ""
    }
    func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
        FileWrapper(regularFileWithContents: Data(text.utf8))
    }
}

Modo: window

Toolbar Styles (macOS-only)

Aplique no nível da Scene:

WindowGroup { ContentView() }
    .windowToolbarStyle(.unified)           // Título + toolbar em uma linha (recomendado)
    .windowToolbarStyle(.unifiedCompact)    // Idem, menor altura vertical
    .windowToolbarStyle(.expanded)          // Título acima da toolbar
    .windowToolbarStyle(.unified(showsTitle: false))  // Sem título

Conteúdo da toolbar na View:

.toolbar {
    ToolbarItem(placement: .automatic) {
        Button(action: addItem) {
            Label("Adicionar", systemImage: "plus")
        }
    }
}
.searchable(text: $searchText, placement: .sidebar)

Window Sizing & Positioning

WindowGroup {
    ContentView()
        .frame(minWidth: 600, minHeight: 400)   // Mínimos no conteúdo
}
.defaultSize(width: 900, height: 600)           // Tamanho inicial
.defaultPosition(.center)                       // Posição inicial
.windowResizability(.contentMinSize)            // Usa minWidth/minHeight do frame

windowResizability opções:

ValorComportamento
.automaticSistema decide
.contentSizeTamanho fixo, sem redimensione
.contentMinSizeRedimensionável com mínimo pelo frame

Posicionamento preciso (macOS 15.0+):

.windowIdealPlacement { context in
    let screen = context.defaultDisplay.visibleArea
    return WindowPlacement(x: screen.midX, y: screen.midY,
                           width: screen.width / 2,
                           height: screen.height)
}

Window Style

// Padrão — barra de título visível
WindowGroup { ContentView() }
    .windowStyle(.titleBar)

// Sem barra de título — janelas imersivas
WindowGroup { ContentView() }
    .windowStyle(.hiddenTitleBar)

NavigationSplitView no macOS

No macOS, as colunas são exibidas lado a lado (nunca sobrepostas). A sidebar recebe fundo translúcido automaticamente.

NavigationSplitView {
    List(items, selection: $selectedID) { item in
        Text(item.name)
    }
    .navigationSplitViewColumnWidth(min: 180, ideal: 220, max: 300)
} detail: {
    DetailView(id: selectedID)
}
.navigationSplitViewStyle(.balanced)

Três colunas:

NavigationSplitView {
    SidebarView()
} content: {
    ContentListView(selection: $selectedItem)
} detail: {
    DetailView(item: selectedItem)
}

Inspector (macOS 14.0+)

Painel lateral direito redimensionável pelo usuário.

struct ContentView: View {
    @State private var showInspector = false

    var body: some View {
        MainContent()
            .inspector(isPresented: $showInspector) {
                InspectorView()
                    .inspectorColumnWidth(min: 200, ideal: 250, max: 400)
            }
            .toolbar {
                ToolbarItem {
                    Button {
                        showInspector.toggle()
                    } label: {
                        Label("Inspetor", systemImage: "info.circle")
                    }
                }
            }
    }
}

Commands & Atalhos de Teclado

// Na Scene
.commands {
    CommandMenu("Ferramentas") {
        Button("Executar Análise") { /* ... */ }
            .keyboardShortcut("r", modifiers: [.command, .shift])
    }
    CommandGroup(after: .newItem) {
        Button("Novo Pelo Template…") { /* ... */ }
    }
}

Atalhos em botões:

Button("Salvar") { save() }
    .keyboardShortcut("s", modifiers: .command)

Button("Excluir") { delete() }
    .keyboardShortcut(.delete, modifiers: .command)

Posicionamentos de CommandGroup: .newItem, .saveItem, .help, .toolbar, .sidebar
Use .replacing(_:) para substituir um grupo do sistema.


Modo: views

HSplitView / VSplitView (macOS-only)

Use para layouts IDE-style onde todos os painéis são pares iguais. Para navegação sidebar → conteúdo, prefira NavigationSplitView.

HSplitView {
    FileTreeView()
        .frame(minWidth: 200)
    CodeEditorView()
        .frame(minWidth: 400)
    PreviewPane()
        .frame(minWidth: 200)
}

VSplitView é idêntico mas divide verticalmente (use minHeight em vez de minWidth).


Table (macOS 12.0+)

struct PeopleTable: View {
    @State private var people: [Person] = Person.samples
    @State private var selection: Set<Person.ID> = []
    @State private var sortOrder = [KeyPathComparator(\Person.name)]

    var body: 

---

*Content truncated.*

When not to use it

  • When implementing functionalities that are not exclusive to macOS
  • When the project is not a multi-platform SwiftUI application
  • When the user does not need to use macOS-specific APIs

Limitations

  • All macOS-exclusive APIs MUST be within `#if os(macOS)` in multi-platform projects.
  • UtilityWindow is only available on macOS 15.0+.
  • NSViewRepresentable should not directly define frame/bounds on the managed NSView.

How it compares

This skill provides specialized guidance and code templates for macOS-specific SwiftUI features, including scene configuration and AppKit interop, unlike general SwiftUI development.

Compared to similar skills

macos side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
macos (this skill)04moNo flagsIntermediate
liquid-glass-developer233moNo flagsIntermediate
swiftui-liquid-glass154moNo flagsIntermediate
swiftui-expert-skill134moNo flagsIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

liquid-glass-developer

anyproto

Context-aware routing to iOS 26 Liquid Glass implementation patterns. Use when working with glass effects, GlassEffectContainer, morphing transitions, or iOS 26 visual effects.

2367

swiftui-liquid-glass

Dimillian

Implement, review, or improve SwiftUI features using the iOS 26+ Liquid Glass API. Use when asked to adopt Liquid Glass in new SwiftUI UI, refactor an existing feature to Liquid Glass, or review Liquid Glass usage for correctness, performance, and design alignment.

1567

swiftui-expert-skill

sickn33

Write, review, or improve SwiftUI code following best practices for state management, view composition, performance, modern APIs, Swift concurrency, and iOS 26+ Liquid Glass adoption. Use when building new SwiftUI features, refactoring existing views, reviewing code quality, or adopting modern SwiftUI patterns.

1333

design-system-developer

anyproto

Context-aware routing to the Anytype iOS design system including icons, typography, colors, and spacing. Use when working with Figma-to-code translation, design assets, or UI components.

111

ios-dev-guidelines

anyproto

Context-aware routing to Swift/iOS development patterns, architecture, and best practices. Use when working with .swift files, ViewModels, Coordinators, refactoring, or discussing Swift/SwiftUI patterns.

37

swiftui-ui-patterns

Dimillian

Best practices and example-driven guidance for building SwiftUI views and components. Use when creating or refactoring SwiftUI UI, designing tab architecture with TabView, composing screens, or needing component-specific patterns and examples.

13

Search skills

Search the agent skills registry