Skip to content

Add multiple user-defined scripts per repository#246

Merged
sbertix merged 21 commits intomainfrom
sbertix/multiple-scripts
Apr 15, 2026
Merged

Add multiple user-defined scripts per repository#246
sbertix merged 21 commits intomainfrom
sbertix/multiple-scripts

Conversation

@sbertix
Copy link
Copy Markdown
Collaborator

@sbertix sbertix commented Apr 15, 2026

Summary

  • Replace the single runScript field with an ordered scripts: [ScriptDefinition] array, allowing users to configure multiple on-demand scripts (run, test, deploy, lint, format, custom) per repository.
  • Add a split-button toolbar control: primary button runs the default .run script, chevron dropdown lists all scripts with run/stop actions.
  • Integrate scripts into the command palette with run/stop items and keyboard shortcut hints.
  • Add a dedicated Scripts settings sub-page under each repository with add/remove/reorder support.
  • Show color-cycling sidebar indicators when multiple scripts run concurrently.
  • Backward-compatible serialization: legacy runScript JSON auto-migrates on decode; runScript is derived on encode so older clients still work. Lossy decoding gracefully drops unknown future ScriptKind values.

Closes #145
Closes #156

Test plan

  • Existing worktrees with runScript configured auto-migrate to a .run-kind ScriptDefinition
  • Adding/removing/reordering scripts persists correctly
  • Duplicate predefined kinds are rejected; multiple custom scripts are allowed
  • Running a script tracks per-definition state; duplicate runs are silently prevented
  • Script completion cleans up tracking state; failure shows alert with correct metadata
  • Cross-repository sidebar indicators fall back to green when script definitions differ
  • Cmd+. stops only .run-kind scripts; individual scripts stoppable via dropdown/palette
  • Unknown ScriptKind values in JSON drop only that entry, not the entire array
  • Round-trip encode/decode preserves runScript for backward compatibility

sbertix added 14 commits April 15, 2026 11:22
Introduce the foundational data model for multiple running scripts:

- ScriptKind enum with predefined types (run, debug, test, deploy,
  custom), each carrying default icon, color, and name.
- ScriptDefinition struct with id, kind, name, systemImage, tintColor,
  and command fields.
- Move TerminalTabTintColor to SupacodeSettingsShared and extend with
  blue, purple, yellow, and teal cases for new script types.
- Refactor BlockingScriptKind: replace .run with .script(ScriptDefinition)
  to support multiple concurrent user-defined scripts while keeping
  .archive and .delete as lifecycle-bound cases.
- Add scripts and selectedScriptID fields to RepositorySettings with
  backward-compatible migration from the legacy runScript field.
- Update all downstream switch sites, terminal state tracking, and tests.
Register testScript (Cmd+Shift+U), debugScript (Cmd+Shift+Y), and
deployScript (Cmd+Shift+D) in AppShortcutID with stable keys, display
names, and Ghostty unbind support.

Add corresponding menu items in WorktreeCommands and wire focused
value actions through WorktreeDetailView. Actions are currently nil
placeholders — they will be connected to AppFeature in a later commit.
Split repository settings into General and Scripts sub-sections via
expandable DisclosureGroup in the sidebar. The Scripts section shows a
list-based editor where each row has a ScriptKind picker, name field,
and monospaced command field with add/remove/reorder support.

Remove the old single "Run Script" ScriptSection from the General
settings — lifecycle scripts (setup, archive, delete) stay as-is.

Add reducer tests for addScript, removeScripts, and moveScripts
actions covering edge cases (remove middle, move to end, move to
beginning).
Replace RunScriptToolbarButton with ScriptSplitButton: primary button
runs the selected script, chevron dropdown lists all scripts with
per-type icons and run/stop per-script. Cmd+. only stops .run kind.

Rewrite AppFeature script state: replace selectedRunScript/runScriptDraft
with scripts array and selectedScriptID. Wire testScript/debugScript/
deployScript actions to run the first matching script kind.

Add command palette entries: "Run: <name>" and "Stop: <name>" generated
dynamically from repository scripts. Selected script shows Cmd+R badge.

Replace runScriptWorktreeIDs with runningScriptsByWorktreeID dictionary
for per-definition-ID tracking. Remove RunScriptPromptView — scripts
are now configured via Settings.
Replace the single-color boolean PingDot with MultiColorPingDot that
cycles through tint colors of all running script types per worktree.
Uses TimelineView for smooth color transitions and falls back to a
static dot when accessibilityReduceMotion is enabled.

Add scriptTintColorByID cache to RepositoriesFeature.State for
efficient color lookup without passing full ScriptDefinition arrays
through the view hierarchy. Cache is maintained alongside
runningScriptsByWorktreeID on script start, completion, and pruning.
- Add custom encode(to:) deriving runScript from first .run script
  for backward compatibility with older app versions.
- Guard against running the same script definition twice concurrently.
- Navigate to repositoryScripts settings (not General) when no scripts
  are configured and user presses Cmd+R.
- Use try? for scripts decode so unknown ScriptKind values from future
  versions fall back gracefully instead of crashing.
- Remove selectedScriptID entirely — primary toolbar button always
  runs the first .run-kind script, matching the "Open In" pattern.
- Enforce at most one script per predefined kind in settings (only
  .custom allows duplicates).
- Add Codable migration tests: legacy decode, dual-key decode,
  encode round-trip, and unknown-kind resilience.
Add .lint and .format cases to ScriptKind with dedicated SF Symbols
and colors. Add displayName computed property to ScriptDefinition:
predefined types use their kind name, custom types use user name.

Lock script kind at creation: the + button opens a Menu showing only
unused predefined kinds plus always-available custom. Kind picker
replaced with static icon in script rows. Uniqueness enforced at
insertion in addScript(ScriptKind). Move TerminalTabTintColor.color
to shared module so SupacodeSettingsFeature can access it.

Add lintScript/formatScript keyboard shortcuts (Cmd+Shift+L/F),
menu items, and focused value wiring.
Remove debug script kind. Add resolvedSystemImage/resolvedTintColor
to ScriptDefinition so non-custom scripts always derive visuals from
ScriptKind defaults rather than persisted values.

Add Image.tintedSymbol helper for colored SF Symbols in macOS menus
(auto-resolves .fill variants via AppKit palette colors). Use tinted
icons in toolbar script dropdown, plain icons in menu bar.

Hide toolbar dropdown chevron when only a .run script is configured.
Fix DisclosureGroup: auto-expands on selection, allows manual collapse.
Navigate to Scripts settings tab (not General) from toolbar and Cmd+R.

Move lifecycle scripts to Scripts tab. Remove non-run/stop keyboard
shortcuts entirely (deferred to future iteration). Extend Makefile
and swiftlint to cover SupacodeSettingsShared/SupacodeSettingsFeature.
- Remove `scriptTintColorByID` side-cache from RepositoriesFeature;
  resolve colors from current script definitions via environment.
- Use `displayName` in BlockingScriptKind.tabTitle and settings header.
- Encode `runScript` as empty string when no .run scripts exist.
- Distinguish absent vs corrupted `scripts` key in lossy decoder.
- Document `runScript` as legacy backward-compat field.
- Extract duplicated `shortcutDisplay` into shared free function.
- Add test for encode fallback with no .run-kind script.
- Update RepositorySettingsKeyTests to use setupScript for round-trips.
- Fix sidebar indicator disappearing for scripts running in non-selected
  repositories by falling back to .green when script ID lookup fails
- Refactor .binding case to reuse persistAndNotify, removing duplication
- Extract scriptButton helper in ScriptSplitButton to DRY three branches
- Extract LifecycleScriptSection in RepositoryScriptsSettingsView
- Make runScript property private(set) to prevent accidental direct mutation
- Clarify stopRunScripts intent with expanded doc comments
- Pre-compute scriptsByID dictionary once in environment instead of
  rebuilding per sidebar row in runningScriptColors
- Add test verifying duplicate runNamedScript is silently rejected
- Add trailing dots to help text strings for convention consistency
@sbertix sbertix changed the title Multiple user-defined scripts per repository Add multiple user-defined scripts per repository Apr 15, 2026
@tuist
Copy link
Copy Markdown

tuist bot commented Apr 15, 2026

🛠️ Tuist Run Report 🛠️

Builds 🔨

Scheme Status Duration Commit
supacode 40.6s c892710fe

sbertix added 7 commits April 15, 2026 19:36
Show an alert before removing a user-defined script in repository
settings. Also extract SettingsView subviews to fix type-checker
timeout caused by the new @presents alert state.
- Extract duplicate isExpanded Binding to local let in SettingsView
- Update toolbar placeholder to match live ScriptMenu (play instead of play.fill, Label instead of HStack)
- Guard against empty shortcut display in resolveShortcutDisplay
- Use fallback label in ScriptMenu when shortcut resolves to empty
- Use stroke-only stop icon consistently (stop instead of stop.fill)
- Make Divider conditional on non-empty scripts in ScriptMenu dropdown
- Fix doc comments for ScriptMenu and primaryScript
@sbertix sbertix enabled auto-merge (squash) April 15, 2026 19:36
@sbertix sbertix merged commit 1f38a0c into main Apr 15, 2026
2 checks passed
@sbertix sbertix deleted the sbertix/multiple-scripts branch April 15, 2026 19:40
Whoaa512 added a commit to Whoaa512/supacode that referenced this pull request Apr 16, 2026
* fix/unfocused-split-opacity: (24 commits)
  add xcbeautify to mise.toml so local builds work without separate install
  install dev build as supacode-dev.app to coexist with homebrew install
  ignore legacy Ghostty build outputs
  work around Xcode 26.4 local builds
  Respect unfocused-split-opacity from Ghostty config
  Add multiple user-defined scripts per repository (supabitapp#246)
  Respect ghostty split-preserve-zoom config when cycling splits (supabitapp#241)
  Improve open worktree UX and rename openFinder to openWorktree (supabitapp#247)
  Add RubyMine editor support (supabitapp#248)
  fix(ci): skip tuist auth on fork pull requests
  stuff
  Align trailing comma tooling
  cache
  Split dependency inspection CI
  Switch Tuist CI auth to OIDC
  simplify build output formatting
  simplify app tuist dependencies
  simplify tuist package linkage
  restore required tuist package overrides
  remove package framework search paths
  ...

# Conflicts:
#	supacode/Features/Repositories/Views/WorktreeRow.swift
#	supacode/Features/Repositories/Views/WorktreeRowsView.swift
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add an action function similar to the Codex app multiple run scripts

1 participant