diff --git a/docs-ai/063-agent-workflows/000-plan.md b/docs-ai/063-agent-workflows/000-plan.md index 1600f4f4..e7af7060 100644 --- a/docs-ai/063-agent-workflows/000-plan.md +++ b/docs-ai/063-agent-workflows/000-plan.md @@ -564,4 +564,4 @@ attaches hooks through A2's launch boundary. ## Amendments -(append `- Updated 2026-MM-DD: ... — see [00N-topic.md](00N-topic.md)` lines here) +- Updated 2026-08-22: Shipped C0 with the Agents sidebar group, Profiles page, and Command Line Tool page; Workflows remains deferred to D1 — see [001-settings-agents-group.md](001-settings-agents-group.md). diff --git a/docs-ai/063-agent-workflows/001-settings-agents-group.md b/docs-ai/063-agent-workflows/001-settings-agents-group.md new file mode 100644 index 00000000..755d35dd --- /dev/null +++ b/docs-ai/063-agent-workflows/001-settings-agents-group.md @@ -0,0 +1,30 @@ +# 063.001 — Settings Agents Group (C0) + +## Context + +Release R1 starts by establishing the Settings information architecture that later workflow UI will extend. The existing Agent Profiles page was a standalone “Agents” sidebar item, while the `prowl` installation controls lived under Advanced. + +## Change + +- Settings now has an `Agents` sidebar group with `Profiles` and `Command Line Tool` pages. +- The existing profile list is titled `Profiles`; `openAgentProfilesSettings` and “Manage Agent Profiles…” continue to select it. +- The Command Line Tool page owns the existing install/status controls and also exposes the active Unix socket path and the existing agent-help prompt. +- Advanced now contains only analytics, crash reporting, and terminal-layout controls. +- The Workflows page remains absent until 063-D1, as planned. + +## Current state + +The selection boundary is represented by `SettingsSection.profiles` and `.commandLineTool`. Profile editor state is initialized only for the Profiles page and is cleared when another page is selected. CLI installation behavior remains owned by `SettingsFeature`; C0 only moves its Settings presentation. + +## Verification + +- Focused Settings selection and CLI-install suites: 11 tests passed. +- `make check` passed. +- `make test` verified 2,366 tests with zero failures; five dependency-scan warnings remain pre-existing. +- `make build-app` passed with zero warnings and errors. +- An isolated Debug app was navigated through Settings to Profiles and Command Line Tool; both rendered with the expected native window titles and ordering. + +## Refs + +- Slice: 063-C0 +- Branch: `feat/settings-agents-group` diff --git a/docs/components/agent-profiles.md b/docs/components/agent-profiles.md index 7e0c5f34..701f480d 100644 --- a/docs/components/agent-profiles.md +++ b/docs/components/agent-profiles.md @@ -32,7 +32,8 @@ respawn. row shows the profile name with the runtime name trailing. Rows for runtimes that look unavailable are dimmed with a warning but stay clickable — availability signals can be wrong, so they never block a launch. "Manage - Agent Profiles…" opens Settings → Agents. When launch rows exist the capsule + Agent Profiles…" opens Settings → Agents → Profiles. When launch rows exist + the capsule carries a trailing **quick-launch segment** (a `play.circle` split button): one click launches the Recommended profile directly, skipping the popover. - **Command Palette** (`⌘P`) — "Launch Agent: " rows dispatch the exact @@ -52,8 +53,8 @@ launched" memory behind the Recommended resolution. ## Managing profiles -Open **Settings → Agents** to see the ordered profile list. Click a profile to -push its editor; the native Back control returns to the list while the Settings +Open **Settings → Agents → Profiles** to see the ordered profile list. Click a +profile to push its editor; the native Back control returns to the list while the Settings sidebar remains available. Adding a profile opens the same editor immediately. Changing another Settings sidebar section leaves the editor and opens that section's root. diff --git a/docs/components/cli.md b/docs/components/cli.md index d2b7fbcd..85de5524 100644 --- a/docs/components/cli.md +++ b/docs/components/cli.md @@ -22,9 +22,10 @@ inside a repo, and not for how-to questions about Prowl's settings. ## Install -From the app: **Settings → Advanced → Install Command Line Tool**, or Command +From the app: **Settings → Agents → Command Line Tool → Install**, or Command Palette → "Install Command Line Tool". This symlinks `prowl` into -`/usr/local/bin` (prompting for admin if needed). +`/usr/local/bin` (prompting for admin if needed). The Settings page also shows +the active local socket path used by the CLI. ## Global options diff --git a/docs/components/settings.md b/docs/components/settings.md index aaddf133..fe6e4ffd 100644 --- a/docs/components/settings.md +++ b/docs/components/settings.md @@ -16,10 +16,10 @@ Settings brings the existing Settings window forward rather than creating another one. `⌘W` closes it. Most sections are roots in the detail pane. A section can drill in without -losing the sidebar; for example, **Agents** → a profile pushes its editor and -macOS shows the standard Back control beside the editor title. Back returns to -the Agents list, while selecting another sidebar item leaves the drill-in and -opens that section's root. +losing the sidebar; for example, **Agents → Profiles** → a profile pushes its +editor and macOS shows the standard Back control beside the editor title. Back +returns to Profiles, while selecting another sidebar item leaves the drill-in +and opens that section's root. ## Sections @@ -30,10 +30,11 @@ opens that section's root. | **Shortcuts** | Remap app keyboard shortcuts; view defaults; resolve conflicts. → [keyboard-shortcuts](../reference/keyboard-shortcuts.md) | | **Worktree** | Worktree creation/deletion defaults: prompt on create, fetch before create, base directory, copy ignored/untracked files, automatic local-branch cleanup, merged-worktree action, archived auto-delete period. | | **Updates** | Auto-check toggle, "Check for Updates Now". → [updates](updates.md) | -| **Advanced** | Analytics, crash reports, restore terminal layout on launch (experimental) + clear saved layout, and the **Install Command Line Tool** (`prowl` CLI) action. | +| **Advanced** | Analytics, crash reports, restore terminal layout on launch (experimental) + clear saved layout. | | **GitHub** | Enable GitHub integration (uses the `gh` CLI). → [github-pull-requests](github-pull-requests.md) | | **Commands** | Global Custom Commands. Enabled commands appear in the window toolbar; each repo can independently hide a Global command. → [custom-actions](custom-actions.md) | -| **Agents** | Agent Profiles: named launch presets for Claude Code/Codex (model, effort, execution mode, tab/split placement, extra arguments, opt-in dedicated home for a separate account) with a live launch preview. List order is the recommendation fallback. → [agent-profiles](agent-profiles.md) | +| **Agents → Profiles** | Named launch presets for supported agent runtimes (model, effort, execution mode, tab/split placement, extra arguments, opt-in dedicated home for a separate account) with a live launch preview. List order is the recommendation fallback. → [agent-profiles](agent-profiles.md) | +| **Agents → Command Line Tool** | Install/status for the bundled `prowl` CLI, its local socket path, and an “Ask Agent About Prowl…” prompt entry. → [cli](cli.md) | | **Repositories / Repo Settings** | Per-repository: setup/archive/run scripts, **Custom Commands**, Global-command visibility, **Default Agent Profile**, default base ref & directory, copy-files overrides, open-with app, custom title, icon & color, PR merge strategy, line-diff & PR-state fetching. Reached from the sidebar context menu → "Repo Settings". → [custom-actions](custom-actions.md), [repositories-and-worktrees](repositories-and-worktrees.md) | ## Where settings live on disk @@ -48,7 +49,7 @@ Legacy `~/.supacode` is migrated to `~/.prowl` on first launch. ## Install the CLI from here -**Advanced → Install Command Line Tool** symlinks `prowl` into `/usr/local/bin` +**Agents → Command Line Tool → Install** symlinks `prowl` into `/usr/local/bin` (prompting for admin rights if needed). Also available via Command Palette → "Install Command Line Tool". See [cli](cli.md). diff --git a/supacode/Features/App/Reducer/AppFeature.swift b/supacode/Features/App/Reducer/AppFeature.swift index 65059c30..f653bc61 100644 --- a/supacode/Features/App/Reducer/AppFeature.swift +++ b/supacode/Features/App/Reducer/AppFeature.swift @@ -380,7 +380,7 @@ struct AppFeature { state.settings.repositorySettings = nil state.settings.globalCustomCommands = .init() state.settings.agentProfiles = nil - case .agents: + case .profiles: state.settings.repositorySettings = nil state.settings.globalCustomCommands = nil state.settings.agentProfiles = .init() @@ -407,7 +407,7 @@ struct AppFeature { state.settings.repositorySettings = repoSettingsState state.settings.globalCustomCommands = nil state.settings.agentProfiles = nil - case .general, .notifications, .shortcuts, .worktree, .updates, .advanced, .github: + case .general, .notifications, .shortcuts, .worktree, .updates, .advanced, .github, .commandLineTool: state.settings.repositorySettings = nil state.settings.globalCustomCommands = nil state.settings.agentProfiles = nil @@ -715,7 +715,7 @@ struct AppFeature { return launchAgentProfile(profileID, state: &state) case .openAgentProfilesSettings: - return openSettingsEffect(selecting: .agents) + return openSettingsEffect(selecting: .profiles) case .runCustomCommand(let commandID): guard let worktree = actionTargetWorktree(repositories: state.repositories) else { diff --git a/supacode/Features/Settings/Views/AdvancedSettingsView.swift b/supacode/Features/Settings/Views/AdvancedSettingsView.swift index 4c19d398..d5e8c869 100644 --- a/supacode/Features/Settings/Views/AdvancedSettingsView.swift +++ b/supacode/Features/Settings/Views/AdvancedSettingsView.swift @@ -7,62 +7,6 @@ struct AdvancedSettingsView: View { var body: some View { VStack(alignment: .leading) { Form { - Section("Command Line Tool") { - VStack(alignment: .leading, spacing: 8) { - HStack(spacing: 6) { - switch store.cliInstallStatus { - case .installed(let path): - Image(systemName: "checkmark.circle.fill") - .foregroundStyle(.green) - .accessibilityLabel("Installed") - Text("Installed at \(path)") - case .installedDifferentSource(let path): - Image(systemName: "exclamationmark.triangle.fill") - .foregroundStyle(.yellow) - .accessibilityLabel("Different version") - Text("A different version exists at \(path)") - case .notInstalled: - Image(systemName: "xmark.circle") - .foregroundStyle(.secondary) - .accessibilityLabel("Not installed") - Text("Not installed") - } - } - .font(.callout) - - Text("Install the prowl command to control Prowl from the terminal.") - .foregroundStyle(.secondary) - .font(.callout) - - HStack(spacing: 8) { - switch store.cliInstallStatus { - case .notInstalled: - Button("Install") { - store.send(.installCLIButtonTapped()) - } - .help("Install prowl command line tool to /usr/local/bin") - .buttonStyle(.bordered) - case .installed: - Button("Uninstall") { - store.send(.uninstallCLIButtonTapped) - } - .help("Remove prowl command line tool from /usr/local/bin") - .buttonStyle(.bordered) - case .installedDifferentSource: - Button("Reinstall") { - store.send(.installCLIButtonTapped()) - } - .help("Replace the existing prowl command with the version bundled in this app") - .buttonStyle(.bordered) - } - } - } - .frame(maxWidth: .infinity, alignment: .leading) - .onAppear { - store.send(.refreshCLIInstallStatus) - } - } - Section("Advanced") { VStack(alignment: .leading) { Toggle( diff --git a/supacode/Features/Settings/Views/AgentProfilesSettingsView.swift b/supacode/Features/Settings/Views/AgentProfilesSettingsView.swift index 357e5d20..a673ce9b 100644 --- a/supacode/Features/Settings/Views/AgentProfilesSettingsView.swift +++ b/supacode/Features/Settings/Views/AgentProfilesSettingsView.swift @@ -1,7 +1,7 @@ import ComposableArchitecture import SwiftUI -/// Settings → Agents: the profile list, with a native drill-in editor page per +/// Settings → Agents → Profiles: the profile list, with a native drill-in editor page per /// profile. `NavigationStack` is driven by TCA's `StackState`, so the system /// Back control writes its pop directly to the reducer-owned route. /// List order is the recommendation fallback order. @@ -14,7 +14,7 @@ struct AgentProfilesSettingsView: View { profileListSection } .formStyle(.grouped) - .navigationTitle("Agents") + .navigationTitle("Profiles") .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) .task { store.send(.task) } } destination: { editorStore in diff --git a/supacode/Features/Settings/Views/CommandLineToolSettingsView.swift b/supacode/Features/Settings/Views/CommandLineToolSettingsView.swift new file mode 100644 index 00000000..dec87af7 --- /dev/null +++ b/supacode/Features/Settings/Views/CommandLineToolSettingsView.swift @@ -0,0 +1,103 @@ +import ComposableArchitecture +import SwiftUI + +struct CommandLineToolSettingsView: View { + @Bindable var store: StoreOf + @State private var isAskAgentHelpPresented = false + + var body: some View { + Form { + Section("Installation") { + VStack(alignment: .leading, spacing: 8) { + HStack(spacing: 6) { + switch store.cliInstallStatus { + case .installed(let path): + Image(systemName: "checkmark.circle.fill") + .foregroundStyle(.green) + .accessibilityLabel("Installed") + Text("Installed at \(path)") + case .installedDifferentSource(let path): + Image(systemName: "exclamationmark.triangle.fill") + .foregroundStyle(.yellow) + .accessibilityLabel("Different version") + Text("A different version exists at \(path)") + case .notInstalled: + Image(systemName: "xmark.circle") + .foregroundStyle(.secondary) + .accessibilityLabel("Not installed") + Text("Not installed") + } + } + .font(.callout) + + Text("Install the prowl command to let terminals and coding agents control Prowl.") + .foregroundStyle(.secondary) + .font(.callout) + + HStack(spacing: 8) { + switch store.cliInstallStatus { + case .notInstalled: + Button("Install") { + store.send(.installCLIButtonTapped()) + } + .help("Install prowl command line tool to /usr/local/bin") + .buttonStyle(.bordered) + case .installed: + Button("Uninstall") { + store.send(.uninstallCLIButtonTapped) + } + .help("Remove prowl command line tool from /usr/local/bin") + .buttonStyle(.bordered) + case .installedDifferentSource: + Button("Reinstall") { + store.send(.installCLIButtonTapped()) + } + .help("Replace the existing prowl command with the version bundled in this app") + .buttonStyle(.bordered) + } + } + } + .frame(maxWidth: .infinity, alignment: .leading) + .onAppear { + store.send(.refreshCLIInstallStatus) + } + } + + Section("Connection") { + LabeledContent("Socket") { + Text(ProwlSocket.defaultPath) + .font(.callout.monospaced()) + .foregroundStyle(.secondary) + .textSelection(.enabled) + .lineLimit(1) + .truncationMode(.middle) + } + + Text("prowl connects to the running app through this local Unix socket.") + .foregroundStyle(.secondary) + .font(.callout) + } + + Section("Ask Your Agent") { + VStack(alignment: .leading, spacing: 8) { + Text("Give your coding agent a prompt that points it at Prowl's bundled documentation.") + .foregroundStyle(.secondary) + .font(.callout) + Button("Ask Agent About Prowl…") { + isAskAgentHelpPresented = true + } + .help("Copy a prompt that points your coding agent at Prowl's bundled docs") + .buttonStyle(.bordered) + } + .frame(maxWidth: .infinity, alignment: .leading) + } + } + .formStyle(.grouped) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) + .sheet(isPresented: $isAskAgentHelpPresented) { + AskAgentHelpView { + isAskAgentHelpPresented = false + } + } + } +} diff --git a/supacode/Features/Settings/Views/SettingsSection.swift b/supacode/Features/Settings/Views/SettingsSection.swift index 2e81144b..230b9bf6 100644 --- a/supacode/Features/Settings/Views/SettingsSection.swift +++ b/supacode/Features/Settings/Views/SettingsSection.swift @@ -9,6 +9,7 @@ enum SettingsSection: Hashable { case advanced case github case customCommands - case agents + case profiles + case commandLineTool case repository(Repository.ID) } diff --git a/supacode/Features/Settings/Views/SettingsView.swift b/supacode/Features/Settings/Views/SettingsView.swift index 21e50ece..3fd4a5d5 100644 --- a/supacode/Features/Settings/Views/SettingsView.swift +++ b/supacode/Features/Settings/Views/SettingsView.swift @@ -36,8 +36,13 @@ struct SettingsView: View { .tag(SettingsSection.github) Label("Commands", systemImage: "globe") .tag(SettingsSection.customCommands) - Label("Agents", systemImage: "sparkles") - .tag(SettingsSection.agents) + + Section("Agents") { + Label("Profiles", systemImage: "person.crop.circle") + .tag(SettingsSection.profiles) + Label("Command Line Tool", systemImage: "terminal") + .tag(SettingsSection.commandLineTool) + } Section("Repositories") { ForEach(repositories) { repository in @@ -102,7 +107,7 @@ struct SettingsView: View { .frame(maxWidth: .infinity, maxHeight: .infinity) } } - case .agents: + case .profiles: SettingsDetailView { if let agentProfilesStore = settingsStore.scope( state: \.agentProfiles, @@ -114,6 +119,11 @@ struct SettingsView: View { .frame(maxWidth: .infinity, maxHeight: .infinity) } } + case .commandLineTool: + SettingsDetailView { + CommandLineToolSettingsView(store: settingsStore) + .navigationTitle("Command Line Tool") + } case .repository(let repositoryID): if let repository = repositories[id: repositoryID] { SettingsDetailView { diff --git a/supacodeTests/AppFeatureSettingsSelectionTests.swift b/supacodeTests/AppFeatureSettingsSelectionTests.swift index 98ed021b..3792b848 100644 --- a/supacodeTests/AppFeatureSettingsSelectionTests.swift +++ b/supacodeTests/AppFeatureSettingsSelectionTests.swift @@ -163,10 +163,32 @@ struct AppFeatureSettingsSelectionTests { } } + @Test(.dependencies) func openAgentProfilesSettingsSelectsProfiles() async { + let shown = LockIsolated(false) + var state = AppFeature.State(settings: SettingsFeature.State()) + state.settings.selection = .commandLineTool + let store = TestStore(initialState: state) { + AppFeature() + } withDependencies: { + $0.settingsWindowClient.show = { + shown.withValue { $0 = true } + } + } + + await store.send(.openAgentProfilesSettings) + await store.receive(\.settings.setSelection) { + $0.settings.selection = .profiles + $0.settings.agentProfiles = .init() + } + await store.finish() + + #expect(shown.value) + } + @Test func selectingAnotherSectionClearsAgentProfileEditorState() async { let profile = AgentProfile(name: "Codex", runtime: .codex) var state = AppFeature.State(settings: SettingsFeature.State()) - state.settings.selection = .agents + state.settings.selection = .profiles var agentProfiles = AgentProfilesFeature.State() agentProfiles.settings = UserGlobalSettings(customCommands: [], agentProfiles: [profile]) agentProfiles.path.append(AgentProfileEditorFeature.State(profile: profile)) -- 2.51.2 From 22abd4a6d4bb2d026a2f7488293e6baa6483b022 Mon Sep 17 00:00:00 2001 From: onevcat Date: Sat, 22 Aug 2026 10:34:10 +0900 Subject: [PATCH 02/11] docs: link settings group pull request --- docs-ai/063-agent-workflows/001-settings-agents-group.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs-ai/063-agent-workflows/001-settings-agents-group.md b/docs-ai/063-agent-workflows/001-settings-agents-group.md index 755d35dd..bf8e038f 100644 --- a/docs-ai/063-agent-workflows/001-settings-agents-group.md +++ b/docs-ai/063-agent-workflows/001-settings-agents-group.md @@ -28,3 +28,4 @@ The selection boundary is represented by `SettingsSection.profiles` and `.comman - Slice: 063-C0 - Branch: `feat/settings-agents-group` +- PR: #709 -- 2.51.2 From e9dd218a537fbb1c366addf2e6f74320871640e5 Mon Sep 17 00:00:00 2001 From: onevcat Date: Sat, 22 Aug 2026 14:15:25 +0900 Subject: [PATCH 03/11] refactor(settings): tighten Agents group pages after review - Drop the generic Ask-Agent entry from Command Line Tool; agent skill distribution is a separate slice and the page stays CLI-only for now - Describe the socket row as where prowl connects (PROWL_CLI_SOCKET override) instead of implying a live status - Title the profile list "Agent Profiles" while the sidebar keeps "Profiles" - Split Advanced into Analytics & Crash Reports / Terminal Layout sections - Cover .commandLineTool in the editor-state clearing test - Record slice as 063.002 and document the multi-PR amendment convention Claude-Session: https://claude.ai/code/session_01YUytym5xEn5FKMhWjSkNkm --- ...{001-settings-agents-group.md => 002-settings-agents-group.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs-ai/063-agent-workflows/{001-settings-agents-group.md => 002-settings-agents-group.md} (100%) diff --git a/docs-ai/063-agent-workflows/001-settings-agents-group.md b/docs-ai/063-agent-workflows/002-settings-agents-group.md similarity index 100% rename from docs-ai/063-agent-workflows/001-settings-agents-group.md rename to docs-ai/063-agent-workflows/002-settings-agents-group.md -- 2.51.2 From 48732b02b84642dc828124652ef1d1c1313c9472 Mon Sep 17 00:00:00 2001 From: onevcat Date: Sat, 22 Aug 2026 14:15:57 +0900 Subject: [PATCH 04/11] refactor(settings): apply Agents group review fixes The previous commit only carried the docs-ai rename; this one holds the rest of the review follow-up: - Drop the generic Ask-Agent entry from Command Line Tool; agent skill distribution is a separate slice and the page stays CLI-only for now - Describe the socket row as where prowl connects (PROWL_CLI_SOCKET override) instead of implying a live status - Title the profile list "Agent Profiles" while the sidebar keeps "Profiles" - Split Advanced into Analytics & Crash Reports / Terminal Layout sections - Cover .commandLineTool in the editor-state clearing test - Fill in 063.002 and document the multi-PR amendment convention Claude-Session: https://claude.ai/code/session_01YUytym5xEn5FKMhWjSkNkm --- .claude/skills/write-ai-doc/SKILL.md | 3 + docs-ai/063-agent-workflows/000-plan.md | 2 +- .../002-settings-agents-group.md | 29 ++++-- docs-ai/README.md | 6 +- docs/components/cli.md | 3 +- docs/components/settings.md | 4 +- .../Reducer/AgentProfileEditorFeature.swift | 2 +- .../Reducer/AgentProfilesFeature.swift | 2 +- .../Settings/Views/AdvancedSettingsView.swift | 92 +++++++++---------- .../Views/AgentProfileEditorView.swift | 2 +- .../Views/AgentProfilesSettingsView.swift | 2 +- .../Views/CommandLineToolSettingsView.swift | 32 ++----- .../AppFeatureSettingsSelectionTests.swift | 7 +- 13 files changed, 94 insertions(+), 92 deletions(-) diff --git a/.claude/skills/write-ai-doc/SKILL.md b/.claude/skills/write-ai-doc/SKILL.md index 8086193c..f3599e78 100644 --- a/.claude/skills/write-ai-doc/SKILL.md +++ b/.claude/skills/write-ai-doc/SKILL.md @@ -46,6 +46,9 @@ non-qualifying task. When in doubt, do not write one. `- Updated 2026-MM-DD: — see [002-.md](002-.md)`. 3. If the follow-up invalidates part of the plan or action text, correct that text in place (keep it truthful) and note the correction in the amendment. +4. Multi-PR entries (a plan with a slice table, e.g. `063`): each slice ships its own + `00N-.md` amendment in the slice's PR, starting at `002`; write `001-action.md` + once, when the last slice lands (or the entry is superseded), summarizing the slices. ### 3. Large pivot / redesign diff --git a/docs-ai/063-agent-workflows/000-plan.md b/docs-ai/063-agent-workflows/000-plan.md index e7af7060..ca24f806 100644 --- a/docs-ai/063-agent-workflows/000-plan.md +++ b/docs-ai/063-agent-workflows/000-plan.md @@ -564,4 +564,4 @@ attaches hooks through A2's launch boundary. ## Amendments -- Updated 2026-08-22: Shipped C0 with the Agents sidebar group, Profiles page, and Command Line Tool page; Workflows remains deferred to D1 — see [001-settings-agents-group.md](001-settings-agents-group.md). +- Updated 2026-08-22: Shipped C0 with the Agents sidebar group, Profiles page, and Command Line Tool page; Workflows remains deferred to D1 — see [002-settings-agents-group.md](002-settings-agents-group.md). diff --git a/docs-ai/063-agent-workflows/002-settings-agents-group.md b/docs-ai/063-agent-workflows/002-settings-agents-group.md index bf8e038f..dd9bf008 100644 --- a/docs-ai/063-agent-workflows/002-settings-agents-group.md +++ b/docs-ai/063-agent-workflows/002-settings-agents-group.md @@ -1,4 +1,4 @@ -# 063.001 — Settings Agents Group (C0) +# 063.002 — Settings Agents Group (C0) ## Context @@ -6,23 +6,32 @@ Release R1 starts by establishing the Settings information architecture that lat ## Change -- Settings now has an `Agents` sidebar group with `Profiles` and `Command Line Tool` pages. -- The existing profile list is titled `Profiles`; `openAgentProfilesSettings` and “Manage Agent Profiles…” continue to select it. -- The Command Line Tool page owns the existing install/status controls and also exposes the active Unix socket path and the existing agent-help prompt. -- Advanced now contains only analytics, crash reporting, and terminal-layout controls. +- Settings now reads: flat items (General … Commands) → `Agents` group (`Profiles`, `Command Line Tool`) → `Repositories` group. +- The profile list keeps the sidebar label `Profiles` and is titled `Agent Profiles`; `openAgentProfilesSettings` and “Manage Agent Profiles…” continue to select it. +- The Command Line Tool page owns the existing install/status controls and shows the Unix socket path `prowl` uses to reach the app (`ProwlSocket.defaultPath`, honouring `PROWL_CLI_SOCKET`). The copy describes where `prowl` connects; it does not claim the socket is live. +- Advanced keeps analytics, crash reporting, and terminal-layout controls, now split into `Analytics & Crash Reports` and `Terminal Layout` sections. - The Workflows page remains absent until 063-D1, as planned. +## Deviations from plan + +- The plan listed an “Ask your agent” entry on the Command Line Tool page. The existing Ask-Agent-About-Prowl prompt (Help menu, sidebar footer) is a user-onboarding prompt, not a CLI one, so it was not duplicated here. What this page should eventually carry is agent *skill* distribution: bundling the official skills (`skills/prowl-cli`, later review/handoff skills) into the app, a `prowl skills` CLI that links them into user or project skill folders, and an install/update UI mirroring the CLI one. That is a separate slice with its own plan; until it lands the page has no agent-help section. +- Slice records in 063 are amendments starting at `002`; `001-action.md` is written when the entry completes (see `docs-ai/README.md`). + ## Current state -The selection boundary is represented by `SettingsSection.profiles` and `.commandLineTool`. Profile editor state is initialized only for the Profiles page and is cleared when another page is selected. CLI installation behavior remains owned by `SettingsFeature`; C0 only moves its Settings presentation. +The selection boundary is `SettingsSection.profiles` / `.commandLineTool` (`supacode/Features/Settings/Views/SettingsSection.swift`). Profile editor state is initialized only for the Profiles page and cleared when another page is selected (`AppFeature.swift`, `.settings(.setSelection)`). CLI installation behavior remains owned by `SettingsFeature`; C0 only moves its presentation to `supacode/Features/Settings/Views/CommandLineToolSettingsView.swift`. + +## Deferred + +- Socket listening status: a `CLISocketServer` start failure is only logged (`supacode/App/supacodeApp.swift`), so the page cannot tell “should listen here” from “is listening”. Surfacing `listening / failed(reason)` needs the server state plumbed into `SettingsFeature`; its natural home is the 063-D1 CLI preflight, which needs the same reachability signal. +- Skill distribution (`prowl skills` + Settings UI): separate plan. ## Verification -- Focused Settings selection and CLI-install suites: 11 tests passed. - `make check` passed. -- `make test` verified 2,366 tests with zero failures; five dependency-scan warnings remain pre-existing. -- `make build-app` passed with zero warnings and errors. -- An isolated Debug app was navigated through Settings to Profiles and Command Line Tool; both rendered with the expected native window titles and ordering. +- Focused suites (`AppFeatureSettingsSelectionTests`, `AppFeatureCLIInstallTests`, `SettingsFeatureTests`, `CLIInstallClientTests`) passed; the test build also compiles the app target. +- `make test` on the initial revision: 2,366 verified, zero failures (five pre-existing dependency-scan warnings). +- An isolated Debug app was navigated through Settings to Profiles and Command Line Tool on the initial revision; both rendered with the expected native window titles and ordering. ## Refs diff --git a/docs-ai/README.md b/docs-ai/README.md index ddc36f52..18a2e30d 100644 --- a/docs-ai/README.md +++ b/docs-ai/README.md @@ -15,14 +15,16 @@ onevcat explicitly asks for a `docs-ai/` record. docs-ai/NNN-/ 000-plan.md # plan before implementation (RFC-like) 001-action.md # what was actually done, verified against the code - 002-.md # amendments: follow-up waves, corrections (indexed in 000-plan.md) + 002-.md # amendments: follow-up waves, corrections, or one record per slice of a multi-PR entry (indexed in 000-plan.md) .md # non-numbered = living doc (runbook/ledger/reference), updated in place ``` Rules for writing new entries live in the `write-ai-doc` skill (`.claude/skills/write-ai-doc/SKILL.md`). In short: select only qualifying product work, then plan first, act second, amend in place for in-frame follow-ups, and open a new numbered -entry for large pivots. Numbered files are immutable history; non-numbered files are living +entry for large pivots. An entry delivered across several PRs records each slice as an +amendment (`002+`, shipped with its PR) and writes `001-action.md` once, when the last slice +lands, summarizing them. Numbered files are immutable history; non-numbered files are living documents. Entries `001`–`045` were backfilled on 2026-07-12 from PRs, commits, and the former diff --git a/docs/components/cli.md b/docs/components/cli.md index 85de5524..c2b4dd3b 100644 --- a/docs/components/cli.md +++ b/docs/components/cli.md @@ -25,7 +25,8 @@ inside a repo, and not for how-to questions about Prowl's settings. From the app: **Settings → Agents → Command Line Tool → Install**, or Command Palette → "Install Command Line Tool". This symlinks `prowl` into `/usr/local/bin` (prompting for admin if needed). The Settings page also shows -the active local socket path used by the CLI. +the local Unix socket path `prowl` uses to reach the app (`PROWL_CLI_SOCKET` +overrides it for both processes). ## Global options diff --git a/docs/components/settings.md b/docs/components/settings.md index fe6e4ffd..fc7e2ab4 100644 --- a/docs/components/settings.md +++ b/docs/components/settings.md @@ -3,7 +3,7 @@ > The Settings window (`⌘,`): what each tab controls. For the exhaustive > field-by-field list, see [`reference/settings-fields.md`](../reference/settings-fields.md). -**Keywords:** settings, preferences, ⌘comma, general, notifications, shortcuts, worktree, updates, advanced, github, repo settings, appearance +**Keywords:** settings, preferences, ⌘comma, general, notifications, shortcuts, worktree, updates, advanced, github, agents, agent profiles, command line tool, cli, repo settings, appearance **Related:** [reference/settings-fields](../reference/settings-fields.md) · [custom-actions](custom-actions.md) · [updates](updates.md) · [notifications](notifications.md) @@ -34,7 +34,7 @@ and opens that section's root. | **GitHub** | Enable GitHub integration (uses the `gh` CLI). → [github-pull-requests](github-pull-requests.md) | | **Commands** | Global Custom Commands. Enabled commands appear in the window toolbar; each repo can independently hide a Global command. → [custom-actions](custom-actions.md) | | **Agents → Profiles** | Named launch presets for supported agent runtimes (model, effort, execution mode, tab/split placement, extra arguments, opt-in dedicated home for a separate account) with a live launch preview. List order is the recommendation fallback. → [agent-profiles](agent-profiles.md) | -| **Agents → Command Line Tool** | Install/status for the bundled `prowl` CLI, its local socket path, and an “Ask Agent About Prowl…” prompt entry. → [cli](cli.md) | +| **Agents → Command Line Tool** | Install/status for the bundled `prowl` CLI and the local socket path it uses to reach the app. → [cli](cli.md) | | **Repositories / Repo Settings** | Per-repository: setup/archive/run scripts, **Custom Commands**, Global-command visibility, **Default Agent Profile**, default base ref & directory, copy-files overrides, open-with app, custom title, icon & color, PR merge strategy, line-diff & PR-state fetching. Reached from the sidebar context menu → "Repo Settings". → [custom-actions](custom-actions.md), [repositories-and-worktrees](repositories-and-worktrees.md) | ## Where settings live on disk diff --git a/supacode/Features/Settings/Reducer/AgentProfileEditorFeature.swift b/supacode/Features/Settings/Reducer/AgentProfileEditorFeature.swift index b691db95..adea225f 100644 --- a/supacode/Features/Settings/Reducer/AgentProfileEditorFeature.swift +++ b/supacode/Features/Settings/Reducer/AgentProfileEditorFeature.swift @@ -3,7 +3,7 @@ import Foundation import Sharing import SwiftUI -/// Settings → Agents → drill-in editor for one profile (docs-ai 053). Owns +/// Settings → Agents → Profiles → drill-in editor for one profile (docs-ai 053). Owns /// every profile-scoped mutation gate (unrestricted confirmation, removal /// confirmation) and its own alert: the presentation state lives inside the /// pushed page's state, so an alert can only ever fire while the page that diff --git a/supacode/Features/Settings/Reducer/AgentProfilesFeature.swift b/supacode/Features/Settings/Reducer/AgentProfilesFeature.swift index 39dc2c5a..eb1df86e 100644 --- a/supacode/Features/Settings/Reducer/AgentProfilesFeature.swift +++ b/supacode/Features/Settings/Reducer/AgentProfilesFeature.swift @@ -3,7 +3,7 @@ import Foundation import Sharing import SwiftUI -/// Settings → Agents: the global agent profile list (docs-ai 053). List order +/// Settings → Agents → Profiles: the global agent profile list (docs-ai 053). List order /// is the recommendation fallback order; edits persist to /// `UserGlobalSettings` the same way global custom commands do. Editing one /// profile is a native drill-in `AgentProfileEditorFeature` represented by a diff --git a/supacode/Features/Settings/Views/AdvancedSettingsView.swift b/supacode/Features/Settings/Views/AdvancedSettingsView.swift index d5e8c869..d100a1d4 100644 --- a/supacode/Features/Settings/Views/AdvancedSettingsView.swift +++ b/supacode/Features/Settings/Views/AdvancedSettingsView.swift @@ -5,58 +5,58 @@ struct AdvancedSettingsView: View { @Bindable var store: StoreOf var body: some View { - VStack(alignment: .leading) { - Form { - Section("Advanced") { - VStack(alignment: .leading) { - Toggle( - "Share analytics with Prowl", - isOn: $store.analyticsEnabled - ) - .help("Share anonymous usage data with Prowl (requires restart)") - Text("Anonymous usage data helps improve Prowl.") - .foregroundStyle(.secondary) - .font(.callout) - Text("Requires app restart.") - .foregroundStyle(.secondary) - .font(.callout) - } - .frame(maxWidth: .infinity, alignment: .leading) + Form { + Section("Analytics & Crash Reports") { + VStack(alignment: .leading) { + Toggle( + "Share analytics with Prowl", + isOn: $store.analyticsEnabled + ) + .help("Share anonymous usage data with Prowl (requires restart)") + Text("Anonymous usage data helps improve Prowl.") + .foregroundStyle(.secondary) + .font(.callout) + Text("Requires app restart.") + .foregroundStyle(.secondary) + .font(.callout) + } + .frame(maxWidth: .infinity, alignment: .leading) - VStack(alignment: .leading) { - Toggle( - "Share crash reports with Prowl", - isOn: $store.crashReportsEnabled - ) - .help("Share anonymous crash reports with Prowl (requires restart)") - Text("Anonymous crash reports help improve stability.") - .foregroundStyle(.secondary) - .font(.callout) - Text("Requires app restart.") - .foregroundStyle(.secondary) - .font(.callout) - } - .frame(maxWidth: .infinity, alignment: .leading) + VStack(alignment: .leading) { + Toggle( + "Share crash reports with Prowl", + isOn: $store.crashReportsEnabled + ) + .help("Share anonymous crash reports with Prowl (requires restart)") + Text("Anonymous crash reports help improve stability.") + .foregroundStyle(.secondary) + .font(.callout) + Text("Requires app restart.") + .foregroundStyle(.secondary) + .font(.callout) + } + .frame(maxWidth: .infinity, alignment: .leading) + } - VStack(alignment: .leading, spacing: 8) { - Toggle( - "Restore terminal layout on launch (experimental)", - isOn: $store.restoreTerminalLayoutOnLaunch - ) - Text("When enabled, Prowl attempts to restore tabs and splits after restart.") - .foregroundStyle(.secondary) - .font(.callout) - Button("Clear saved terminal layout") { - store.send(.clearTerminalLayoutSnapshotButtonTapped) - } - .help("Remove the saved terminal tab and split layout from disk") - .buttonStyle(.bordered) + Section("Terminal Layout") { + VStack(alignment: .leading, spacing: 8) { + Toggle( + "Restore terminal layout on launch (experimental)", + isOn: $store.restoreTerminalLayoutOnLaunch + ) + Text("When enabled, Prowl attempts to restore tabs and splits after restart.") + .foregroundStyle(.secondary) + .font(.callout) + Button("Clear saved terminal layout") { + store.send(.clearTerminalLayoutSnapshotButtonTapped) } - .frame(maxWidth: .infinity, alignment: .leading) + .help("Remove the saved terminal tab and split layout from disk") + .buttonStyle(.bordered) } + .frame(maxWidth: .infinity, alignment: .leading) } - .formStyle(.grouped) } + .formStyle(.grouped) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) } } diff --git a/supacode/Features/Settings/Views/AgentProfileEditorView.swift b/supacode/Features/Settings/Views/AgentProfileEditorView.swift index e2f58d99..d5cfa376 100644 --- a/supacode/Features/Settings/Views/AgentProfileEditorView.swift +++ b/supacode/Features/Settings/Views/AgentProfileEditorView.swift @@ -1,7 +1,7 @@ import ComposableArchitecture import SwiftUI -/// Settings → Agents → native drill-in editor for one profile. The feature +/// Settings → Agents → Profiles → native drill-in editor for one profile. The feature /// owns the alert presentation because its state lives with this destination. struct AgentProfileEditorView: View { @Bindable var store: StoreOf diff --git a/supacode/Features/Settings/Views/AgentProfilesSettingsView.swift b/supacode/Features/Settings/Views/AgentProfilesSettingsView.swift index a673ce9b..ce9112d1 100644 --- a/supacode/Features/Settings/Views/AgentProfilesSettingsView.swift +++ b/supacode/Features/Settings/Views/AgentProfilesSettingsView.swift @@ -14,7 +14,7 @@ struct AgentProfilesSettingsView: View { profileListSection } .formStyle(.grouped) - .navigationTitle("Profiles") + .navigationTitle("Agent Profiles") .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) .task { store.send(.task) } } destination: { editorStore in diff --git a/supacode/Features/Settings/Views/CommandLineToolSettingsView.swift b/supacode/Features/Settings/Views/CommandLineToolSettingsView.swift index dec87af7..877ab4e5 100644 --- a/supacode/Features/Settings/Views/CommandLineToolSettingsView.swift +++ b/supacode/Features/Settings/Views/CommandLineToolSettingsView.swift @@ -1,9 +1,11 @@ import ComposableArchitecture import SwiftUI +/// Settings → Agents → Command Line Tool: install/status for the bundled `prowl` +/// CLI and the socket it reaches the app through. Installation behavior stays in +/// `SettingsFeature`; this view only presents it. struct CommandLineToolSettingsView: View { @Bindable var store: StoreOf - @State private var isAskAgentHelpPresented = false var body: some View { Form { @@ -73,31 +75,15 @@ struct CommandLineToolSettingsView: View { .truncationMode(.middle) } - Text("prowl connects to the running app through this local Unix socket.") - .foregroundStyle(.secondary) - .font(.callout) - } - - Section("Ask Your Agent") { - VStack(alignment: .leading, spacing: 8) { - Text("Give your coding agent a prompt that points it at Prowl's bundled documentation.") - .foregroundStyle(.secondary) - .font(.callout) - Button("Ask Agent About Prowl…") { - isAskAgentHelpPresented = true - } - .help("Copy a prompt that points your coding agent at Prowl's bundled docs") - .buttonStyle(.bordered) - } - .frame(maxWidth: .infinity, alignment: .leading) + Text( + "prowl reaches the running app through this local Unix socket. " + + "Set PROWL_CLI_SOCKET for both Prowl and prowl to use a different path." + ) + .foregroundStyle(.secondary) + .font(.callout) } } .formStyle(.grouped) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) - .sheet(isPresented: $isAskAgentHelpPresented) { - AskAgentHelpView { - isAskAgentHelpPresented = false - } - } } } diff --git a/supacodeTests/AppFeatureSettingsSelectionTests.swift b/supacodeTests/AppFeatureSettingsSelectionTests.swift index 3792b848..371cc26f 100644 --- a/supacodeTests/AppFeatureSettingsSelectionTests.swift +++ b/supacodeTests/AppFeatureSettingsSelectionTests.swift @@ -185,7 +185,8 @@ struct AppFeatureSettingsSelectionTests { #expect(shown.value) } - @Test func selectingAnotherSectionClearsAgentProfileEditorState() async { + @Test(arguments: [SettingsSection.general, .commandLineTool]) + func selectingAnotherSectionClearsAgentProfileEditorState(section: SettingsSection) async { let profile = AgentProfile(name: "Codex", runtime: .codex) var state = AppFeature.State(settings: SettingsFeature.State()) state.settings.selection = .profiles @@ -197,8 +198,8 @@ struct AppFeatureSettingsSelectionTests { AppFeature() } - await store.send(.settings(.setSelection(.general))) { - $0.settings.selection = .general + await store.send(.settings(.setSelection(section))) { + $0.settings.selection = section $0.settings.agentProfiles = nil } } -- 2.51.2 From 868ae6668c2b77e132f8458de6185dcd356ad5f5 Mon Sep 17 00:00:00 2001 From: onevcat Date: Sat, 22 Aug 2026 14:41:15 +0900 Subject: [PATCH 05/11] docs(ai): record CLI reachability status as a D1 preflight item Claude-Session: https://claude.ai/code/session_01YUytym5xEn5FKMhWjSkNkm --- docs-ai/063-agent-workflows/000-plan.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs-ai/063-agent-workflows/000-plan.md b/docs-ai/063-agent-workflows/000-plan.md index ca24f806..ece0377b 100644 --- a/docs-ai/063-agent-workflows/000-plan.md +++ b/docs-ai/063-agent-workflows/000-plan.md @@ -283,6 +283,25 @@ writes. / User / Repo lists, enable toggle, per-workflow "ask for bindings" override, validation status with YAML line errors, Reveal, New Workflow… (template file), Ask your agent to write one (prompt pointing at bundled `docs/` + `skills/`). +- **CLI reachability status** (deferred from C0 #709, see + [002-settings-agents-group.md](002-settings-agents-group.md); lands with D1's preflight): + the Command Line Tool page shows only `ProwlSocket.defaultPath` — a computed value that + honours `PROWL_CLI_SOCKET` — not whether Prowl is actually listening there. Today + `CLISocketServer.start()` (`supacode/CLIService/CLISocketServer.swift`) throws + `CLIServiceError` (`socketAlreadyOwned` when another Prowl instance holds the lock, + `lockFailed`, `permissionFailed`, `bindFailed`, `listenFailed`, `socketPathTooLong`, + `socketCreationFailed`), `supacodeApp.makeCLISocketServer` only logs the failure, and + `isRunning` is private — nothing downstream observes it, so a user whose `prowl` cannot + connect sees a healthy-looking Settings page. D1's CLI dependency banner and the runner + preflight need the same signal, so build it once: a `CLIServiceStatus` + (`listening(path)` / `failed(CLIServiceError, path)` / `stopped`) published by the server + through a small dependency client or the existing `TerminalClient`-style event stream (not + NSNotification), read by `SettingsFeature` for a status row under Command Line Tool › + Connection (tri-state indicator like the install row; failure text names the reason and, + for `socketAlreadyOwned`, the competing instance) and by the workflow preflight + (`install` / `socket` blockers before a run). Tests: reducer tests with a stubbed status, + plus a `CLISocketServer` test that `start()` on an already-owned path surfaces + `socketAlreadyOwned`. ### CLI (per 060's four-layer rule) -- 2.51.2 From 3006b6447d4ed92fe2a938c7ae9cfc1098b3f41c Mon Sep 17 00:00:00 2001 From: onevcat Date: Sat, 22 Aug 2026 14:43:44 +0900 Subject: [PATCH 06/11] docs(ai): plan bundled agent skills distribution (065) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bundle Prowl's official skills into the app, add `prowl skills` for symlink installs into agent skill folders, a Settings › Agents › Skills page, and a shared registry that 063-D1 consumes; move `embed-skills` ownership from 063-D1 to this entry. Claude-Session: https://claude.ai/code/session_01YUytym5xEn5FKMhWjSkNkm --- docs-ai/063-agent-workflows/000-plan.md | 10 +- docs-ai/063-agent-workflows/release-plan.md | 2 +- docs-ai/065-bundled-agent-skills/000-plan.md | 171 +++++++++++++++++++ docs-ai/README.md | 1 + 4 files changed, 179 insertions(+), 5 deletions(-) create mode 100644 docs-ai/065-bundled-agent-skills/000-plan.md diff --git a/docs-ai/063-agent-workflows/000-plan.md b/docs-ai/063-agent-workflows/000-plan.md index 1600f4f4..c912e8fd 100644 --- a/docs-ai/063-agent-workflows/000-plan.md +++ b/docs-ai/063-agent-workflows/000-plan.md @@ -305,9 +305,11 @@ run …` replacement, then removal (see Built-ins). ### Built-ins and distribution -- `Resources/workflows/*.yaml` and `Resources/skills/` are embedded like `docs/` - (`Makefile` `embed-docs` pattern); `skill:` references are materialized into the run - directory so sandboxed agents can read them. +- `Resources/workflows/*.yaml` are embedded like `docs/` (`Makefile` `embed-docs` pattern); + `Resources/skills/` and the bundled-skill registry are owned by + [065-bundled-agent-skills](../065-bundled-agent-skills/000-plan.md) (`embed-skills`, + `ProwlSkills`); `skill:` references resolve through that registry and are materialized + into the run directory so sandboxed agents can read them. - `prowl.adversarial-review`: interactive reviewer in a right split (transparency and user trust outweigh headless precision), `repeat … until outputs.findings.verdict == clean` with `max_rounds`. @@ -394,7 +396,7 @@ attaches hooks through A2's launch boundary. | **B3** | B | A2, 064-S1, B2 | Runner wiring: `WorkflowRunsFeature` effects, observer consumption via `AppFeature`, CLI preflight, `prowl workflow run/status/done/cancel` + contracts. Engine first powered on. | | **C1** | C | B3 | Status center fifth state + run panel + attention triggers + notifications (061 visual verification). Runs become visible. | | **C2** | C | B3 | Start sheet (bindings, suggestion-based profile creation, don't-ask-again, `--skip` equivalent) + entry points (capsule popover, palette, Active Agents context menu). GUI-initiated runs. | -| **D1** | D | B1, C2 | `embed-skills`, `prowl-workflows` authoring skill, `docs/components/workflows.md`, Settings › Workflows page (enable/validate/Reveal/New/Ask-agent/per-workflow auto) added to the Agents group. Distribution and docs. | +| **D1** | D | B1, C2, 065-K1 | `prowl-workflows` authoring skill (registered by adding it to `skills/`; embedding and the registry come from [065](../065-bundled-agent-skills/000-plan.md)), `docs/components/workflows.md`, Settings › Workflows page (enable/validate/Reveal/New/Ask-agent/per-workflow auto) added to the Agents group. Distribution and docs. | | **D2** | D | A2, C2, D1, 064-S3 wave 1 | `prowl.adversarial-review` built-in + reviewer skill + E2E self-verification; the watchdog consumes exact signals (064-S5 part). Proves the engine on a fresh flow before touching shipped behavior. | | **D3** | D | D2 | `prowl.handoff` + `prowl.handoff-checkpoint` built-ins + `handoff.transition`/`handoff.checkpoint` actions; `prowl handoff to\|save` → `HANDOFF_RETIRED` stubs; remove `HandoffHudFeature`, `HandoffCommandHandler`, `HandoffRequestRegistry`; rewrite `docs/components/handoff.md` and the `prowl-cli` skill. Migrate the shipped feature last. | | **V2** | — | — | observe mode (`expect.status` + `agents read` / hook `last_assistant_message`), `on_attention: ask `, fan-out (`count`, `wait all`), run persistence/resume, retention, cross-worktree roles, GUI editor. | diff --git a/docs-ai/063-agent-workflows/release-plan.md b/docs-ai/063-agent-workflows/release-plan.md index de500ae6..35bd4f46 100644 --- a/docs-ai/063-agent-workflows/release-plan.md +++ b/docs-ai/063-agent-workflows/release-plan.md @@ -48,7 +48,7 @@ User-visible result: onevcat's daily CLI-driven orchestration is first-class | 3 | **B3** runner wiring + `workflow run/status/done/cancel` | 063 | A2, S1, B2 | engine powered on | | 4 | **C1** status center + run panel + notifications | 063 | B3 | runs visible | | 5 | **C2** start sheet + entry points (capsule popover, palette, Active Agents) | 063 | B3 | GUI-initiated runs | -| 6 | **D1** `embed-skills`, `prowl-workflows` authoring skill, `docs/components/workflows.md`, Settings › Workflows page | 063 | B1, C2 | custom workflows, agent-assisted authoring | +| 6 | **D1** `prowl-workflows` authoring skill (skills embedding from 065), `docs/components/workflows.md`, Settings › Workflows page | 063 | B1, C2, 065-K1 | custom workflows, agent-assisted authoring | | 7 | **D2** `prowl.adversarial-review` built-in + reviewer skill + E2E; watchdog consumes exact signals (064-S5 part) | 063 + 064 | A2, C2, D1, S3 wave 1 | first built-in workflow | The shipped handoff (HUD + `prowl handoff`) stays untouched in R2. Fallback split if R2 is diff --git a/docs-ai/065-bundled-agent-skills/000-plan.md b/docs-ai/065-bundled-agent-skills/000-plan.md new file mode 100644 index 00000000..d44db8e1 --- /dev/null +++ b/docs-ai/065-bundled-agent-skills/000-plan.md @@ -0,0 +1,171 @@ +# 065 — Bundled Agent Skills: Plan + +| | | +| --- | --- | +| **Status** | Planned | +| **Anchor date** | 2026-08-22 | +| **Primary PRs** | (plan PR), K1–K3 to fill in | +| **Related** | [063-agent-workflows](../063-agent-workflows/000-plan.md) (D1 `skill:` materialization, D1–D3 new skills), [060-prowl-cli-targeting-and-contract-governance](../060-prowl-cli-targeting-and-contract-governance/000-plan.md) (four-layer CLI rule), [013-prowl-cli](../013-prowl-cli/000-plan.md), `docs/components/cli.md`, `skills/prowl-cli/SKILL.md` | + +## Background + +Prowl's official agent skills live only in the source tree: `skills/prowl-cli/SKILL.md` +today, with `prowl-workflows` (063-D1), a reviewer skill (063-D2), and a handoff skill +(063-D3) planned. The shipped app bundles `docs/` (`Makefile` `embed-docs` → +`Contents/Resources/docs`, read through `SupacodePaths.bundledDocsDirectoryPath`) but not +`skills/`, so a user who wants Claude Code or Codex to drive Prowl has to clone the repo or +copy the skill by hand, and nothing keeps that copy current after an app update. The +`.claude/skills/prowl-cli → ../../skills/prowl-cli` symlink in this repo is exactly the +experience users should get: one link, always the version that matches the installed app. + +063 needs the same files inside the bundle to materialize `skill:` references into a run +directory, and its Settings › Workflows page wants an “ask your agent to write one” prompt +that points at bundled `docs/` + `skills/`. C0 (#709) deliberately shipped the Command Line +Tool page without an agent-help entry because the generic “Ask Agent About Prowl” prompt is +user onboarding, not agent enablement; this entry is the missing piece. + +## Goals + +1. **Bundle** the official skills into the app (`Contents/Resources/skills//`) with a + registry that the app, the `prowl` CLI, and the 063 runner all read. +2. **`prowl skills`** — list, install, uninstall, path — links bundled skills into agent skill + folders (user scope: `~/.claude/skills`, `~/.codex/skills`, `~/.agents/skills`; project + scope: the matching folders under a repository root) so updates propagate automatically. +3. **Settings › Agents › Skills** — per-skill rows with per-target install status and + Install/Remove actions, mirroring the Command Line Tool install row (same tri-state idea). +4. **One locator** (`ProwlSkills`) for 063: `skill(id:)` resolves to the bundled directory so + workflows and kickoff prompts can reference skills without any install step. + +**Non-goals (V1):** managing third-party or user-authored skills (this is Prowl's own skills +only, not a general skills manager); copy mode (symlink only — see open questions); silently +installing into an agent without a user action; editing skills in-app; Settings UI for +project scope (CLI only in V1). + +## Design / Approach + +**Build & bundle.** `Makefile` gains `embed-skills` (rsync `skills/` → `Resources/skills/`, +`--delete`, same shape as `embed-docs`), wired into `build-app`, `test`, `archive`, `bench`, +`benchmark-build`; `Resources/skills` becomes a folder reference in `supacode.xcodeproj` +exactly like `Resources/docs`. Text resources only — signing/notarization unchanged. + +**Registry (`ProwlSkills`, in `ProwlCLIShared` = `supacode/CLIService/Shared`).** +`BundledSkill { id (directory name), name, description, directoryURL }` parsed from +`SKILL.md` frontmatter (a minimal YAML subset: `name:`, `description:` including the `>-` +folded block `prowl-cli` already uses — no YAML dependency). `bundled(resourcesURL:)` lists +skills; the app passes `Bundle.main.resourceURL`, the CLI resolves its own executable +(`/usr/local/bin/prowl` → symlink → `Prowl.app/Contents/Resources/prowl-cli/prowl`, so +`../skills` is a sibling); `PROWL_SKILLS_DIR` overrides for SwiftPM dev builds and tests. +Not run from a bundle and no override → `BUNDLE_NOT_FOUND`. + +**Install targets (declarative, verified per runtime).** `SkillInstallTarget { id, +displayName, userDirectory, projectDirectory?, runtimes }`. V1 table — entries marked +*verify* are confirmed (dir, symlink following) by spike S0 before K2 builds on them: + +| Target id | User dir | Project dir | Read by | +| --- | --- | --- | --- | +| `claude` | `~/.claude/skills` | `.claude/skills` | Claude Code | +| `codex` | `~/.codex/skills` | *verify* | Codex | +| `agents` | `~/.agents/skills` | `.agents/skills` | cross-agent convention (agentskills.io); *verify* which installed runtimes honour it | + +Other `AgentProfileRuntime` cases (gemini, copilot, cursor, opencode, amp, droid, …) join the +table as their skill directories are verified; unknown ones stay out rather than guessed. +A user target counts as *detected* when its parent (`~/.claude`, `~/.codex`, `~/.agents`) +exists; undetected targets are listed but never chosen by default. + +**Install semantics.** `install` = `ln -s /skills/ /` (directory +symlink; creates `` if missing). Status mirrors `CLIInstallClient`: +`notInstalled` / `installed(path)` (symlink → this bundle) / `installedDifferentSource(path)` +(symlink elsewhere — e.g. a Debug build in DerivedData — or a real directory) / `broken(path)` +(dangling symlink: the app moved or was removed; offer Repair). `uninstall` refuses anything +that is not a symlink we recognise, like the CLI uninstall does. No admin rights needed. +Project scope: `--scope project` with `--path ` or the cwd's git root; the CLI prints a +note that a committed symlink carries a machine-specific absolute path (git hygiene is the +user's call — see open questions). + +**CLI (per 060's four-layer rule: parser → contract → `docs/components/cli.md` → skill).** +``` +prowl skills list [--json] # skills × targets with status +prowl skills install ... | --all [--target ]... [--scope user|project] [--path ] +prowl skills uninstall ... | --all [--target ]... [--scope user|project] [--path ] +prowl skills path # bundled directory, for scripts and workflows +``` +Plural `skills` matches `agents` and the planned `profiles`. `install` without `--target` +uses all detected user targets; without `--scope` uses `user`. Local-only: never opens the +socket or launches the app (the app need not be running). JSON `schema_version` +`prowl.cli.skills.v1`; errors `SKILL_NOT_FOUND`, `TARGET_NOT_FOUND`, `INSTALL_CONFLICT` +(non-symlink exists), `BUNDLE_NOT_FOUND`. Contract file +`docs-ai/013-prowl-cli/contracts/skills.md`; `prowl-cli` skill gains one line telling an +agent that `prowl skills install prowl-cli` keeps it current. + +**Settings.** `SettingsSection.skills` and `SkillsSettingsView` under the Agents group +(order: Profiles, Skills, Command Line Tool; 063-D1 inserts Workflows after Profiles). +`SkillsFeature` (TCA) owns `skills`, `targets`, `statuses[skill][target]`, `alert`; +`SkillInstallClient` dependency wraps the shared installer (`bundledSkills`, `targets`, +`status`, `install`, `uninstall`) with a temp-directory test value. Rows: name + description, +one status chip per detected target with Install/Remove (Repair for `broken`), Reveal bundled +skill in Finder, Copy path. `AppFeature.setSelection(.skills)` initialises/clears the state +like `.profiles`. The Command Line Tool page stays CLI-only. + +**063 integration.** `embed-skills` and the registry move here from 063-D1; D1 depends on +K1 and uses `ProwlSkills.skill(id:)` to materialize `skill:` references and to build its +“ask your agent” prompt. D1–D3 skills appear in `prowl skills` and Settings by being added to +`skills/`; no per-skill code. + +## Slices + +| Slice | Contents | Depends | +| --- | --- | --- | +| **S0** spike | Verify the target table: directories, symlinked skill directories honoured by Claude Code and Codex, `.agents/skills` readers. Record results in this plan. | — | +| **K1** | `embed-skills`, `Resources/skills` folder reference, `ProwlSkills` registry + frontmatter parser, tests; 063 plan cross-link. | — | +| **K2** | `prowl skills list\|install\|uninstall\|path`, shared installer + status model, contract, `cli.md`, `prowl-cli` skill line, smoke + integration tests (temp dirs, `PROWL_SKILLS_DIR`). | S0, K1 | +| **K3** | Settings › Agents › Skills page, `SkillsFeature` + `SkillInstallClient`, reducer tests, `docs/components/settings.md`. | K2 | + +## Alternatives & decisions + +- **Symlink vs copy** — symlink: one source of truth that follows app updates, and it is + what the CLI install already does. Copy stays an open question for dotfile-sync users. +- **CLI reads the bundle next to itself vs asks the app over the socket** — local: works + with the app closed and adds no protocol surface; `PROWL_SKILLS_DIR` covers dev/tests. +- **Separate Skills page vs a section on Command Line Tool** — separate page: the list + grows to four skills × several targets by 063-D3, and the CLI page should stay about the + CLI. +- **Registry in `ProwlCLIShared` vs app-only** — shared: the CLI and the workflow runner + both need it; Foundation-only, no new dependency. +- **Prowl's skills only vs a general skills manager** — Prowl's only; general managers + (`npx skills`, per-runtime marketplaces) exist and are not this app's job. +- **Naming** — `prowl skills` (plural), consistent with `agents` / `profiles`. + +## Risks + +- A runtime may not follow directory symlinks for skills → S0 verifies before K2; if any V1 + target refuses symlinks, copy mode is promoted from open question to K2 scope. +- Debug builds: links point into DerivedData and show as `installedDifferentSource` in a + Release app (and vice versa). Acceptable; the status text names the other source. +- Runtimes move their skill directories → the table is declarative and small; unknown + runtimes are omitted, never guessed. +- Project-scope symlinks leak absolute paths into a repo if committed → CLI note; no git + mutation by Prowl. + +## Verification + +- Unit: frontmatter parser (plain and `>-` descriptions), status tri-state + `broken` over + temp directories, uninstall refusing real directories, CLI bundle resolution through a + symlinked executable. +- `make test-cli-smoke` (parsing) and `make test-cli-integration` (filesystem round trip in a + temp `PROWL_SKILLS_DIR`, no socket needed); reducer tests for `SkillsFeature`. +- `make check`, `make build-app`; release archive contains `Contents/Resources/skills/`. +- Manual: `prowl skills install prowl-cli`, start Claude Code and Codex in a fresh shell, the + skill is listed and triggers. + +## Open questions + +- Copy mode (`--copy`) in V1 or later? Needed only if S0 finds a symlink-averse runtime or + users sync dotfiles across machines. +- Project scope git hygiene: leave to the user (CLI note) or offer `.git/info/exclude`? +- Should the Command Line Tool install success alert nudge “install the prowl-cli skill”? +- Should 063-D1's Workflows “ask your agent” prompt instruct `prowl skills install` first? +- Settings project-scope UI (per-repository Skills section in Repo Settings) — V2 if asked. + +## Amendments + +(append `- Updated 2026-MM-DD: ... — see [00N-topic.md](00N-topic.md)` lines here) diff --git a/docs-ai/README.md b/docs-ai/README.md index ddc36f52..35e1b899 100644 --- a/docs-ai/README.md +++ b/docs-ai/README.md @@ -119,3 +119,4 @@ agent-facing manual for that). | 062 | [workspace-child-diff](062-workspace-child-diff/000-plan.md) | 2026-08-19 | Per-repository diff for workspace children via unified DiffTarget routing | | 063 | [agent-workflows](063-agent-workflows/000-plan.md) | 2026-08-21 | Agent Workflows: YAML-declared, profile-bound multi-agent orchestration (runner, `prowl workflow` CLI, status center, built-in handoff/adversarial review); successor to 047's fixed handoff flow | | 064 | [agent-completion-signals](064-agent-completion-signals/000-plan.md) | 2026-08-22 | Layered agent signal bus (cooperative / launch-scoped hooks / transcript+process+OSC / heuristic), `prowl agents signal` + `agents wait` with source/confidence, per-runtime hook research | +| 065 | [bundled-agent-skills](065-bundled-agent-skills/000-plan.md) | 2026-08-22 | Bundle Prowl's official agent skills into the app, `prowl skills` install/uninstall via symlinks into agent skill folders, Settings › Agents › Skills page, shared registry for 063 | -- 2.51.2 From 16fbbb8b64ba9ee2994ad33efe652751152c3f18 Mon Sep 17 00:00:00 2001 From: onevcat Date: Sat, 22 Aug 2026 14:44:04 +0900 Subject: [PATCH 07/11] docs(ai): link bundled skills plan pull request Claude-Session: https://claude.ai/code/session_01YUytym5xEn5FKMhWjSkNkm --- docs-ai/065-bundled-agent-skills/000-plan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-ai/065-bundled-agent-skills/000-plan.md b/docs-ai/065-bundled-agent-skills/000-plan.md index d44db8e1..2ba9e69f 100644 --- a/docs-ai/065-bundled-agent-skills/000-plan.md +++ b/docs-ai/065-bundled-agent-skills/000-plan.md @@ -4,7 +4,7 @@ | --- | --- | | **Status** | Planned | | **Anchor date** | 2026-08-22 | -| **Primary PRs** | (plan PR), K1–K3 to fill in | +| **Primary PRs** | #712 (plan), K1–K3 to fill in | | **Related** | [063-agent-workflows](../063-agent-workflows/000-plan.md) (D1 `skill:` materialization, D1–D3 new skills), [060-prowl-cli-targeting-and-contract-governance](../060-prowl-cli-targeting-and-contract-governance/000-plan.md) (four-layer CLI rule), [013-prowl-cli](../013-prowl-cli/000-plan.md), `docs/components/cli.md`, `skills/prowl-cli/SKILL.md` | ## Background -- 2.51.2 From d8f70218b5b28481fd358fd317e33c49ec4baa75 Mon Sep 17 00:00:00 2001 From: onevcat Date: Sat, 22 Aug 2026 15:07:04 +0900 Subject: [PATCH 08/11] docs(ai): record bundled skills plan review decisions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Direct bundle symlinks with a shared SymlinkInstaller, note-only git handling for project scope, frontmatter audience (metadata.prowl-install), an Agent Skills section on the Command Line Tool page instead of a new page, skill-by-target granularity, and R1 placement of S0/K1–K3. Claude-Session: https://claude.ai/code/session_01YUytym5xEn5FKMhWjSkNkm --- docs-ai/063-agent-workflows/release-plan.md | 5 +- docs-ai/065-bundled-agent-skills/000-plan.md | 167 ++++++++++++------- docs-ai/README.md | 2 +- 3 files changed, 108 insertions(+), 66 deletions(-) diff --git a/docs-ai/063-agent-workflows/release-plan.md b/docs-ai/063-agent-workflows/release-plan.md index 35bd4f46..6a7b7071 100644 --- a/docs-ai/063-agent-workflows/release-plan.md +++ b/docs-ai/063-agent-workflows/release-plan.md @@ -30,6 +30,9 @@ user-facing surface may merge before "their" release and stay dormant. Three rel | --- | --- | --- | --- | --- | | 1 | **C0** Settings IA: `Section("Agents")` with Profiles (renamed) + Command Line Tool (from Advanced); no Workflows page yet | 063 | — | CLI install lives with Agents | | 1 | **A1** `prowl create pane` (#699) + anchored split primitive | 063 | 060 | CLI can split | +| 1 | **065-S0/K1** skill-target spike; `embed-skills` + `ProwlSkills` registry | 065 | — | skills ship in the bundle; D1 prerequisite | +| 2 | **065-K2** shared `SymlinkInstaller` + `prowl skills list\|install\|uninstall\|path` | 065 | 065-K1 | one command installs Prowl's skills into agent skill folders | +| 3 | **065-K3** Agent Skills section on Settings › Command Line Tool | 065 | 065-K2 | GUI users install skills without a terminal | | 2 | **A2** profile launch boundary + `create tab\|pane --profile

--prompt -` + `profiles list` | 063 | A1 | CLI launches a profile with a kickoff prompt and gets the pane back | | 2 | **S1** signal bus + `ObservedAgentState` multicast observer + `prowl agents signal` | 064 | — | layer-0 signals for every runtime | | 3 | **S2** `prowl agents wait` (`source`/`confidence`, `--include-screen`) + `agents` `signals` field + skill rubric | 064 | S1 | no hand-written polling; heuristic results are labelled | @@ -37,7 +40,7 @@ user-facing surface may merge before "their" release and stay dormant. Three rel User-visible result: onevcat's daily CLI-driven orchestration is first-class (`create pane --profile --prompt -` → `agents wait` → `send`). Docs: `docs/components/cli.md`, -`agent-detection.md`, `settings.md`, `prowl-cli` skill. Parallelism: C0 ∥ A1, A2 ∥ S1. +`agent-detection.md`, `settings.md`, `prowl-cli` skill. Parallelism: C0 ∥ A1 ∥ 065-K1, A2 ∥ S1. ### R2 — Agent Workflows diff --git a/docs-ai/065-bundled-agent-skills/000-plan.md b/docs-ai/065-bundled-agent-skills/000-plan.md index 2ba9e69f..00318dac 100644 --- a/docs-ai/065-bundled-agent-skills/000-plan.md +++ b/docs-ai/065-bundled-agent-skills/000-plan.md @@ -31,15 +31,17 @@ user onboarding, not agent enablement; this entry is the missing piece. 2. **`prowl skills`** — list, install, uninstall, path — links bundled skills into agent skill folders (user scope: `~/.claude/skills`, `~/.codex/skills`, `~/.agents/skills`; project scope: the matching folders under a repository root) so updates propagate automatically. -3. **Settings › Agents › Skills** — per-skill rows with per-target install status and - Install/Remove actions, mirroring the Command Line Tool install row (same tri-state idea). +3. **Settings › Agents › Command Line Tool › Agent Skills** — a section on the existing + page listing the user-facing skills with per-target install status and Install/Remove + actions, mirroring the CLI install row above it. 4. **One locator** (`ProwlSkills`) for 063: `skill(id:)` resolves to the bundled directory so workflows and kickoff prompts can reference skills without any install step. **Non-goals (V1):** managing third-party or user-authored skills (this is Prowl's own skills -only, not a general skills manager); copy mode (symlink only — see open questions); silently -installing into an agent without a user action; editing skills in-app; Settings UI for -project scope (CLI only in V1). +only, not a general skills manager); copy mode (symlink only — see open questions); writing +into an agent's skill folder without an explicit user action (no auto-linking of new skills +after an update); editing skills in-app; Settings UI for project scope (CLI only in V1); +touching git state in the user's repositories. ## Design / Approach @@ -49,9 +51,12 @@ project scope (CLI only in V1). exactly like `Resources/docs`. Text resources only — signing/notarization unchanged. **Registry (`ProwlSkills`, in `ProwlCLIShared` = `supacode/CLIService/Shared`).** -`BundledSkill { id (directory name), name, description, directoryURL }` parsed from -`SKILL.md` frontmatter (a minimal YAML subset: `name:`, `description:` including the `>-` -folded block `prowl-cli` already uses — no YAML dependency). `bundled(resourcesURL:)` lists +`BundledSkill { id (directory name), name, description, audience, directoryURL }` parsed +from `SKILL.md` frontmatter — a minimal YAML subset (`name:`, `description:` including the +`>-` folded block `prowl-cli` already uses, and a `metadata:` map), no YAML dependency. +`audience` comes from `metadata.prowl-install`: `user` (default when absent — installable +into agent skill folders) or `workflow` (063-D2/D3 role skills: materialized into a run +directory by the runner, never offered for global install). `bundled(resourcesURL:)` lists skills; the app passes `Bundle.main.resourceURL`, the CLI resolves its own executable (`/usr/local/bin/prowl` → symlink → `Prowl.app/Contents/Resources/prowl-cli/prowl`, so `../skills` is a sibling); `PROWL_SKILLS_DIR` overrides for SwiftPM dev builds and tests. @@ -59,80 +64,113 @@ Not run from a bundle and no override → `BUNDLE_NOT_FOUND`. **Install targets (declarative, verified per runtime).** `SkillInstallTarget { id, displayName, userDirectory, projectDirectory?, runtimes }`. V1 table — entries marked -*verify* are confirmed (dir, symlink following) by spike S0 before K2 builds on them: +*verify* are confirmed (directory, symlink following) by spike S0 before K2 builds on them: | Target id | User dir | Project dir | Read by | | --- | --- | --- | --- | -| `claude` | `~/.claude/skills` | `.claude/skills` | Claude Code | -| `codex` | `~/.codex/skills` | *verify* | Codex | +| `claude` | `~/.claude/skills` | `.claude/skills` | Claude Code (follows symlinked skill directories — this repo's `.claude/skills/prowl-cli` link loads) | +| `codex` | `~/.codex/skills` | *verify* | Codex (follows a symlinked skills root; per-directory symlink *verify*) | | `agents` | `~/.agents/skills` | `.agents/skills` | cross-agent convention (agentskills.io); *verify* which installed runtimes honour it | Other `AgentProfileRuntime` cases (gemini, copilot, cursor, opencode, amp, droid, …) join the table as their skill directories are verified; unknown ones stay out rather than guessed. A user target counts as *detected* when its parent (`~/.claude`, `~/.codex`, `~/.agents`) -exists; undetected targets are listed but never chosen by default. - -**Install semantics.** `install` = `ln -s /skills/ /` (directory -symlink; creates `` if missing). Status mirrors `CLIInstallClient`: +exists; undetected targets are listed but never chosen by default, and an explicit +`--target` creates the directory. + +**Install semantics (decided 2026-08-22, see Alternatives).** The link points straight at +the bundle: `ln -s /Contents/Resources/skills/ /` (directory +symlink; creates `` if missing). The symlink install/verify logic is extracted +from `CLIInstallClient` (`supacode/Clients/CLIInstall/CLIInstallClient.swift`) into a shared +`SymlinkInstaller` used by both the CLI install and skills, with one status enum: `notInstalled` / `installed(path)` (symlink → this bundle) / `installedDifferentSource(path)` -(symlink elsewhere — e.g. a Debug build in DerivedData — or a real directory) / `broken(path)` -(dangling symlink: the app moved or was removed; offer Repair). `uninstall` refuses anything -that is not a symlink we recognise, like the CLI uninstall does. No admin rights needed. -Project scope: `--scope project` with `--path ` or the cwd's git root; the CLI prints a -note that a committed symlink carries a machine-specific absolute path (git hygiene is the -user's call — see open questions). +(symlink elsewhere — e.g. a Debug build in DerivedData — or a real directory) / +`broken(path)` (dangling symlink: the app moved or was removed). Conflict rules mirror the +CLI: an existing symlink is replaced (this doubles as Repair for `broken`), a real +file/directory is refused (`INSTALL_CONFLICT`); `uninstall` removes only symlinks. No admin +rights needed. Granularity is skill × target: every link is one explicit action, in the CLI +and in Settings; a skill added by an app update simply shows as Not installed. +Project scope: `--scope project` with `--path ` or the cwd's git root; the CLI prints +one note that the link carries a machine-specific absolute path and that `.git/info/exclude` +is the user's call — Prowl never edits git state. **CLI (per 060's four-layer rule: parser → contract → `docs/components/cli.md` → skill).** ``` -prowl skills list [--json] # skills × targets with status -prowl skills install ... | --all [--target ]... [--scope user|project] [--path

] -prowl skills uninstall ... | --all [--target ]... [--scope user|project] [--path ] -prowl skills path # bundled directory, for scripts and workflows +prowl skills list [--json] # skills × targets with status; workflow-audience skills tagged +prowl skills install [...] [--target ]... [--scope user|project] [--path ] +prowl skills uninstall [...] [--target ]... [--scope user|project] [--path ] +prowl skills path # bundled directory, for scripts and workflows (any audience) ``` -Plural `skills` matches `agents` and the planned `profiles`. `install` without `--target` -uses all detected user targets; without `--scope` uses `user`. Local-only: never opens the -socket or launches the app (the app need not be running). JSON `schema_version` -`prowl.cli.skills.v1`; errors `SKILL_NOT_FOUND`, `TARGET_NOT_FOUND`, `INSTALL_CONFLICT` -(non-symlink exists), `BUNDLE_NOT_FOUND`. Contract file -`docs-ai/013-prowl-cli/contracts/skills.md`; `prowl-cli` skill gains one line telling an -agent that `prowl skills install prowl-cli` keeps it current. - -**Settings.** `SettingsSection.skills` and `SkillsSettingsView` under the Agents group -(order: Profiles, Skills, Command Line Tool; 063-D1 inserts Workflows after Profiles). -`SkillsFeature` (TCA) owns `skills`, `targets`, `statuses[skill][target]`, `alert`; -`SkillInstallClient` dependency wraps the shared installer (`bundledSkills`, `targets`, -`status`, `install`, `uninstall`) with a temp-directory test value. Rows: name + description, -one status chip per detected target with Install/Remove (Repair for `broken`), Reveal bundled -skill in Finder, Copy path. `AppFeature.setSelection(.skills)` initialises/clears the state -like `.profiles`. The Command Line Tool page stays CLI-only. +Plural `skills` matches `agents` and the planned `profiles`. `install` without skills = every +`user`-audience skill; without `--target` = all detected user targets; without `--scope` = +`user`. Naming a `workflow`-audience skill in `install` is an error. Local-only: never opens +the socket or launches the app. JSON `schema_version` `prowl.cli.skills.v1`; errors +`SKILL_NOT_FOUND`, `SKILL_NOT_INSTALLABLE`, `TARGET_NOT_FOUND`, `INSTALL_CONFLICT`, +`BUNDLE_NOT_FOUND`. Contract file `docs-ai/013-prowl-cli/contracts/skills.md`; `prowl-cli` +skill gains one line telling an agent that `prowl skills install prowl-cli` keeps it current. + +**Settings.** No new sidebar item: the Command Line Tool page +(`supacode/Features/Settings/Views/CommandLineToolSettingsView.swift`) gains an **Agent +Skills** section under Installation and Connection, listing `user`-audience skills only +(`workflow`-audience skills belong to 063-D1's Workflows page). Row = name + description + +one status chip per detected target with Install/Remove (Repair for `broken`) + Reveal +bundled skill. State lives in an `AgentSkillsFeature` child of `SettingsFeature`, +initialised when `.commandLineTool` is selected (as `.profiles` initialises `agentProfiles` +in `AppFeature.setSelection`), backed by a `SkillInstallClient` dependency over the shared +installer with a temp-directory test value. Sidebar label stays “Command Line Tool” until +063-D1 reviews the Agents group as a whole. **063 integration.** `embed-skills` and the registry move here from 063-D1; D1 depends on K1 and uses `ProwlSkills.skill(id:)` to materialize `skill:` references and to build its “ask your agent” prompt. D1–D3 skills appear in `prowl skills` and Settings by being added to -`skills/`; no per-skill code. +`skills/` with the right `metadata.prowl-install`; no per-skill code. ## Slices +Release placement: S0 and K1 ship in 063's R1 in parallel with A1 (K1 is small and D1 +depends on it); K2 and K3 follow inside R1 so the R1 user can `prowl skills install`. + | Slice | Contents | Depends | | --- | --- | --- | -| **S0** spike | Verify the target table: directories, symlinked skill directories honoured by Claude Code and Codex, `.agents/skills` readers. Record results in this plan. | — | -| **K1** | `embed-skills`, `Resources/skills` folder reference, `ProwlSkills` registry + frontmatter parser, tests; 063 plan cross-link. | — | -| **K2** | `prowl skills list\|install\|uninstall\|path`, shared installer + status model, contract, `cli.md`, `prowl-cli` skill line, smoke + integration tests (temp dirs, `PROWL_SKILLS_DIR`). | S0, K1 | -| **K3** | Settings › Agents › Skills page, `SkillsFeature` + `SkillInstallClient`, reducer tests, `docs/components/settings.md`. | K2 | +| **S0** spike | Verify the target table: Codex per-directory symlink following and project dir, `.agents/skills` readers among installed runtimes, how each runtime treats a dangling symlink. Use a temporary `CODEX_HOME` / project, never the user's live skill folders. Record results in this plan. | — | +| **K1** | `embed-skills`, `Resources/skills` folder reference, `ProwlSkills` registry + frontmatter parser (incl. `metadata.prowl-install`), tests; 063 plan cross-link. | — | +| **K2** | Shared `SymlinkInstaller` extracted from `CLIInstallClient`, `prowl skills list\|install\|uninstall\|path`, contract, `cli.md`, `prowl-cli` skill line, smoke + integration tests (temp dirs, `PROWL_SKILLS_DIR`). | S0, K1 | +| **K3** | Agent Skills section on the Command Line Tool page, `AgentSkillsFeature` + `SkillInstallClient`, reducer tests, `docs/components/settings.md`. | K2 | ## Alternatives & decisions -- **Symlink vs copy** — symlink: one source of truth that follows app updates, and it is - what the CLI install already does. Copy stays an open question for dotfile-sync users. +Decisions below were taken in the 2026-08-22 plan review (#712): + +- **Link target: bundle directly vs an app-maintained indirection** + (`~/Library/Application Support/com.onevcat.prowl/skills` → current bundle). Direct: its + failure modes (app moved, Debug-vs-Release source, dangling links) are the same set the + `/usr/local/bin/prowl` symlink has carried without trouble; the indirection only buys + self-healing after an app move, at the cost of a launch-time write, a two-hop status check, + and a second mental model. Synced dotfiles (onevcat's `~/.claude/skills` and + `~/.codex/skills` are symlinks into a synced folder) resolve on any Mac with Prowl at + `/Applications`, which is the common case. Indirection stays an upgrade path if moves + break installs in practice. +- **Project scope and git: note only vs auto `.git/info/exclude` vs no project scope.** Note + only: Prowl is a per-user app and project scope is a personal preference, so its git + hygiene is the user's; auto-editing `.git/info/exclude` surprises users and must find the + main repo's `.git` under worktrees. +- **Audience: flat vs frontmatter `metadata.prowl-install` vs directory split.** Frontmatter: + audience is the skill's own property; it keeps one registry root for 063's `skill:` + resolution and lets a bare `prowl skills install` mean “install Prowl's skills”. +- **Settings: dedicated Skills page vs a section on Command Line Tool.** Section: with only + `user`-audience skills shown (two by 063-D3), a page would be thin, the CLI page was + thinner still, and “install the tool → how it connects → teach your agent to use it” + reads as one story. +- **Granularity: skill × target vs per-target toggle with auto-linking of new skills.** + Skill × target: one explicit action per link, same shape as the CLI; auto-linking would + write into agent folders without a user action and fight Debug/Release builds. +- **Symlink vs copy** — symlink; copy stays an open question for users whose runtime + refuses symlinks. - **CLI reads the bundle next to itself vs asks the app over the socket** — local: works with the app closed and adds no protocol surface; `PROWL_SKILLS_DIR` covers dev/tests. -- **Separate Skills page vs a section on Command Line Tool** — separate page: the list - grows to four skills × several targets by 063-D3, and the CLI page should stay about the - CLI. - **Registry in `ProwlCLIShared` vs app-only** — shared: the CLI and the workflow runner both need it; Foundation-only, no new dependency. -- **Prowl's skills only vs a general skills manager** — Prowl's only; general managers - (`npx skills`, per-runtime marketplaces) exist and are not this app's job. +- **Prowl's skills only vs a general skills manager** — Prowl's only. - **Naming** — `prowl skills` (plural), consistent with `agents` / `profiles`. ## Risks @@ -145,26 +183,27 @@ K1 and uses `ProwlSkills.skill(id:)` to materialize `skill:` references and to b runtimes are omitted, never guessed. - Project-scope symlinks leak absolute paths into a repo if committed → CLI note; no git mutation by Prowl. +- Synced skill folders carry the link to other Macs → resolves wherever Prowl is at the + same path; otherwise `broken` until Prowl is installed there. ## Verification -- Unit: frontmatter parser (plain and `>-` descriptions), status tri-state + `broken` over - temp directories, uninstall refusing real directories, CLI bundle resolution through a - symlinked executable. +- Unit: frontmatter parser (plain and `>-` descriptions, `metadata.prowl-install`), status + tri-state + `broken` over temp directories, symlink replacement and real-directory refusal, + CLI bundle resolution through a symlinked executable, `install` refusing + `workflow`-audience skills. - `make test-cli-smoke` (parsing) and `make test-cli-integration` (filesystem round trip in a - temp `PROWL_SKILLS_DIR`, no socket needed); reducer tests for `SkillsFeature`. + temp `PROWL_SKILLS_DIR`, no socket needed); reducer tests for `AgentSkillsFeature`; the + existing CLI install tests keep passing on the extracted `SymlinkInstaller`. - `make check`, `make build-app`; release archive contains `Contents/Resources/skills/`. -- Manual: `prowl skills install prowl-cli`, start Claude Code and Codex in a fresh shell, the - skill is listed and triggers. +- Manual: `prowl skills install`, start Claude Code and Codex in a fresh shell, `prowl-cli` + is listed and triggers; Settings shows the same status as `prowl skills list`. ## Open questions -- Copy mode (`--copy`) in V1 or later? Needed only if S0 finds a symlink-averse runtime or - users sync dotfiles across machines. -- Project scope git hygiene: leave to the user (CLI note) or offer `.git/info/exclude`? -- Should the Command Line Tool install success alert nudge “install the prowl-cli skill”? +- Copy mode (`--copy`) in V1 or later? Needed only if S0 finds a symlink-averse runtime. - Should 063-D1's Workflows “ask your agent” prompt instruct `prowl skills install` first? -- Settings project-scope UI (per-repository Skills section in Repo Settings) — V2 if asked. +- Settings project-scope UI (per-repository section in Repo Settings) — V2 if asked. ## Amendments diff --git a/docs-ai/README.md b/docs-ai/README.md index 35e1b899..9e5095f4 100644 --- a/docs-ai/README.md +++ b/docs-ai/README.md @@ -119,4 +119,4 @@ agent-facing manual for that). | 062 | [workspace-child-diff](062-workspace-child-diff/000-plan.md) | 2026-08-19 | Per-repository diff for workspace children via unified DiffTarget routing | | 063 | [agent-workflows](063-agent-workflows/000-plan.md) | 2026-08-21 | Agent Workflows: YAML-declared, profile-bound multi-agent orchestration (runner, `prowl workflow` CLI, status center, built-in handoff/adversarial review); successor to 047's fixed handoff flow | | 064 | [agent-completion-signals](064-agent-completion-signals/000-plan.md) | 2026-08-22 | Layered agent signal bus (cooperative / launch-scoped hooks / transcript+process+OSC / heuristic), `prowl agents signal` + `agents wait` with source/confidence, per-runtime hook research | -| 065 | [bundled-agent-skills](065-bundled-agent-skills/000-plan.md) | 2026-08-22 | Bundle Prowl's official agent skills into the app, `prowl skills` install/uninstall via symlinks into agent skill folders, Settings › Agents › Skills page, shared registry for 063 | +| 065 | [bundled-agent-skills](065-bundled-agent-skills/000-plan.md) | 2026-08-22 | Bundle Prowl's official agent skills into the app, `prowl skills` install/uninstall via symlinks into agent skill folders, Agent Skills section on Settings › Command Line Tool, shared registry for 063 | -- 2.51.2 From b49219d8af9e0b1bf1f2742dfea49036d15bd96d Mon Sep 17 00:00:00 2001 From: onevcat Date: Sat, 22 Aug 2026 15:07:26 +0900 Subject: [PATCH 09/11] docs(ai): point C0 record at the bundled skills plan Claude-Session: https://claude.ai/code/session_01YUytym5xEn5FKMhWjSkNkm --- docs-ai/063-agent-workflows/002-settings-agents-group.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs-ai/063-agent-workflows/002-settings-agents-group.md b/docs-ai/063-agent-workflows/002-settings-agents-group.md index dd9bf008..68c246da 100644 --- a/docs-ai/063-agent-workflows/002-settings-agents-group.md +++ b/docs-ai/063-agent-workflows/002-settings-agents-group.md @@ -14,7 +14,7 @@ Release R1 starts by establishing the Settings information architecture that lat ## Deviations from plan -- The plan listed an “Ask your agent” entry on the Command Line Tool page. The existing Ask-Agent-About-Prowl prompt (Help menu, sidebar footer) is a user-onboarding prompt, not a CLI one, so it was not duplicated here. What this page should eventually carry is agent *skill* distribution: bundling the official skills (`skills/prowl-cli`, later review/handoff skills) into the app, a `prowl skills` CLI that links them into user or project skill folders, and an install/update UI mirroring the CLI one. That is a separate slice with its own plan; until it lands the page has no agent-help section. +- The plan listed an “Ask your agent” entry on the Command Line Tool page. The existing Ask-Agent-About-Prowl prompt (Help menu, sidebar footer) is a user-onboarding prompt, not a CLI one, so it was not duplicated here. What this page should eventually carry is agent *skill* distribution — bundling the official skills (`skills/prowl-cli`, later workflow skills) into the app, a `prowl skills` CLI that links them into user or project skill folders, and an **Agent Skills** section on this very page mirroring the install row. That is [065-bundled-agent-skills](../065-bundled-agent-skills/000-plan.md) (#712); until its K3 lands the page has no agent-help section. - Slice records in 063 are amendments starting at `002`; `001-action.md` is written when the entry completes (see `docs-ai/README.md`). ## Current state @@ -24,7 +24,7 @@ The selection boundary is `SettingsSection.profiles` / `.commandLineTool` (`supa ## Deferred - Socket listening status: a `CLISocketServer` start failure is only logged (`supacode/App/supacodeApp.swift`), so the page cannot tell “should listen here” from “is listening”. Surfacing `listening / failed(reason)` needs the server state plumbed into `SettingsFeature`; its natural home is the 063-D1 CLI preflight, which needs the same reachability signal. -- Skill distribution (`prowl skills` + Settings UI): separate plan. +- Skill distribution (`prowl skills` + the Agent Skills section here): [065-bundled-agent-skills](../065-bundled-agent-skills/000-plan.md), K3. ## Verification -- 2.51.2 From 410831c9f7c4400596b5ba842faca4e66eac1dfc Mon Sep 17 00:00:00 2001 From: onevcat Date: Sat, 22 Aug 2026 15:10:18 +0900 Subject: [PATCH 10/11] docs(ai): place 065 slices in the shared release plan Claude-Session: https://claude.ai/code/session_01YUytym5xEn5FKMhWjSkNkm --- docs-ai/063-agent-workflows/000-plan.md | 3 ++- docs-ai/063-agent-workflows/release-plan.md | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs-ai/063-agent-workflows/000-plan.md b/docs-ai/063-agent-workflows/000-plan.md index c912e8fd..4a84e4f8 100644 --- a/docs-ai/063-agent-workflows/000-plan.md +++ b/docs-ai/063-agent-workflows/000-plan.md @@ -481,7 +481,8 @@ attaches hooks through A2's launch boundary. when wrong: grace before acting, a nudge that only asks the agent to finish with `done` when it is truly complete, and attention states that never discard a late delivery. - **PR order / releases** (revised 2026-08-22): three releases — R1 = C0, A1, A2, - 064-S1/S2/S3-wave-1 (CLI orchestration + signals); R2 = B1, B2, B3, C1, C2, D1, D2 + 064-S1/S2/S3-wave-1, 065-S0/K1/K2/K3 (CLI orchestration + signals + skill distribution); + R2 = B1, B2, B3, C1, C2, D1, D2 (Agent Workflows); R3 = D3, 064-S3-wave-2/S4, first V2 items (handoff migration). The single source for order and release assignment is [release-plan.md](release-plan.md); the slice tables in 063/064 define contents only. The new Adversarial Review flow diff --git a/docs-ai/063-agent-workflows/release-plan.md b/docs-ai/063-agent-workflows/release-plan.md index 6a7b7071..5221d772 100644 --- a/docs-ai/063-agent-workflows/release-plan.md +++ b/docs-ai/063-agent-workflows/release-plan.md @@ -31,11 +31,11 @@ user-facing surface may merge before "their" release and stay dormant. Three rel | 1 | **C0** Settings IA: `Section("Agents")` with Profiles (renamed) + Command Line Tool (from Advanced); no Workflows page yet | 063 | — | CLI install lives with Agents | | 1 | **A1** `prowl create pane` (#699) + anchored split primitive | 063 | 060 | CLI can split | | 1 | **065-S0/K1** skill-target spike; `embed-skills` + `ProwlSkills` registry | 065 | — | skills ship in the bundle; D1 prerequisite | -| 2 | **065-K2** shared `SymlinkInstaller` + `prowl skills list\|install\|uninstall\|path` | 065 | 065-K1 | one command installs Prowl's skills into agent skill folders | -| 3 | **065-K3** Agent Skills section on Settings › Command Line Tool | 065 | 065-K2 | GUI users install skills without a terminal | | 2 | **A2** profile launch boundary + `create tab\|pane --profile

--prompt -` + `profiles list` | 063 | A1 | CLI launches a profile with a kickoff prompt and gets the pane back | | 2 | **S1** signal bus + `ObservedAgentState` multicast observer + `prowl agents signal` | 064 | — | layer-0 signals for every runtime | +| 2 | **065-K2** shared `SymlinkInstaller` + `prowl skills list\|install\|uninstall\|path` | 065 | 065-K1 | one command installs Prowl's skills into agent skill folders | | 3 | **S2** `prowl agents wait` (`source`/`confidence`, `--include-screen`) + `agents` `signals` field + skill rubric | 064 | S1 | no hand-written polling; heuristic results are labelled | +| 3 | **065-K3** Agent Skills section on Settings › Command Line Tool | 065 | 065-K2 | GUI users install skills without a terminal | | 4 | **S3 wave 1** launch-scoped hooks for tier-A runtimes (Claude Code, Codex `notify`, Copilot, Droid, Qoder, Pi, OMP, OpenCode) + self-check | 064 | A2, S1 | `agents wait` is deterministic for Prowl-launched agents | User-visible result: onevcat's daily CLI-driven orchestration is first-class @@ -80,7 +80,8 @@ cross-worktree roles, GUI editor) and the rest of 064-S5; scheduled by demand. R1: C0 A1 ──► A2 ──┐ S1 ──► S2 ├──► S3w1 └────────┘ -R2: B1 ──► B2 ──► B3 (◄ A2, S1) ──► C1 ──► C2 ──► D1 ──► D2 (◄ S3w1) + 065-S0/K1 ──► 065-K2 ──► 065-K3 +R2: B1 ──► B2 ──► B3 (◄ A2, S1) ──► C1 ──► C2 ──► D1 (◄ 065-K1) ──► D2 (◄ S3w1) R3: D3 (◄ D2) S3w2 (◄ S3w1) S4 (◄ S1) R3+: V2 / S5 rest; delete HANDOFF_RETIRED stubs ``` @@ -90,3 +91,5 @@ R3+: V2 / S5 rest; delete HANDOFF_RETIRED stubs - 2026-08-22 — first version: three releases agreed; `ObservedAgentState` observer moved from 063-B3 to 064-S1; C0 ships without the Workflows page; `prowl agents wait` owned by 064-S2. +- 2026-08-22 — 065 bundled-agent-skills joins R1 (S0/K1 ∥ A1, then K2, K3); `embed-skills` + and the skill registry move from 063-D1 to 065-K1, D1 depends on it. -- 2.51.2 From e13db18d3367c07b93358caae7493db2eebde87e Mon Sep 17 00:00:00 2001 From: onevcat Date: Sat, 22 Aug 2026 15:13:19 +0900 Subject: [PATCH 11/11] feat(settings): move Advanced to the end of the ungrouped sections Claude-Session: https://claude.ai/code/session_01YUytym5xEn5FKMhWjSkNkm --- docs-ai/063-agent-workflows/002-settings-agents-group.md | 2 +- docs/components/settings.md | 2 +- supacode/Features/Settings/Views/SettingsView.swift | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs-ai/063-agent-workflows/002-settings-agents-group.md b/docs-ai/063-agent-workflows/002-settings-agents-group.md index 68c246da..c477ac1f 100644 --- a/docs-ai/063-agent-workflows/002-settings-agents-group.md +++ b/docs-ai/063-agent-workflows/002-settings-agents-group.md @@ -6,7 +6,7 @@ Release R1 starts by establishing the Settings information architecture that lat ## Change -- Settings now reads: flat items (General … Commands) → `Agents` group (`Profiles`, `Command Line Tool`) → `Repositories` group. +- Settings now reads: flat items (General … Commands, Advanced last) → `Agents` group (`Profiles`, `Command Line Tool`) → `Repositories` group. - The profile list keeps the sidebar label `Profiles` and is titled `Agent Profiles`; `openAgentProfilesSettings` and “Manage Agent Profiles…” continue to select it. - The Command Line Tool page owns the existing install/status controls and shows the Unix socket path `prowl` uses to reach the app (`ProwlSocket.defaultPath`, honouring `PROWL_CLI_SOCKET`). The copy describes where `prowl` connects; it does not claim the socket is live. - Advanced keeps analytics, crash reporting, and terminal-layout controls, now split into `Analytics & Crash Reports` and `Terminal Layout` sections. diff --git a/docs/components/settings.md b/docs/components/settings.md index fc7e2ab4..8e1c41fb 100644 --- a/docs/components/settings.md +++ b/docs/components/settings.md @@ -30,9 +30,9 @@ and opens that section's root. | **Shortcuts** | Remap app keyboard shortcuts; view defaults; resolve conflicts. → [keyboard-shortcuts](../reference/keyboard-shortcuts.md) | | **Worktree** | Worktree creation/deletion defaults: prompt on create, fetch before create, base directory, copy ignored/untracked files, automatic local-branch cleanup, merged-worktree action, archived auto-delete period. | | **Updates** | Auto-check toggle, "Check for Updates Now". → [updates](updates.md) | -| **Advanced** | Analytics, crash reports, restore terminal layout on launch (experimental) + clear saved layout. | | **GitHub** | Enable GitHub integration (uses the `gh` CLI). → [github-pull-requests](github-pull-requests.md) | | **Commands** | Global Custom Commands. Enabled commands appear in the window toolbar; each repo can independently hide a Global command. → [custom-actions](custom-actions.md) | +| **Advanced** | Analytics, crash reports, restore terminal layout on launch (experimental) + clear saved layout. | | **Agents → Profiles** | Named launch presets for supported agent runtimes (model, effort, execution mode, tab/split placement, extra arguments, opt-in dedicated home for a separate account) with a live launch preview. List order is the recommendation fallback. → [agent-profiles](agent-profiles.md) | | **Agents → Command Line Tool** | Install/status for the bundled `prowl` CLI and the local socket path it uses to reach the app. → [cli](cli.md) | | **Repositories / Repo Settings** | Per-repository: setup/archive/run scripts, **Custom Commands**, Global-command visibility, **Default Agent Profile**, default base ref & directory, copy-files overrides, open-with app, custom title, icon & color, PR merge strategy, line-diff & PR-state fetching. Reached from the sidebar context menu → "Repo Settings". → [custom-actions](custom-actions.md), [repositories-and-worktrees](repositories-and-worktrees.md) | diff --git a/supacode/Features/Settings/Views/SettingsView.swift b/supacode/Features/Settings/Views/SettingsView.swift index 3fd4a5d5..fb2e94fe 100644 --- a/supacode/Features/Settings/Views/SettingsView.swift +++ b/supacode/Features/Settings/Views/SettingsView.swift @@ -30,12 +30,12 @@ struct SettingsView: View { .tag(SettingsSection.worktree) Label("Updates", systemImage: "arrow.down.circle") .tag(SettingsSection.updates) - Label("Advanced", systemImage: "gearshape.2") - .tag(SettingsSection.advanced) Label("GitHub", systemImage: "arrow.triangle.branch") .tag(SettingsSection.github) Label("Commands", systemImage: "globe") .tag(SettingsSection.customCommands) + Label("Advanced", systemImage: "gearshape.2") + .tag(SettingsSection.advanced) Section("Agents") { Label("Profiles", systemImage: "person.crop.circle")