NOASSERTIONupdated 1mo ago
Let be the absolute plugin directory two levels above this SKILL.md. Resolve that path before running commands or opening shared references. When these instructions say swiftui-ctx, invoke /scripts/swiftui-ctx; do not assume the command is on PATH.
What can you do with Audit Swiftui Navigation Toolbars?
name: audit-swiftui-navigation-toolbars description: Audit macOS SwiftUI navigation toolbars for correctness, current APIs, and production conventions. Use for that domain or as part of a full audit.
Bundled resource root
Let <swiftui-plugin-root> be the absolute plugin directory two levels above this SKILL.md. Resolve that path before running commands or opening shared references. When these instructions say swiftui-ctx, invoke <swiftui-plugin-root>/scripts/swiftui-ctx; do not assume the command is on PATH.
Audit SwiftUI Navigation & Toolbars
AUDIT-ONLY Β· macOS-only Β· SwiftUI-only. Run this on a finished or in-progress macOS SwiftUI
project to detect β and where certain, fix β every way the in-window navigation shell and toolbar go
wrong on a macOS 26 (Tahoe) target: a deprecated NavigationView, an iPhone push-stack as the Mac
shell, two- vs three-column confusion, frame-hack column hiding, deprecated/platform-absent toolbar
placements, iOS-bar title concepts, and the detail-column-width no-op. Findings are written to disk in
the toolkit's unified schema; certain mechanical defects are fixed under the fix-safety protocol. This
is never a from-scratch navigation generator.
The Mac wants a persistent multi-column sidebar (NavigationSplitView), not an iPhone push stack.
The containers exist on both platforms but the idioms diverge sharply β be suspicious wherever AI wrote
navigation code from an iOS mental model.
Boundary / seam note (stay in lane)
- AppKit
NSSplitViewController/NSToolbarinternals are out of scope. If audited code bridges to an AppKit split or toolbar, note it in one line and route the whether-to-bridge decision toaudit-swiftui-appkit-overuseand the how toaudit-swiftui-appkit-interopβ do not audit AppKit internals here. AnHSplitView/NSSplitViewControllerinspector is the legitimate workaround for nav-12 (named, not flagged). NavigationViewdeprecation-flagging is co-owned:audit-swiftui-api-currencyowns the deprecation flag; this skill owns the structural migration toNavigationSplitView/NavigationStack. Emit across_ref: api-currencyon aNavigationViewfinding.- Window scene sizing (
.defaultSize/.windowResizability) andnavigationTitle-in-a-Windowtitlebar belong toaudit-swiftui-scenes-windows; content-frame sizing (.frame(min/ideal/max)) belongs toaudit-swiftui-layout-and-tables. SidebarListstyling density crosses intoaudit-swiftui-controls-forms;@FocusedValuedetail-routing crosses intoaudit-swiftui-menus-commands; theToolbarSpacerglass era crosses intoaudit-swiftui-liquid-glass. Cross_ref, don't double-own.
The three non-negotiable macOS rules
- Mac shell =
NavigationSplitView, neverNavigationView/NavigationStack.NavigationViewis deprecated;NavigationStackis a push/pop stack for drill-down inside a column, not the app shell. - Drive columns with the binding, never the frame. Column show/hide is the
columnVisibility:initializer parameter bound to aNavigationSplitViewVisibilityβ not a boolean+.frame(maxWidth: 0)hack. - macOS has no navigation bar β only semantic toolbar placements + the window titlebar.
.navigationBarLeading/.navigationBarTrailingare deprecated iOS-only;.topBarLeading/.topBarTrailingare unavailable on macOS (compile error);navigationBarTitle/navigationBarTitleDisplayModeare no-ops. Use.navigation/.principal/.primaryActionandnavigationTitle/navigationSubtitle.
The shell test: is this container the top level of the app and does it want a persistent sidebar?
β NavigationSplitView. Is it drill-down inside one column? β NavigationStack. Full reasoning +
the column-map artifact: references/navigation-shell-and-columns.md.
Grounded β
(the consensus Mac shell). swiftui-ctx lookup NavigationSplitView β the 2-column
{ } detail: { } shape is the consensus at 71% of 818 uses across 487 repos (introduced_macos: 13.0,
deprecated: false); the (columnVisibility) variant is 27% (nav-04). This is the ## Correct to put in
every shell finding β not a hand-written snippet. Real macOS-26 call site (f/textream, β
3300):
NavigationSplitView {
pageSidebar
} detail: {
mainContent
}
// https://github.com/f/textream/blob/6c34baaef9fea5de30bce619b4ed34cd675d5617/Textream/Textream/ContentView.swift#L412
// doc: https://sosumi.ai/documentation/swiftui/navigationsplitview
Defect index (nav-01 β¦ nav-12)
id Β· tell Β· severity Β· fix Β· open reference. Severities: hard-fail (build break / never-correct on
macOS), warning (compiles but non-native / silently no-ops), advisory (judgment / craft). auto
= mechanical single-answer fix; flag = show the β
, dev applies.
| id | One-line tell | Sev | Fix | Reference |
|---|---|---|---|---|
| nav-01 | NavigationView { β deprecated container (through macOS 26.5) |
warning | flag | navigation-shell-and-columns.md |
| nav-02 | top-level NavigationStack { wrapping a sidebar List(selection:) β wrong Mac shell |
warning | flag | navigation-shell-and-columns.md |
| nav-03 | three-column init(sidebar:content:detail:) whose content: is EmptyView()/placeholder β should be 2-column |
warning | flag | navigation-shell-and-columns.md |
| nav-04 | boolean + .frame(maxWidth: shown ? .infinity : 0) (or width: 0) to hide a column |
warning | flag | navigation-shell-and-columns.md |
| nav-05 | .topBarLeading / .topBarTrailing placement on a Mac target β unavailable on macOS (compile error) |
hard-fail | auto | toolbar-placements-and-titles.md |
| nav-06 | .navigationBarLeading / .navigationBarTrailing placement β deprecated iOS-only |
hard-fail | auto | toolbar-placements-and-titles.md |
| nav-07 | .navigationBarTitle( / .navigationBarTitleDisplayMode( β iOS-bar concept, no-op on macOS |
hard-fail | auto | toolbar-placements-and-titles.md |
| nav-08 | .navigationSplitViewColumnWidth( on the detail closure β silent no-op on detail |
warning | flag | inspector-and-detail-width.md |
| nav-09 | sidebar List missing .listStyle(.sidebar) β wrong material / selection highlight |
advisory | flag | navigation-shell-and-columns.md |
| nav-10 | .searchable( on a column instead of the NavigationSplitView β wrong toolbar slot |
advisory | flag | toolbar-placements-and-titles.md |
| nav-11 | ToolbarSpacer( / SpacerSizing used ungated under a < macOS 26 floor |
warning | flag | toolbar-placements-and-titles.md |
| nav-12 | empty detail is a blank view, not ContentUnavailableView |
advisory | flag | inspector-and-detail-width.md |
One claim is UNVERIFIED β carry as the reference's verify against Xcode 26 SDK, never as fact: the
navigationSplitViewColumnWidth no-op on the detail column (nav-08, practitioner-confirmed) and the
inspector standard width (225 pt Apple examples / 270 pt community-observed). The
navigationBar* placement exact deprecation version is verify-SDK per floors-master.md.
The real API, at a glance
Real (exist on a Mac target): NavigationSplitView (2-/3-col inits + columnVisibility: /
preferredCompactColumn: variants, macOS 13.0+), NavigationSplitViewVisibility
(.all/.doubleColumn/.detailOnly/.automatic), NavigationStack (drill-down inside a column),
navigationTitle(_:) (β window titlebar, macOS 11.0+), navigationSubtitle(_:) (macOS 11.0+ β but iOS
floor is 26.0, much higher), semantic ToolbarItemPlacement (.navigation β leading, .principal/
.status β centered, .primaryAction β leading edge on macOS, not trailing), ToolbarItem /
ToolbarItemGroup, ToolbarSpacer + SpacerSizing (.fixed/.flexible, macOS 26.0+ β gate it),
.listStyle(.sidebar), .inspector(isPresented:) + .inspectorColumnWidth (macOS 14.0+),
HSplitView (the resizable-inspector escape hatch).
Platform-wrong (macOS ABSENT β compile error, never gate, replace):
ToolbarItemPlacement.topBarLeading / .topBarTrailing. Deprecated: NavigationView (β
NavigationSplitView/NavigationStack), .navigationBarLeading / .navigationBarTrailing (β
.navigation / .primaryAction). No-op on macOS: navigationBarTitle,
navigationBarTitleDisplayMode (+ .inline/.large).
Signatures, floors, and the full βββ
rewrites: the routed references/*.md. Floor values are the
reconciled truth in <swiftui-plugin-root>/references/_shared/floors-master.md and the canonical
platform-wrong-name list in <swiftui-plugin-root>/references/_shared/hallucination-blacklist.md Β§5 β
read, never restate them.
The 8-step audit workflow (execute verbatim)
- ORIENT.
tree/findthe SwiftUI sources. Read the deployment target (project.pbxprojMACOSX_DEPLOYMENT_TARGET, orPackage.swiftplatforms:). It is load-bearing: nav-11 (ToolbarSpacer) fires only when the floor is below macOS 26; nav-01 deprecation prose depends on the floor relative to 26.5. Record it. - LOCATE. Run the shared hybrid lint runner:
bash <swiftui-plugin-root>/scripts/swiftui-lint.sh --skill audit-swiftui-navigation-toolbars --dir <sources> --json /tmp/nav.json --sarif /tmp/nav.sarif. It runs this skill's tier-1 grep tells (lint/grep-tells.tsv) + the tier-2 structural ast-grep rule (lint/ast-grep/*.ymlβ nav-03's empty-middle-column shape, which grep can't express; nav-04's frame-hack and nav-08's columnWidth-on-detail stay grep tells, READ-confirmed, per the rule-file note), plus a per-file parse probe, and emits unified JSON + SARIF. Read itsparse_warningsβ a flagged file did not fully parse, so a structural miss can't masquerade as clean; READ those by hand. The runner only LOCATES β never treat a hit as a finding. Engine + rule-file format + degradation:<swiftui-plugin-root>/references/_shared/lint-architecture.md. - READ. Open every located file in full β never pattern-match-and-patch blind. Whether a
NavigationStackis the shell or a column drill-down, whether a three-columncontent:is truly empty, and whether acolumnWidthsits on the detail closure are all cross-line facts invisible to grep. Build a per-file inventory: each navigation container + its role (shell/column) + its columns + each toolbar placement + each title modifier. - DETECT. Apply the index. Assign each candidate a confidence; report a finding only at 100%
certainty (e.g. a
.topBarLeadingplacement on a Mac target, anavigationBarTitlecall, aNavigationView). - VERIFY. For anything β€ ~70% confidence (a placement you're unsure resolves on macOS, a floor you
can't place, the detail-column no-op behavior), run both evidence sources. (a) Practice β
bash <swiftui-plugin-root>/scripts/swiftui-ctx lookup <api> --json(andswiftui-ctx deprecated <api>for a currency/deprecation rule): read itsconsensus(the canonical shape),deprecated+replacement/migrate_to,recommendedpermalink,introduced_macos, andco_occurs_with; alookupexit 3 (not-found, with a did-you-meansuggestion) corroborates a platform-wrong / invented-placement finding β no shipping Mac app uses the symbol. (b) Spec β confirm via Sosumi:curl -sSL https://sosumi.ai/<apple-path>usingreferences/source-directory.mdfor the path and<swiftui-plugin-root>/references/_shared/sosumi-reference.mdfor the protocol (neverWebFetchdeveloper.apple.com). Cross-checkintroduced_macosagainstfloors-master.mdand the Sosumidoc:floor. The CLI contract is<swiftui-plugin-root>/references/_shared/swiftui-ctx-reference.md. Promote with the citation or discard. Carry nav-08's no-op + inspector width assource: verify against Xcode 26 SDKβ never as fact. - REPORT. Write each confirmed finding (output contract below). One finding per file, zero-padded,
ordered. Emit
cross_refon shared-seam findings (nav-01 βapi-currency). Write the run's_index.md. - FIX. Apply corrections under the fix-safety protocol
(
<swiftui-plugin-root>/references/_shared/fix-safety-protocol.md): clean-tree gate, findings-first, onlyfix_mode: auto(nav-05/06/07 β the mechanical placement/title renames), one conventional commit per finding citing itsrule_id, never weaken a check. The β "Correct" is not a hand-written snippet β it is the swiftui-ctx consensus shape put in## Correct, backed by a real macOS-26 example fetched withbash <swiftui-plugin-root>/scripts/swiftui-ctx file <recommended.id> --smartwhose GitHub permalink (plus the Sosumidoc:) goes in## Sourceas the canonical example. Leaveflag-onlyfindingsopenwith that β in## Correct. (E.g. theNavigationSplitViewconsensus shape is the trailing{ β¦ }two-column form β see the routed reference for the live permalink.) - DOUBLE-CHECK. Re-grep each fixed file to confirm the tell no longer matches; record the evidence
in
## Fix applied?. Re-confirm every citation still resolves and still says itsmacOSfloor. If a fix introduced a new tell (e.g. a swapped placement now needs aToolbarSpacergate), loop that file back to DETECT.
Confidence gating (load-bearing)
Report a finding only at 100% certainty. Anything β€ ~70% goes to VERIFY (step 5) before it can
become a finding β never emit a speculative finding (especially nav-02 shell-vs-drill-down and nav-03
empty-middle-column, which need a READ to settle). Auto-fix only the mechanical placement/title set
(nav-05/06/07); everything else is fix_mode: flag-only.
Output contract
Inherits the toolkit's unified contract (full schema + body sections + frontmatter keys:
<swiftui-plugin-root>/references/_shared/finding-schema.md β do not restate it). Specialized for this
domain:
- Findings:
swiftui-audits/navigation-toolbars/<context>/NN-slug.md(one finding per file, zero-padded, ordered). Per-run index:swiftui-audits/navigation-toolbars/_index.md. domain: navigation-toolbars. Frontmatter is the canonical schema;fix_modeisautofor nav-05/06/07, elseflag-only.availabilityreads fromfloors-master.md.sourceis an Apple URL- access date (fetched via Sosumi) or
verify against Xcode 26 SDK. Emitcross_refper the boundary/seam note.
- access date (fetched via Sosumi) or
Starter <context> folders (file here whenβ¦):
<context> |
File a finding here when⦠|
|---|---|
navigation-shell/ |
a deprecated NavigationView, or a NavigationStack used as the Mac shell (nav-01, nav-02) |
column-structure/ |
a 3-col init with an empty middle, a frame-hack column hide, or a missing sidebar style (nav-03, nav-04, nav-09) |
toolbar-placement/ |
a platform-absent/deprecated placement, or .searchable on the wrong slot (nav-05, nav-06, nav-10) |
titlebar-title/ |
an iOS-bar title concept used instead of navigationTitle/navigationSubtitle (nav-07) |
inspector-detail-width/ |
a columnWidth no-op on detail, or a blank empty-detail (nav-08, nav-12) |
availability-gating/ |
ToolbarSpacer/SpacerSizing ungated under a < macOS 26 floor (nav-11) |
New-folder rule: if a finding does not fit any existing context folder, create a new one under
swiftui-audits/navigation-toolbars/ with a lowercase-hyphen slug naming the sub-category, and note it
in the run's _index.md. Prefer an existing folder when the fit is reasonable; consistency across runs
is a hard requirement. Two runs over the same code produce structurally identical trees.
Go-beyond artifact (optional):
swiftui-audits/navigation-toolbars/_column-map.mdclassifying every navigation container asshell/column-drilldownwith a column-count and visibility-binding coverage score β seereferences/navigation-shell-and-columns.md.
Reference routing
| File | Open when |
|---|---|
references/navigation-shell-and-columns.md |
shell-vs-stack, 2-/3-column inits, columnVisibility binding, sidebar List style, the column map (nav-01/02/03/04/09) |
references/toolbar-placements-and-titles.md |
semantic vs deprecated/platform-absent placements, navigationTitle/navigationSubtitle vs iOS-bar titles, .searchable slot, ToolbarSpacer gating (nav-05/06/07/10/11) |
references/inspector-and-detail-width.md |
the detail-column-width no-op, HSplitView/NSSplitViewController / .inspector workaround, empty-detail ContentUnavailableView (nav-08/12) |
references/source-directory.md |
step VERIFY β the Apple/WWDC/practitioner source map fetched via Sosumi |
lint/grep-tells.tsv + lint/ast-grep/*.yml |
step LOCATE β this skill's declarative lint rule set fed to the shared runner (tier-1 grep tells + tier-2 structural ast-grep); edit here to tune detection |
Shared toolkit references (point in, never restate):
| Shared file | For |
|---|---|
<swiftui-plugin-root>/references/_shared/floors-master.md |
every floor/availability value (the reconciled truth) |
<swiftui-plugin-root>/references/_shared/hallucination-blacklist.md |
Β§5 toolbar/navigation platform-wrong placements |
<swiftui-plugin-root>/references/_shared/macos-arm-gating.md |
the macOS-arm gating rule + the macOS ABSENT "replace, never gate" rule (nav-05, nav-11) |
<swiftui-plugin-root>/references/_shared/finding-schema.md |
the unified finding schema + frontmatter keys |
<swiftui-plugin-root>/references/_shared/fix-safety-protocol.md |
the 8-point fix-safety protocol (step 7) |
<swiftui-plugin-root>/references/_shared/sosumi-reference.md |
the Apple-doc spec fetch protocol (step 5 VERIFY) |
<swiftui-plugin-root>/references/_shared/swiftui-ctx-reference.md |
the practice-corpus CLI contract β lookup/deprecated/file --smart for the consensus shape + permalinked example (steps 5 VERIFY Β· 7 FIX) |
<swiftui-plugin-root>/references/_shared/cross-ref-graph.md |
seam ownership + cross_ref targets |
Detection accelerator
bash <swiftui-plugin-root>/scripts/swiftui-lint.sh --skill audit-swiftui-navigation-toolbars --dir <files-or-dir> [--json out.json] [--sarif out.sarif] β the toolkit's one shared hybrid lint engine, fed this
skill's declarative rules: tier-1 grep tells (lint/grep-tells.tsv,
nav-01/02/04/05/06/07/08/09/10/11/12) + the tier-2 ast-grep structural rule (lint/ast-grep/*.yml β
nav-03 empty-middle-column shape) that grep cannot express; nav-04 frame-hack and nav-08
columnWidth-on-detail: stay grep tells (READ-confirmed) because they can't be a clean ast-grep rule.
It runs
a per-file parse probe (surfaces "did not fully parse" so a structural miss can't look clean), emits
unified JSON + SARIF, exits 2 on any hard-fail (nav-05/06/07/11) for a CI gate, and degrades
to grep-only with a notice if ast-grep is unreachable (npx --package @ast-grep/cli ast-grep; faster:
brew install ast-grep). It only LOCATES β always READ each hit in full before reporting (step 3). The
thin scripts/nav-lint.sh is a pointer to this runner. Engine + rule-file format + JSON/SARIF shape +
safety rails: <swiftui-plugin-root>/references/_shared/lint-architecture.md.
Install
Add Audit Swiftui Navigation Toolbars to your client. Pick the one you use.
npx skills add yigitkonur/plugin-swiftuiInstalls every skill in the repository, then prompts for which to keep.
/plugin marketplace add yigitkonur/plugin-swiftuiAdds the repository as a plugin marketplace; install individual plugins with `/plugin install`.
git clone https://github.com/yigitkonur/plugin-swiftui
cp -r plugins/swiftui/skills/audit-swiftui-navigation-toolbars ~/.claude/skills/A skill is a plain directory. Copy it into `.claude/skills/` in a project or in your home directory.
Score
75 / 100
Good