From swiftasb-skills
Build or refactor an AppKit app feature on top of SwiftASB using explicit application, window, document, thread, and turn ownership with main-actor UI updates and clear runtime diagnostics.
How this skill is triggered — by the user, by Claude, or both
Slash command
/swiftasb-skills:build-appkit-appThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
When a task combines SwiftData with SwiftUI, keep SwiftData directly coupled to SwiftUI through Apple's data-driven path: `modelContainer`, environment `modelContext`, `@Query`, SwiftData model objects, and bindings. Do not add repositories, stores, service layers, DTO mirrors, view-model caches, wrapper objects, or other abstraction layers between SwiftData and SwiftUI. If this skill is not th...
When a task combines SwiftData with SwiftUI, keep SwiftData directly coupled to SwiftUI through Apple's data-driven path: modelContainer, environment modelContext, @Query, SwiftData model objects, and bindings. Do not add repositories, stores, service layers, DTO mirrors, view-model caches, wrapper objects, or other abstraction layers between SwiftData and SwiftUI. If this skill is not the right owner for SwiftData-backed SwiftUI work, hand off to apple-dev-skills:swiftui-app-architecture-workflow instead of inventing an intermediate data layer.
Help an AppKit app use SwiftASB to start local Codex work, show thread, agenda, and turn progress, answer approvals or elicitation requests, list stored threads, archive or unarchive stored threads, inspect app-server-owned worktree, selected Git status, project identity, thread source, filesystem/config/extension/MCP/workspace facts, observe SwiftASB-owned feature operations, expose app-wide inventory, and expose recent history from app-owned controllers or models.
The real job is to keep AppKit's app, window, document, and view-controller lifetimes in charge of UI behavior while SwiftASB owns the local Codex subprocess, app-wide library and inventory companions, thread agenda companions, stable worktree groups, repository/worktree filters, selected-worktree Git status, project identity and thread-source facts, app-server-owned worktree snapshots, app-server-routed filesystem/config/extension/MCP reads, workspace permission facts, feature policy, feature-operation events, plan-mode turn starts, goal helpers, review and shell-command entry points, typed thread, agenda, and turn handles, events, request responses, diagnostics, and local history.
Before implementing or proposing AppKit structure, read the relevant Apple documentation through Apple Dev Skills or official Apple docs.
Minimum rules to rely on:
NSApplication manages the app's main event loop, windows, menus, events, and app-wide resources.NSApplicationDelegate handles app lifecycle callbacks such as launch, termination, activation, reopen, and window-update behavior.NSWindowController manages a window and often participates in document-based ownership.NSViewController manages a view and has lifecycle methods suitable for window content.NSWindow and many delegate callbacks are main-actor UI surfaces; update AppKit views and controllers from the main actor.Authoritative docs:
swiftasb:choose-integration-shape selects an AppKit, document, window-controller, or menu-bar app shape.Verify current SwiftASB docs and public API before editing:
README.mdSources/SwiftASB/SwiftASB.docc/GettingStartedWithSwiftASB.mdSources/SwiftASB/SwiftASB.docc/HandlingTurnProgressAndApprovals.mdSources/SwiftASB/SwiftASB.docc/ReadingDiagnosticsAndHistory.mdSources/SwiftASB/SwiftASB.docc/ThreadHistoryAndObservables.mdSources/SwiftASB/SwiftASB.docc/AppWideCapabilities.mdSources/SwiftASB/SwiftASB.docc/CodexInventory.mdSources/SwiftASB/SwiftASB.docc/CodexMCP.mdSources/SwiftASB/SwiftASB.docc/CodexFS.mdSources/SwiftASB/SwiftASB.docc/CodexConfig.mdSources/SwiftASB/SwiftASB.docc/CodexExtensions.mdSources/SwiftASB/SwiftASB.docc/CodexWorkspace.mdSources/SwiftASB/SwiftASB.docc/FeaturePermissionPolicy.mdSources/SwiftASB/SwiftASB.docc/ThreadManagement.mdSources/SwiftASB/Public/CodexAppServer+Library.swiftSources/SwiftASB/Public/CodexAppServer+Inventory.swiftSources/SwiftASB/Public/CodexAppServer+LoadedThreads.swiftSources/SwiftASB/Public/CodexAppServer+CodexExtensions.swiftSources/SwiftASB/Public/CodexAppServer+MCP.swiftSources/SwiftASB/Public/CodexMCP.swiftSources/SwiftASB/Public/CodexFS.swiftSources/SwiftASB/Public/CodexConfig.swiftSources/SwiftASB/Public/CodexWorkspace.swiftSources/SwiftASB/Public/CodexAppServer+Bootstrap.swiftSources/SwiftASB/Public/CodexAppServer.swiftSources/SwiftASB/Public/CodexDiagnostics.swiftSources/SwiftASB/Public/CodexErrors.swiftSources/SwiftASB/Public/CodexReviewHandle.swiftSources/SwiftASB/Public/CodexThread.swiftSources/SwiftASB/Public/CodexThread+Dashboard.swiftSources/SwiftASB/Public/CodexThread+Agenda.swiftSources/SwiftASB/Public/CodexTurnHandle.swiftAs of SwiftASB v1.8.0, AppKit-facing integrations should prefer:
CodexAppServer.start(_:) with CodexAppServer.StartupRequest for normal one-call subprocess startup, compatibility validation, initialization, and typed CodexAppServerStartupError failuresCodexAppServer.start(), cliExecutableDiagnostics(), and initialize(_:) only when the app intentionally owns custom diagnostics, compatibility policy, or test setup before initializationCodexAppServer for subprocess ownership, diagnostics, stored-thread operations, model capability reads, feature-operation-event streams, and hook diagnosticsCodexAppServer.makeLibrary(configuration:) for app-wide stored-thread lists, cwd or repository grouping, stable worktree groups, repository/worktree filters, selected worktree or repository context, selected-worktree Git status, library-local selection, CodexWorkspace.ProjectInfo project identity, CodexAppServer.ThreadSource source badges, and model/MCP/hook snapshots that refresh when app-server app/skill/MCP state changesCodexAppServer.makeInventory(configuration:) for routine app-wide model capabilities, global MCP summaries, hook diagnostics, apps, skills, plugins, and collaboration modesCodexAppServer.fs, CodexAppServer.config, and CodexAppServer.extensions for app-server-owned file metadata, directory/file reads, file discovery with match metadata, effective config, advanced extension pagination, plugin detail reads, and already-configured marketplace upgradesCodexAppServer.mcp for MCP server installs, full status snapshots, and app-wide or thread-scoped MCP resource contentsSwiftASBFeaturePolicy for feature-category defaults and host app authority, with gitObservability, extensionInventory, and extensionMaintenance enabled by default and mutation-oriented categories disabled until the app opts inCodexAppServer.featureOperationEvents() for human-readable SwiftASB-owned mutation records, such as marketplace maintenance attemptsCodexWorkspace for session cwd, app-server-owned worktree snapshots, project identity, Git repository facts, selected Git status snapshots, active permission profile, and runtime filesystem/network permission factsCodexThread for conversation-scoped text turns, plan-mode turns, thread events, thread actions, archive/unarchive, thread goals, request responses, and local historyCodexThread.startReview(against:placement:) for code-review UI, and CodexThread.sendShellCommand(_:) only for explicit user-level shell actions when shellCommandExecution is enabledCodexTurnHandle for one active turn, including events, steering, interruption, request responses, minimap state, and completion handoffCodexTurnItem.Kind.sleep when custom transcript, history, or activity UI switches over public turn item kindsCodexThread.makeDashboard(), CodexThread.makeAgenda(), and CodexTurnHandle.minimap as UI-friendly current-state mirrorsCodexAppServer.ThreadListQD, CodexFS.FileDiscoveryQD, CodexThread.HistoryWindowQD, CodexThread.RecentFilesQD, and CodexThread.RecentCommandsQD for repeatable sidebar, file-picker, inspector, and history intentASBPresentation and ASBAppKit products when the app wants SwiftASB presentation snapshots or the packaged AppKit thread sidebar viewhttps://github.com/gaelic-ghost/SwiftASB1.8.0 when using current one-call startup, Codex CLI 0.142.x compatibility, app-wide library or inventory, stable worktree groups, repository/worktree filters, selected-worktree Git status, feature policy, feature-operation events, extension marketplace maintenance, project identity, thread source, filesystem match metadata, MCP installs/status/resource reads, config warnings, extension inventory, workspace, query-descriptor, thread archive/unarchive, code-review starts, shell-command execution, plan/goal UI, sleep turn-item classification, presentation products, or recent-activity guidance; otherwise verify the support window in SwiftASB's READMESwiftASBASBPresentation and ASBAppKit when the app uses SwiftASB's reusable presentation snapshots or packaged AppKit viewsCodexAppServer when one runtime serves many windowsCodexAppServer.Library when the UI needs stored-thread lists before a thread is selectedCodexThread when work belongs to one workspace or documentCodexTurnHandle while one turn is runningappServer.start(_:) for normal clients and the lower-level start() plus initialize(_:) sequence only for custom diagnostics or tests.appServer.fs, appServer.config, appServer.makeInventory(configuration:), appServer.extensions, appServer.mcp, CodexWorkspace, and SwiftASBFeaturePolicy when inspectors, preferences, file pickers, MCP panes, or diagnostics need Codex-owned filesystem, config, plugin/skill/app, collaboration-mode, marketplace-maintenance, resource, worktree, selected Git status, project identity, thread source, permission facts, or feature-category choices.CodexTurnHandle or CodexThread.Prefer one AppKit-facing object that makes lifetime visible:
import AppKit
import SwiftASB
@MainActor
final class CodexWorkspaceWindowController: NSWindowController {
private let appServer: CodexAppServer
private var inventory: CodexAppServer.Inventory?
private var library: CodexAppServer.Library?
private var thread: CodexThread?
private var currentTurn: CodexTurnHandle?
@IBOutlet private var statusField: NSTextField!
init(appServer: CodexAppServer) {
self.appServer = appServer
super.init(window: nil)
}
required init?(coder: NSCoder) {
nil
}
func connect(workspacePath: String) {
Task { @MainActor in
do {
let session = try await appServer.start(
.init(
clientInfo: .init(
name: "ExampleApp",
title: "Example App",
version: "1.0.0"
)
)
)
_ = session.cliExecutableDiagnostics
inventory = try await appServer.makeInventory(
configuration: .init(
hookListCurrentDirectoryPaths: [workspacePath],
extensionCurrentDirectoryPaths: [workspacePath]
)
)
thread = try await appServer.startThread(
.init(currentDirectoryPath: workspacePath)
)
library = try await appServer.makeLibrary(
configuration: .init(
sortedBy: .turnFinishedNewestFirst,
groupedBy: .repository,
query: .unarchived(limit: 30),
mcpServerStatusRequest: .init(detail: .toolsAndAuthOnly)
)
)
statusField.stringValue = "Codex is ready."
} catch {
statusField.stringValue = "SwiftASB could not start Codex: \(error)"
}
}
}
@IBAction func runSelectedTask(_ sender: Any?) {
guard let thread else {
statusField.stringValue = "SwiftASB cannot start a turn before a thread exists."
return
}
Task { @MainActor in
do {
let turn = try await thread.startTextTurn("Summarize the current workspace.")
currentTurn = turn
for try await event in turn.events {
if case .completed = event {
_ = try await turn.complete()
currentTurn = nil
statusField.stringValue = "Codex turn finished."
return
}
}
} catch {
currentTurn = nil
statusField.stringValue = "SwiftASB turn failed: \(error)"
}
}
}
@IBAction func interruptTurn(_ sender: Any?) {
Task { @MainActor in
do {
try await currentTurn?.interrupt()
statusField.stringValue = "Interrupt sent to Codex."
} catch {
statusField.stringValue = "SwiftASB could not interrupt the turn: \(error)"
}
}
}
}
Use this as a shape, not as a file to paste blindly. Match the app's actual nib/storyboard/programmatic-window setup, document model, and error UI.
CodexAppServerStartupError startup and compatibility failures before enabling menu or toolbar actions.CodexAppServer.Inventory for routine app-wide model capabilities, global MCP summaries, hook diagnostics, apps, skills, plugins, and collaboration modes.CodexAppServer.Library for source lists, launchers, project browsers, stored-thread selection, selected-worktree Git status, project identity display, thread-source badges, app-wide model capabilities, MCP status, and hook diagnostics.CodexAppServer.fs and CodexFS.FileDiscoveryQD for sandbox-safe file pickers, metadata inspectors, directory browsers, file-byte previews, watches, highlighted matches, and ranking explanations.CodexAppServer.mcp when the app needs to install MCP servers, show full MCP details, or show text/blob resource contents advertised by a configured MCP server.CodexAppServer.config, CodexAppServer.extensions, and CodexWorkspace for preferences or diagnostics panes that show effective config, requirements, advanced extension detail, marketplace maintenance, worktree snapshots, selected Git status, project identity, active profile, and filesystem/network permissions.SwiftASBFeaturePolicy to present feature-category toggles only when the app actually lets users change SwiftASB-owned authority. Read-only Git observability and extension inventory are enabled by default; stronger mutation categories should stay deliberate app choices.CodexAppServer.featureOperationEvents() when AppKit needs to show marketplace-upgrade results or future SwiftASB-owned mutation records in a status pane, log view, or inspector.CodexThread.archive() and CodexThread.unarchive() for archive UI actions when the app already owns the selected thread handle.CodexThread.readGoal(), setGoal(_:), clearGoal(), setName(_:), updateMetadata(gitInfo:), compactContext(), and rollbackLastTurns(_:) from explicit menu, toolbar, inspector, or document actions that already own the selected thread.CodexThread.startReview(against:placement:) only from review controls that clearly say what will be reviewed and whether the result appears inline or detached.CodexThread.sendShellCommand(_:) only behind explicit user opt-in for high-impact shell execution; preserve shell syntax and explain that it does not inherit the thread sandbox policy.dashboard and minimap state for activity views instead of replaying every raw event into controller-owned arrays.CodexTurnItem.Kind.sleep explicitly in custom turn item switches so AppKit transcript and activity UI remains current with Codex CLI 0.142.x events.ASBThreadSidebarView from ASBAppKit when the app wants the packaged dense source-list renderer over ASBPresentation snapshots.Use the repository's documented Xcode build and test path. For Xcode projects, do not assume SwiftPM validation is enough because scheme, target membership, entitlements, sandboxing, signing, and resources may be Xcode-owned.
Live Codex integration tests should be opt-in, isolated in temporary workspaces, and bounded by hard timeouts.
swiftasb:explain-swiftasb when the user needs adoption tradeoffs before implementation.swiftasb:choose-integration-shape when ownership or app shape is unclear.swiftasb:diagnose-integration when startup, turn, approval, MCP, diagnostics, or history behavior fails.apple-dev-skills:explore-apple-swift-docs for AppKit, SwiftUI, SwiftPM, or Observation documentation.CodexAppServer.CodexWire... models into AppKit controller or view state.CodexAppServerStartupError cases when mapping errors into AppKit status text.npx claudepluginhub gaelic-ghost/socket --plugin swiftasb-skillsCreates, edits, and verifies skills using a test-driven development approach with pressure scenarios and subagents.