native macOS codings agent orchestrator
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #234 from onevcat/feat/auto-tab-icon-detect

feat(terminal): auto-detect tab icon from running command

authored by

Wei Wang and committed by
GitHub
ce37503d 942a5609

+1511 -17
+21 -7
supacode/App/supacodeApp.swift
··· 245 245 ghosttyShortcuts: shortcuts, 246 246 commandKeyObserver: keyObserver 247 247 ) 248 + #if DEBUG 249 + DebugWindowManager.shared.configure(store: appStore) 250 + #endif 248 251 } 249 252 250 253 private static func makeTargetResolver( ··· 622 625 .environment(ghosttyShortcuts) 623 626 .environment(commandKeyObserver) 624 627 .commands { 625 - WorktreeCommands(store: store) 626 - SidebarCommands(store: store) 627 - TerminalCommands(ghosttyShortcuts: ghosttyShortcuts) 628 - WindowCommands( 629 - ghosttyShortcuts: ghosttyShortcuts, 630 - resolvedKeybindings: store.resolvedKeybindings 631 - ) 628 + // Grouped to keep `commands` under SwiftUI's CommandsBuilder 629 + // tuple-arity limit when `#if DEBUG` adds the Debug menu below. 630 + Group { 631 + WorktreeCommands(store: store) 632 + SidebarCommands(store: store) 633 + TerminalCommands(ghosttyShortcuts: ghosttyShortcuts) 634 + WindowCommands( 635 + ghosttyShortcuts: ghosttyShortcuts, 636 + resolvedKeybindings: store.resolvedKeybindings 637 + ) 638 + } 632 639 CommandGroup(after: .textEditing) { 633 640 Button("Command Palette") { 634 641 store.send(.commandPalette(.togglePresented)) ··· 662 669 } 663 670 .help("Install the prowl command line tool to /usr/local/bin") 664 671 } 672 + #if DEBUG 673 + CommandMenu("Debug") { 674 + Button("Icon Catalog") { 675 + DebugWindowManager.shared.show() 676 + } 677 + } 678 + #endif 665 679 CommandGroup(replacing: .help) { 666 680 Button("Homepage", systemImage: "house") { 667 681 if let url = URL(string: "https://prowl.onev.cat/") {
+1
supacode/Assets.xcassets/CommandIcons/AWS.imageset/AWS.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Amazon Web Services</title><path d="M6.763 10.036c0 .296.032.535.088.71.064.176.144.368.256.576.04.063.056.127.056.183 0 .08-.048.16-.152.24l-.503.335a.383.383 0 0 1-.208.072c-.08 0-.16-.04-.239-.112a2.47 2.47 0 0 1-.287-.375 6.18 6.18 0 0 1-.248-.471c-.622.734-1.405 1.101-2.347 1.101-.67 0-1.205-.191-1.596-.574-.391-.384-.59-.894-.59-1.533 0-.678.239-1.23.726-1.644.487-.415 1.133-.623 1.955-.623.272 0 .551.024.846.064.296.04.6.104.918.176v-.583c0-.607-.127-1.03-.375-1.277-.255-.248-.686-.367-1.3-.367-.28 0-.568.031-.863.103-.295.072-.583.16-.862.272a2.287 2.287 0 0 1-.28.104.488.488 0 0 1-.127.023c-.112 0-.168-.08-.168-.247v-.391c0-.128.016-.224.056-.28a.597.597 0 0 1 .224-.167c.279-.144.614-.264 1.005-.36a4.84 4.84 0 0 1 1.246-.151c.95 0 1.644.216 2.091.647.439.43.662 1.085.662 1.963v2.586zm-3.24 1.214c.263 0 .534-.048.822-.144.287-.096.543-.271.758-.51.128-.152.224-.32.272-.512.047-.191.08-.423.08-.694v-.335a6.66 6.66 0 0 0-.735-.136 6.02 6.02 0 0 0-.75-.048c-.535 0-.926.104-1.19.32-.263.215-.39.518-.39.917 0 .375.095.655.295.846.191.2.47.296.838.296zm6.41.862c-.144 0-.24-.024-.304-.08-.064-.048-.12-.16-.168-.311L7.586 5.55a1.398 1.398 0 0 1-.072-.32c0-.128.064-.2.191-.2h.783c.151 0 .255.025.31.08.065.048.113.16.16.312l1.342 5.284 1.245-5.284c.04-.16.088-.264.151-.312a.549.549 0 0 1 .32-.08h.638c.152 0 .256.025.32.08.063.048.12.16.151.312l1.261 5.348 1.381-5.348c.048-.16.104-.264.16-.312a.52.52 0 0 1 .311-.08h.743c.127 0 .2.065.2.2 0 .04-.009.08-.017.128a1.137 1.137 0 0 1-.056.2l-1.923 6.17c-.048.16-.104.263-.168.311a.51.51 0 0 1-.303.08h-.687c-.151 0-.255-.024-.32-.08-.063-.056-.119-.16-.15-.32l-1.238-5.148-1.23 5.14c-.04.16-.087.264-.15.32-.065.056-.177.08-.32.08zm10.256.215c-.415 0-.83-.048-1.229-.143-.399-.096-.71-.2-.918-.32-.128-.071-.215-.151-.247-.223a.563.563 0 0 1-.048-.224v-.407c0-.167.064-.247.183-.247.048 0 .096.008.144.024.048.016.12.048.2.08.271.12.566.215.878.279.319.064.63.096.95.096.502 0 .894-.088 1.165-.264a.86.86 0 0 0 .415-.758.777.777 0 0 0-.215-.559c-.144-.151-.416-.287-.807-.415l-1.157-.36c-.583-.183-1.014-.454-1.277-.813a1.902 1.902 0 0 1-.4-1.158c0-.335.073-.63.216-.886.144-.255.335-.479.575-.654.24-.184.51-.32.83-.415.32-.096.655-.136 1.006-.136.175 0 .359.008.535.032.183.024.35.056.518.088.16.04.312.08.455.127.144.048.256.096.336.144a.69.69 0 0 1 .24.2.43.43 0 0 1 .071.263v.375c0 .168-.064.256-.184.256a.83.83 0 0 1-.303-.096 3.652 3.652 0 0 0-1.532-.311c-.455 0-.815.071-1.062.223-.248.152-.375.383-.375.71 0 .224.08.416.24.567.159.152.454.304.877.44l1.134.358c.574.184.99.44 1.237.767.247.327.367.702.367 1.117 0 .343-.072.655-.207.926-.144.272-.336.511-.583.703-.248.2-.543.343-.886.447-.36.111-.734.167-1.142.167zM21.698 16.207c-2.626 1.94-6.442 2.969-9.722 2.969-4.598 0-8.74-1.7-11.87-4.526-.247-.223-.024-.527.272-.351 3.384 1.963 7.559 3.153 11.877 3.153 2.914 0 6.114-.607 9.06-1.852.439-.2.814.287.383.607zM22.792 14.961c-.336-.43-2.22-.207-3.074-.103-.255.032-.295-.192-.063-.36 1.5-1.053 3.967-.75 4.254-.399.287.36-.08 2.826-1.485 4.007-.215.184-.423.088-.327-.151.32-.79 1.03-2.57.695-2.994z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/AWS.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "AWS.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Amp.imageset/Amp.svg
··· 1 + <svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Amp</title><path d="M15.087 23.18L12.03 24l-2.097-7.823-5.738 5.738-2.251-2.251 5.718-5.719-7.769-2.082.82-3.057 11.294 3.08 3.08 11.295z"></path><path d="M19.505 18.762l-3.057.82-2.564-9.573-9.572-2.564.819-3.057 11.295 3.079 3.08 11.295z"></path><path d="M23.893 14.374l-3.057.82-2.565-9.572L8.7 3.057 9.52 0l11.295 3.08 3.079 11.294z"></path></svg>
+16
supacode/Assets.xcassets/CommandIcons/Amp.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Amp.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Azure.imageset/Azure.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Microsoft Azure</title><path d="M22.379 23.343a1.62 1.62 0 0 0 1.536-2.14v.002L17.35 1.76A1.62 1.62 0 0 0 15.816.657H8.184A1.62 1.62 0 0 0 6.65 1.76L.086 21.204a1.62 1.62 0 0 0 1.536 2.139h4.741a1.62 1.62 0 0 0 1.535-1.103l.977-2.892 4.947 3.675c.28.208.618.32.966.32m-3.084-12.531 3.624 10.739a.54.54 0 0 1-.51.713v-.001h-.03a.54.54 0 0 1-.322-.106l-9.287-6.9h4.853m6.313 7.006c.116-.326.13-.694.007-1.058L9.79 1.76a1.722 1.722 0 0 0-.007-.02h6.034a.54.54 0 0 1 .512.366l6.562 19.445a.54.54 0 0 1-.338.684"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Azure.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Azure.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Bun.imageset/Bun.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Bun</title><path d="M12 22.596c6.628 0 12-4.338 12-9.688 0-3.318-2.057-6.248-5.219-7.986-1.286-.715-2.297-1.357-3.139-1.89C14.058 2.025 13.08 1.404 12 1.404c-1.097 0-2.334.785-3.966 1.821a49.92 49.92 0 0 1-2.816 1.697C2.057 6.66 0 9.59 0 12.908c0 5.35 5.372 9.687 12 9.687v.001ZM10.599 4.715c.334-.759.503-1.58.498-2.409 0-.145.202-.187.23-.029.658 2.783-.902 4.162-2.057 4.624-.124.048-.199-.121-.103-.209a5.763 5.763 0 0 0 1.432-1.977Zm2.058-.102a5.82 5.82 0 0 0-.782-2.306v-.016c-.069-.123.086-.263.185-.172 1.962 2.111 1.307 4.067.556 5.051-.082.103-.23-.003-.189-.126a5.85 5.85 0 0 0 .23-2.431Zm1.776-.561a5.727 5.727 0 0 0-1.612-1.806v-.014c-.112-.085-.024-.274.114-.218 2.595 1.087 2.774 3.18 2.459 4.407a.116.116 0 0 1-.049.071.11.11 0 0 1-.153-.026.122.122 0 0 1-.022-.083 5.891 5.891 0 0 0-.737-2.331Zm-5.087.561c-.617.546-1.282.76-2.063 1-.117 0-.195-.078-.156-.181 1.752-.909 2.376-1.649 2.999-2.778 0 0 .155-.118.188.085 0 .304-.349 1.329-.968 1.874Zm4.945 11.237a2.957 2.957 0 0 1-.937 1.553c-.346.346-.8.565-1.286.62a2.178 2.178 0 0 1-1.327-.62 2.955 2.955 0 0 1-.925-1.553.244.244 0 0 1 .064-.198.234.234 0 0 1 .193-.069h3.965a.226.226 0 0 1 .19.07c.05.053.073.125.063.197Zm-5.458-2.176a1.862 1.862 0 0 1-2.384-.245 1.98 1.98 0 0 1-.233-2.447c.207-.319.503-.566.848-.713a1.84 1.84 0 0 1 1.092-.11c.366.075.703.261.967.531a1.98 1.98 0 0 1 .408 2.114 1.931 1.931 0 0 1-.698.869v.001Zm8.495.005a1.86 1.86 0 0 1-2.381-.253 1.964 1.964 0 0 1-.547-1.366c0-.384.11-.76.32-1.079.207-.319.503-.567.849-.713a1.844 1.844 0 0 1 1.093-.108c.367.076.704.262.968.534a1.98 1.98 0 0 1 .4 2.117 1.932 1.932 0 0 1-.702.868Z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Bun.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Bun.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/ClaudeCode.imageset/ClaudeCode.svg
··· 1 + <svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Claude</title><path d="M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z"></path></svg>
+16
supacode/Assets.xcassets/CommandIcons/ClaudeCode.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "ClaudeCode.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Codex.imageset/Codex.svg
··· 1 + <svg xmlns="http://www.w3.org/2000/svg" viewBox="1 1 18 18" fill="currentColor"><path fill-rule="evenodd" d="M9.002 1.75c1.114 0 2.134.405 2.922 1.072q.392-.072.806-.073a4.523 4.523 0 0 1 4.447 5.326 4.524 4.524 0 0 1-1.922 7.18 4.52 4.52 0 0 1-4.256 2.995 4.5 4.5 0 0 1-2.923-1.073q-.391.072-.805.074a4.523 4.523 0 0 1-4.448-5.327 4.5 4.5 0 0 1-1.066-2.69l-.007-.233a4.53 4.53 0 0 1 2.994-4.258A4.525 4.525 0 0 1 9.002 1.75zM13.333 11.418a.665.665 0 0 1 0 1.33h-2.5a.665.665 0 1 1 0-1.33zM6.741 7.347a.665.665 0 0 1 .912.228l1.25 2.083a.67.67 0 0 1 0 .685l-1.25 2.083a.666.666 0 0 1-1.14-.685L7.557 10 6.513 8.259a.665.665 0 0 1 .228-.912z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Codex.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Codex.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+6
supacode/Assets.xcassets/CommandIcons/Contents.json
··· 1 + { 2 + "info" : { 3 + "author" : "xcode", 4 + "version" : 1 5 + } 6 + }
+16
supacode/Assets.xcassets/CommandIcons/Curl.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Curl.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Curl.imageset/Curl.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>curl</title><path d="M.803 14.8169c0-.5342.433-.9665.9665-.9665.5335 0 .9665.4323.9665.9665 0 .5335-.433.9657-.9665.9657-.5335 0-.9666-.4322-.9666-.9657m2.736 0c0-.1963-.0532-.376-.1119-.5525-.2344-.7024-.876-1.2169-1.6575-1.2169-.1249 0-.2344.0465-.3524.0708C.6149 13.2865 0 13.9646 0 14.817c0 .9764.7923 1.7694 1.7695 1.7694.9772 0 1.7694-.793 1.7694-1.7694m-1.7694-7.149c.5335 0 .9665.433.9665.9665 0 .5335-.433.9665-.9665.9665-.5343 0-.9666-.433-.9666-.9665 0-.5335.4323-.9665.9666-.9665m0 2.7359c.9772 0 1.7694-.7923 1.7694-1.7694 0-.1956-.0532-.376-.1119-.5525-.2344-.7024-.8767-1.2169-1.6575-1.2169-.1249 0-.2344.0465-.3524.0716C.6149 7.104 0 7.782 0 8.6344c0 .9771.7923 1.7694 1.7695 1.7694m13.221-5.694c-.5342 0-.9665-.433-.9665-.9664a.966.966 0 01.9666-.9665c.5335 0 .9658.4322.9658.9665 0 .5334-.4323.9664-.9658.9664m-9.6 16.5133c-.5335 0-.9666-.433-.9666-.9665 0-.5342.433-.9665.9666-.9665a.966.966 0 01.9665.9665c0 .5335-.4323.9665-.9665.9665m9.6-19.2491c-.978 0-1.7695.7922-1.7695 1.7694 0 .2085.0525.4025.1187.5882L5.039 18.5581c-.803.1681-1.4179.8462-1.4179 1.6985 0 .9772.7923 1.7694 1.7695 1.7694.9772 0 1.7694-.7922 1.7694-1.7694 0-.1963-.0525-.3759-.111-.5525l8.3427-14.2728c.7778-.1865 1.3683-.8531 1.3683-1.688 0-.977-.793-1.7693-1.7694-1.7693m7.24 2.7359c-.5343 0-.9666-.433-.9666-.9665a.966.966 0 01.9665-.9665c.5335 0 .9666.4322.9666.9665 0 .5334-.433.9665-.9666.9665M12.6313 21.223c-.5343 0-.9665-.433-.9665-.9665a.966.966 0 01.9665-.9665c.5335 0 .9658.4323.9658.9665 0 .5335-.4323.9665-.9658.9665M22.2305 1.974c-.9772 0-1.7694.7922-1.7694 1.7694 0 .2085.0525.4025.1187.5882l-8.3009 14.2265c-.8021.1681-1.417.8462-1.417 1.6985 0 .9772.7922 1.7694 1.7694 1.7694.9764 0 1.7687-.7922 1.7687-1.7694 0-.1963-.0525-.3759-.1111-.5525l8.3427-14.2728C23.4094 5.2448 24 4.5782 24 3.7433c0-.977-.7923-1.7693-1.7695-1.7693"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Deno.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Deno.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Deno.imageset/Deno.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Deno</title><path d="M1.105 18.02A11.9 11.9 0 0 1 0 12.985q0-.698.078-1.376a12 12 0 0 1 .231-1.34A12 12 0 0 1 4.025 4.02a12 12 0 0 1 5.46-2.771 12 12 0 0 1 3.428-.23c1.452.112 2.825.477 4.077 1.05a12 12 0 0 1 2.78 1.774 12.02 12.02 0 0 1 4.053 7.078A12 12 0 0 1 24 12.985q0 .454-.036.914a12 12 0 0 1-.728 3.305 12 12 0 0 1-2.38 3.875c-1.33 1.357-3.02 1.962-4.43 1.936a4.4 4.4 0 0 1-2.724-1.024c-.99-.853-1.391-1.83-1.53-2.919a5 5 0 0 1 .128-1.518c.105-.38.37-1.116.76-1.437-.455-.197-1.04-.624-1.226-.829-.045-.05-.04-.13 0-.183a.155.155 0 0 1 .177-.053c.392.134.869.267 1.372.35.66.111 1.484.25 2.317.292 2.03.1 4.153-.813 4.812-2.627s.403-3.609-1.96-4.685-3.454-2.356-5.363-3.128c-1.247-.505-2.636-.205-4.06.582-3.838 2.121-7.277 8.822-5.69 15.032a.191.191 0 0 1-.315.19 12 12 0 0 1-1.25-1.634 12 12 0 0 1-.769-1.404M11.57 6.087c.649-.051 1.214.501 1.31 1.236.13.979-.228 1.99-1.41 2.013-1.01.02-1.315-.997-1.248-1.614.066-.616.574-1.575 1.35-1.635"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Docker.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Docker.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Docker.imageset/Docker.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Docker</title><path d="M13.983 11.078h2.119a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.119a.185.185 0 00-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 00.186-.186V3.574a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 00.186-.186V6.29a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.887c0 .102.082.185.185.186m-2.93 0h2.12a.186.186 0 00.184-.186V6.29a.185.185 0 00-.185-.185H8.1a.185.185 0 00-.185.185v1.887c0 .102.083.185.185.186m-2.964 0h2.119a.186.186 0 00.185-.186V6.29a.185.185 0 00-.185-.185H5.136a.186.186 0 00-.186.185v1.887c0 .102.084.185.186.186m5.893 2.715h2.118a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 00.185-.185V9.006a.185.185 0 00-.184-.186h-2.12a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.082.185.185.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51-.338.001-.676.03-1.01.087-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.751.751 0 00-.75.748 11.376 11.376 0 00.692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137.983.003 1.963-.086 2.93-.266a12.248 12.248 0 003.823-1.389c.98-.567 1.86-1.288 2.61-2.136 1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288Z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Gemini.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Gemini.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Gemini.imageset/Gemini.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Google Gemini</title><path d="M11.04 19.32Q12 21.51 12 24q0-2.49.93-4.68.96-2.19 2.58-3.81t3.81-2.55Q21.51 12 24 12q-2.49 0-4.68-.93a12.3 12.3 0 0 1-3.81-2.58 12.3 12.3 0 0 1-2.58-3.81Q12 2.49 12 0q0 2.49-.96 4.68-.93 2.19-2.55 3.81a12.3 12.3 0 0 1-3.81 2.58Q2.49 12 0 12q2.49 0 4.68.96 2.19.93 3.81 2.55t2.55 3.81"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Git.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Git.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Git.imageset/Git.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Git</title><path d="M23.546 10.93L13.067.452c-.604-.603-1.582-.603-2.188 0L8.708 2.627l2.76 2.76c.645-.215 1.379-.07 1.889.441.516.515.658 1.258.438 1.9l2.658 2.66c.645-.223 1.387-.078 1.9.435.721.72.721 1.884 0 2.604-.719.719-1.881.719-2.6 0-.539-.541-.674-1.337-.404-1.996L12.86 8.955v6.525c.176.086.342.203.488.348.713.721.713 1.883 0 2.6-.719.721-1.889.721-2.609 0-.719-.719-.719-1.879 0-2.598.182-.18.387-.316.605-.406V8.835c-.217-.091-.424-.222-.6-.401-.545-.545-.676-1.342-.396-2.009L7.636 3.7.45 10.881c-.6.605-.6 1.584 0 2.189l10.48 10.477c.604.604 1.582.604 2.186 0l10.43-10.43c.605-.603.605-1.582 0-2.187"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/GitHub.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "GitHub.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/GitHub.imageset/GitHub.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/GitHubCopilot.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "GitHubCopilot.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/GitHubCopilot.imageset/GitHubCopilot.svg
··· 1 + <svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>GithubCopilot</title><path d="M19.245 5.364c1.322 1.36 1.877 3.216 2.11 5.817.622 0 1.2.135 1.592.654l.73.964c.21.278.323.61.323.955v2.62c0 .339-.173.669-.453.868C20.239 19.602 16.157 21.5 12 21.5c-4.6 0-9.205-2.583-11.547-4.258-.28-.2-.452-.53-.453-.868v-2.62c0-.345.113-.679.321-.956l.73-.963c.392-.517.974-.654 1.593-.654l.029-.297c.25-2.446.81-4.213 2.082-5.52 2.461-2.54 5.71-2.851 7.146-2.864h.198c1.436.013 4.685.323 7.146 2.864zm-7.244 4.328c-.284 0-.613.016-.962.05-.123.447-.305.85-.57 1.108-1.05 1.023-2.316 1.18-2.994 1.18-.638 0-1.306-.13-1.851-.464-.516.165-1.012.403-1.044.996a65.882 65.882 0 00-.063 2.884l-.002.48c-.002.563-.005 1.126-.013 1.69.002.326.204.63.51.765 2.482 1.102 4.83 1.657 6.99 1.657 2.156 0 4.504-.555 6.985-1.657a.854.854 0 00.51-.766c.03-1.682.006-3.372-.076-5.053-.031-.596-.528-.83-1.046-.996-.546.333-1.212.464-1.85.464-.677 0-1.942-.157-2.993-1.18-.266-.258-.447-.661-.57-1.108-.32-.032-.64-.049-.96-.05zm-2.525 4.013c.539 0 .976.426.976.95v1.753c0 .525-.437.95-.976.95a.964.964 0 01-.976-.95v-1.752c0-.525.437-.951.976-.951zm5 0c.539 0 .976.426.976.95v1.753c0 .525-.437.95-.976.95a.964.964 0 01-.976-.95v-1.752c0-.525.437-.951.976-.951zM7.635 5.087c-1.05.102-1.935.438-2.385.906-.975 1.037-.765 3.668-.21 4.224.405.394 1.17.657 1.995.657h.09c.649-.013 1.785-.176 2.73-1.11.435-.41.705-1.433.675-2.47-.03-.834-.27-1.52-.63-1.813-.39-.336-1.275-.482-2.265-.394zm6.465.394c-.36.292-.6.98-.63 1.813-.03 1.037.24 2.06.675 2.47.968.957 2.136 1.104 2.776 1.11h.044c.825 0 1.59-.263 1.995-.657.555-.556.765-3.187-.21-4.224-.45-.468-1.335-.804-2.385-.906-.99-.088-1.875.058-2.265.394zM12 7.615c-.24 0-.525.015-.84.044.03.16.045.336.06.526l-.001.159a2.94 2.94 0 01-.014.25c.225-.022.425-.027.612-.028h.366c.187 0 .387.006.612.028-.015-.146-.015-.277-.015-.409.015-.19.03-.365.06-.526a9.29 9.29 0 00-.84-.044z"></path></svg>
+16
supacode/Assets.xcassets/CommandIcons/Go.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Go.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Go.imageset/Go.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Go</title><path d="M1.811 10.231c-.047 0-.058-.023-.035-.059l.246-.315c.023-.035.081-.058.128-.058h4.172c.046 0 .058.035.035.07l-.199.303c-.023.036-.082.07-.117.07zM.047 11.306c-.047 0-.059-.023-.035-.058l.245-.316c.023-.035.082-.058.129-.058h5.328c.047 0 .07.035.058.07l-.093.28c-.012.047-.058.07-.105.07zm2.828 1.075c-.047 0-.059-.035-.035-.07l.163-.292c.023-.035.07-.07.117-.07h2.337c.047 0 .07.035.07.082l-.023.28c0 .047-.047.082-.082.082zm12.129-2.36c-.736.187-1.239.327-1.963.514-.176.046-.187.058-.34-.117-.174-.199-.303-.327-.548-.444-.737-.362-1.45-.257-2.115.175-.795.514-1.204 1.274-1.192 2.22.011.935.654 1.706 1.577 1.835.795.105 1.46-.175 1.987-.77.105-.13.198-.27.315-.434H10.47c-.245 0-.304-.152-.222-.35.152-.362.432-.97.596-1.274a.315.315 0 01.292-.187h4.253c-.023.316-.023.631-.07.947a4.983 4.983 0 01-.958 2.29c-.841 1.11-1.94 1.8-3.33 1.986-1.145.152-2.209-.07-3.143-.77-.865-.655-1.356-1.52-1.484-2.595-.152-1.274.222-2.419.993-3.424.83-1.086 1.928-1.776 3.272-2.02 1.098-.2 2.15-.07 3.096.571.62.41 1.063.97 1.356 1.648.07.105.023.164-.117.2m3.868 6.461c-1.064-.024-2.034-.328-2.852-1.029a3.665 3.665 0 01-1.262-2.255c-.21-1.32.152-2.489.947-3.529.853-1.122 1.881-1.706 3.272-1.95 1.192-.21 2.314-.095 3.33.595.923.63 1.496 1.484 1.648 2.605.198 1.578-.257 2.863-1.344 3.962-.771.783-1.718 1.273-2.805 1.495-.315.06-.63.07-.934.106zm2.78-4.72c-.011-.153-.011-.27-.034-.387-.21-1.157-1.274-1.81-2.384-1.554-1.087.245-1.788.935-2.045 2.033-.21.912.234 1.835 1.075 2.21.643.28 1.285.244 1.905-.07.923-.48 1.425-1.228 1.484-2.233z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/GoogleCloud.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "GoogleCloud.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/GoogleCloud.imageset/GoogleCloud.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Google Cloud</title><path d="M12.19 2.38a9.344 9.344 0 0 0-9.234 6.893c.053-.02-.055.013 0 0-3.875 2.551-3.922 8.11-.247 10.941l.006-.007-.007.03a6.717 6.717 0 0 0 4.077 1.356h5.173l.03.03h5.192c6.687.053 9.376-8.605 3.835-12.35a9.365 9.365 0 0 0-2.821-4.552l-.043.043.006-.05A9.344 9.344 0 0 0 12.19 2.38zm-.358 4.146c1.244-.04 2.518.368 3.486 1.15a5.186 5.186 0 0 1 1.862 4.078v.518c3.53-.07 3.53 5.262 0 5.193h-5.193l-.008.009v-.04H6.785a2.59 2.59 0 0 1-1.067-.23h.001a2.597 2.597 0 1 1 3.437-3.437l3.013-3.012A6.747 6.747 0 0 0 8.11 8.24c.018-.01.04-.026.054-.023a5.186 5.186 0 0 1 3.67-1.69z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Gradle.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Gradle.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Gradle.imageset/Gradle.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Gradle</title><path d="M22.695 4.297a3.807 3.807 0 0 0-5.29-.09.368.368 0 0 0 0 .533l.46.47a.363.363 0 0 0 .474.032 2.182 2.182 0 0 1 2.86 3.291c-3.023 3.02-7.056-5.447-16.211-1.083a1.24 1.24 0 0 0-.534 1.745l1.571 2.713a1.238 1.238 0 0 0 1.681.461l.037-.02-.029.02.688-.384a16.083 16.083 0 0 0 2.193-1.635.384.384 0 0 1 .499-.016.357.357 0 0 1 .016.534 16.435 16.435 0 0 1-2.316 1.741H8.77l-.696.39a1.958 1.958 0 0 1-.963.25 1.987 1.987 0 0 1-1.726-.989L3.9 9.696C1.06 11.72-.686 15.603.26 20.522a.363.363 0 0 0 .354.296h1.675a.363.363 0 0 0 .37-.331 2.478 2.478 0 0 1 4.915 0 .36.36 0 0 0 .357.317h1.638a.363.363 0 0 0 .357-.317 2.478 2.478 0 0 1 4.914 0 .363.363 0 0 0 .358.317h1.627a.363.363 0 0 0 .363-.357c.037-2.294.656-4.93 2.42-6.25 6.108-4.57 4.502-8.486 3.088-9.9zm-6.229 6.901l-1.165-.584a.73.73 0 1 1 1.165.587z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Homebrew.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Homebrew.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Homebrew.imageset/Homebrew.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Homebrew</title><path d="M7.938 0a.214.214 0 0 0-.206.156c-.316 1.104.179 2.15.838 2.935.153.181.313.347.476.501a2.039 2.039 0 0 0-.665.02c-1.184.233-2.193.985-2.74 2.532a3.893 3.893 0 0 0-.2 1.466 1.565 1.565 0 0 0-1.156 1.504 1.59 1.59 0 0 0 1.227 1.541l.026 12.046c0 .195.1.377.264.482a.214.214 0 0 0 .008.005c.537.31 2.047.812 5.21.812 3.238 0 4.7-.678 5.181-1.04a.214.214 0 0 0 .008-.007.571.571 0 0 0 .206-.439c.002-.344.002-1.136.002-1.604a.143.143 0 0 1 .147-.144c.397.006.869.006 1.318.005a1.826 1.826 0 0 0 1.832-1.825v-5.804a1.826 1.826 0 0 0-1.825-1.826H16.56a.14.14 0 0 1-.143-.144V10.6h.007v-.001a1.573 1.573 0 0 0 1.356-1.556c0-.816-.627-1.489-1.424-1.563-.025-1.438-.437-2.126-.736-2.58a.214.214 0 0 0-.005-.007c-.364-.51-1.193-1.282-2.275-1.316-.503-.016-.842.124-1.125.254-.217.1-.42.177-.67.22.002-1.286.945-1.981.945-1.981a.214.214 0 0 0 .05-.298s-.087-.122-.21-.26c-.121-.136-.269-.294-.47-.378a.214.214 0 0 0-.079-.017.214.214 0 0 0-.145.055 4.308 4.308 0 0 0-.875 1.101 3.42 3.42 0 0 0-.133.273 3.497 3.497 0 0 0-.381-.846C9.794.978 9.063.436 8.017.016A.214.214 0 0 0 7.939 0zm.156.524c.85.378 1.43.83 1.79 1.403.274.438.426.962.484 1.584a3.07 3.07 0 0 0-.012.462 6.897 6.897 0 0 1-.168-.052 5.487 5.487 0 0 1-1.29-1.106c-.551-.657-.935-1.46-.804-2.291zM11.8 1.618c.07.054.141.101.212.18.034.039.032.04.058.073-.332.308-1.07 1.144-.952 2.453a.214.214 0 0 0 .222.195c.469-.017.782-.172 1.056-.299.273-.126.508-.228.931-.214.875.027 1.639.715 1.939 1.134.295.449.65 1 .663 2.36a1.66 1.66 0 0 0-.41.142 1.938 1.938 0 0 0-1.77-1.16 1.94 1.94 0 0 0-1.87 1.448 1.783 1.783 0 0 0-1.356-.64c-.484 0-.91.205-1.233.517a1.873 1.873 0 0 0-1.85-1.625c-.649 0-1.218.335-1.552.84a3.1 3.1 0 0 1 .157-.735c.51-1.437 1.355-2.045 2.42-2.254.367-.073.664-.011.99.095.325.106.671.262 1.094.342a.214.214 0 0 0 .252-.245c-.112-.67.073-1.266.336-1.744a3.71 3.71 0 0 1 .663-.863zM7.44 6.611a1.442 1.442 0 0 1 1.363 1.925.214.214 0 0 0 .168.283h.005a.214.214 0 0 0 .238-.146 1.373 1.373 0 0 1 2.613-.01.214.214 0 0 0 .417-.09 1.509 1.509 0 0 1 1.504-1.664c.678 0 1.249.445 1.442 1.056a.214.214 0 0 0 .259.143l.15-.04a.214.214 0 0 0 .051-.02 1.139 1.139 0 0 1 1.702.995 1.14 1.14 0 0 1-.985 1.131.214.214 0 0 0-.001 0 2.215 2.215 0 0 0-.485.126 10.65 10.65 0 0 1-1.176.365.214.214 0 0 0-.162.186 1.276 1.276 0 0 1-.146.478 2.07 2.07 0 0 0-.239 1.111l.001.151a.438.438 0 0 1-.16.36.665.665 0 0 1-.43.14.586.586 0 0 1-.588-.59.803.803 0 0 0-.38-.681.214.214 0 0 0-.002-.002c-.24-.145-.43-.37-.532-.636a.214.214 0 0 0-.207-.138 19.469 19.469 0 0 1-5.37-.6l-.003-.002a9.007 9.007 0 0 0-.838-.194h.003a1.16 1.16 0 0 1-.937-1.134c0-.619.488-1.118 1.101-1.14a.214.214 0 0 0 .204-.176 1.443 1.443 0 0 1 1.42-1.187zm8.549 4.106v.455c0 .314.259.573.572.573h1.329a1.397 1.397 0 0 1 1.397 1.397v5.804a1.396 1.396 0 0 1-1.402 1.396.214.214 0 0 0-.002 0c-.448.002-.918 0-1.31-.005a.573.573 0 0 0-.584.573c0 .468 0 1.262-.002 1.603a.214.214 0 0 0 0 .001c0 .042-.019.08-.05.107-.346.26-1.75.95-4.915.95-3.107 0-4.587-.52-4.99-.752a.143.143 0 0 1-.065-.118l-.025-11.955c.145.033.288.07.431.11a.214.214 0 0 0 .003 0c.115.031.246.064.383.097v10.37c0 .129.069.247.18.31.453.217 1.767.732 4.071.732 2.32 0 3.595-.626 4.022-.884a.357.357 0 0 0 .164-.3l.001-10.21c.267-.075.531-.158.792-.254zm-7.99.894a.493.493 0 0 1 .494.493v8.578a.493.493 0 0 1-.493.493.493.493 0 0 1-.494-.493v-8.578A.493.493 0 0 1 8 11.611zm8.652 1.14a.663.663 0 0 0-.662.662v5.208a.663.663 0 0 0 .662.662h1.14a.663.663 0 0 0 .662-.662v-5.209a.663.663 0 0 0-.662-.662zm0 .428h1.14a.233.233 0 0 1 .233.233v5.21a.233.233 0 0 1-.233.232h-1.14a.233.233 0 0 1-.233-.233v-5.209a.233.233 0 0 1 .233-.233z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Kimi.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Kimi.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Kimi.imageset/Kimi.svg
··· 1 + <svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Kimi</title><path d="M21.846 0a1.923 1.923 0 110 3.846H20.15a.226.226 0 01-.227-.226V1.923C19.923.861 20.784 0 21.846 0z"></path><path d="M11.065 11.199l7.257-7.2c.137-.136.06-.41-.116-.41H14.3a.164.164 0 00-.117.051l-7.82 7.756c-.122.12-.302.013-.302-.179V3.82c0-.127-.083-.23-.185-.23H3.186c-.103 0-.186.103-.186.23V19.77c0 .128.083.23.186.23h2.69c.103 0 .186-.102.186-.23v-3.25c0-.069.025-.135.069-.178l2.424-2.406a.158.158 0 01.205-.023l6.484 4.772a7.677 7.677 0 003.453 1.283c.108.012.2-.095.2-.23v-3.06c0-.117-.07-.212-.164-.227a5.028 5.028 0 01-2.027-.807l-5.613-4.064c-.117-.078-.132-.279-.028-.381z"></path></svg>
+16
supacode/Assets.xcassets/CommandIcons/Kubernetes.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Kubernetes.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Kubernetes.imageset/Kubernetes.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Kubernetes</title><path d="M10.204 14.35l.007.01-.999 2.413a5.171 5.171 0 0 1-2.075-2.597l2.578-.437.004.005a.44.44 0 0 1 .484.606zm-.833-2.129a.44.44 0 0 0 .173-.756l.002-.011L7.585 9.7a5.143 5.143 0 0 0-.73 3.255l2.514-.725.002-.009zm1.145-1.98a.44.44 0 0 0 .699-.337l.01-.005.15-2.62a5.144 5.144 0 0 0-3.01 1.442l2.147 1.523.004-.002zm.76 2.75l.723.349.722-.347.18-.78-.5-.623h-.804l-.5.623.179.779zm1.5-3.095a.44.44 0 0 0 .7.336l.008.003 2.134-1.513a5.188 5.188 0 0 0-2.992-1.442l.148 2.615.002.001zm10.876 5.97l-5.773 7.181a1.6 1.6 0 0 1-1.248.594l-9.261.003a1.6 1.6 0 0 1-1.247-.596l-5.776-7.18a1.583 1.583 0 0 1-.307-1.34L2.1 5.573c.108-.47.425-.864.863-1.073L11.305.513a1.606 1.606 0 0 1 1.385 0l8.345 3.985c.438.209.755.604.863 1.073l2.062 8.955c.108.47-.005.963-.308 1.34zm-3.289-2.057c-.042-.01-.103-.026-.145-.034-.174-.033-.315-.025-.479-.038-.35-.037-.638-.067-.895-.148-.105-.04-.18-.165-.216-.216l-.201-.059a6.45 6.45 0 0 0-.105-2.332 6.465 6.465 0 0 0-.936-2.163c.052-.047.15-.133.177-.159.008-.09.001-.183.094-.282.197-.185.444-.338.743-.522.142-.084.273-.137.415-.242.032-.024.076-.062.11-.089.24-.191.295-.52.123-.736-.172-.216-.506-.236-.745-.045-.034.027-.08.062-.111.088-.134.116-.217.23-.33.35-.246.25-.45.458-.673.609-.097.056-.239.037-.303.033l-.19.135a6.545 6.545 0 0 0-4.146-2.003l-.012-.223c-.065-.062-.143-.115-.163-.25-.022-.268.015-.557.057-.905.023-.163.061-.298.068-.475.001-.04-.001-.099-.001-.142 0-.306-.224-.555-.5-.555-.275 0-.499.249-.499.555l.001.014c0 .041-.002.092 0 .128.006.177.044.312.067.475.042.348.078.637.056.906a.545.545 0 0 1-.162.258l-.012.211a6.424 6.424 0 0 0-4.166 2.003 8.373 8.373 0 0 1-.18-.128c-.09.012-.18.04-.297-.029-.223-.15-.427-.358-.673-.608-.113-.12-.195-.234-.329-.349-.03-.026-.077-.062-.111-.088a.594.594 0 0 0-.348-.132.481.481 0 0 0-.398.176c-.172.216-.117.546.123.737l.007.005.104.083c.142.105.272.159.414.242.299.185.546.338.743.522.076.082.09.226.1.288l.16.143a6.462 6.462 0 0 0-1.02 4.506l-.208.06c-.055.072-.133.184-.215.217-.257.081-.546.11-.895.147-.164.014-.305.006-.48.039-.037.007-.09.02-.133.03l-.004.002-.007.002c-.295.071-.484.342-.423.608.061.267.349.429.645.365l.007-.001.01-.003.129-.029c.17-.046.294-.113.448-.172.33-.118.604-.217.87-.256.112-.009.23.069.288.101l.217-.037a6.5 6.5 0 0 0 2.88 3.596l-.09.218c.033.084.069.199.044.282-.097.252-.263.517-.452.813-.091.136-.185.242-.268.399-.02.037-.045.095-.064.134-.128.275-.034.591.213.71.248.12.556-.007.69-.282v-.002c.02-.039.046-.09.062-.127.07-.162.094-.301.144-.458.132-.332.205-.68.387-.897.05-.06.13-.082.215-.105l.113-.205a6.453 6.453 0 0 0 4.609.012l.106.192c.086.028.18.042.256.155.136.232.229.507.342.84.05.156.074.295.145.457.016.037.043.09.062.129.133.276.442.402.69.282.247-.118.341-.435.213-.71-.02-.039-.045-.096-.065-.134-.083-.156-.177-.261-.268-.398-.19-.296-.346-.541-.443-.793-.04-.13.007-.21.038-.294-.018-.022-.059-.144-.083-.202a6.499 6.499 0 0 0 2.88-3.622c.064.01.176.03.213.038.075-.05.144-.114.28-.104.266.039.54.138.87.256.154.06.277.128.448.173.036.01.088.019.13.028l.009.003.007.001c.297.064.584-.098.645-.365.06-.266-.128-.537-.423-.608zM16.4 9.701l-1.95 1.746v.005a.44.44 0 0 0 .173.757l.003.01 2.526.728a5.199 5.199 0 0 0-.108-1.674A5.208 5.208 0 0 0 16.4 9.7zm-4.013 5.325a.437.437 0 0 0-.404-.232.44.44 0 0 0-.372.233h-.002l-1.268 2.292a5.164 5.164 0 0 0 3.326.003l-1.27-2.296h-.01zm1.888-1.293a.44.44 0 0 0-.27.036.44.44 0 0 0-.214.572l-.003.004 1.01 2.438a5.15 5.15 0 0 0 2.081-2.615l-2.6-.44-.004.005z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/MySQL.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "MySQL.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/MySQL.imageset/MySQL.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>MySQL</title><path d="M16.405 5.501c-.115 0-.193.014-.274.033v.013h.014c.054.104.146.18.214.273.054.107.1.214.154.32l.014-.015c.094-.066.14-.172.14-.333-.04-.047-.046-.094-.08-.14-.04-.067-.126-.1-.18-.153zM5.77 18.695h-.927a50.854 50.854 0 00-.27-4.41h-.008l-1.41 4.41H2.45l-1.4-4.41h-.01a72.892 72.892 0 00-.195 4.41H0c.055-1.966.192-3.81.41-5.53h1.15l1.335 4.064h.008l1.347-4.064h1.095c.242 2.015.384 3.86.428 5.53zm4.017-4.08c-.378 2.045-.876 3.533-1.492 4.46-.482.716-1.01 1.073-1.583 1.073-.153 0-.34-.046-.566-.138v-.494c.11.017.24.026.386.026.268 0 .483-.075.647-.222.197-.18.295-.382.295-.605 0-.155-.077-.47-.23-.944L6.23 14.615h.91l.727 2.36c.164.536.233.91.205 1.123.4-1.064.678-2.227.835-3.483zm12.325 4.08h-2.63v-5.53h.885v4.85h1.745zm-3.32.135l-1.016-.5c.09-.076.177-.158.255-.25.433-.506.648-1.258.648-2.253 0-1.83-.718-2.746-2.155-2.746-.704 0-1.254.232-1.65.697-.43.508-.646 1.256-.646 2.245 0 .972.19 1.686.574 2.14.35.41.877.615 1.583.615.264 0 .506-.033.725-.098l1.325.772.36-.622zM15.5 17.588c-.225-.36-.337-.94-.337-1.736 0-1.393.424-2.09 1.27-2.09.443 0 .77.167.977.5.224.362.336.936.336 1.723 0 1.404-.424 2.108-1.27 2.108-.445 0-.77-.167-.978-.5zm-1.658-.425c0 .47-.172.856-.516 1.156-.344.3-.803.45-1.384.45-.543 0-1.064-.172-1.573-.515l.237-.476c.438.22.833.328 1.19.328.332 0 .593-.073.783-.22a.754.754 0 00.3-.615c0-.33-.23-.61-.648-.845-.388-.213-1.163-.657-1.163-.657-.422-.307-.632-.636-.632-1.177 0-.45.157-.81.47-1.085.315-.278.72-.415 1.22-.415.512 0 .98.136 1.4.41l-.213.476a2.726 2.726 0 00-1.064-.23c-.283 0-.502.068-.654.206a.685.685 0 00-.248.524c0 .328.234.61.666.85.393.215 1.187.67 1.187.67.433.305.648.63.648 1.168zm9.382-5.852c-.535-.014-.95.04-1.297.188-.1.04-.26.04-.274.167.055.053.063.14.11.214.08.134.218.313.346.407.14.11.28.216.427.31.26.16.555.255.81.416.145.094.293.213.44.313.073.05.12.14.214.172v-.02c-.046-.06-.06-.147-.105-.214-.067-.067-.134-.127-.2-.193a3.223 3.223 0 00-.695-.675c-.214-.146-.682-.35-.77-.595l-.013-.014c.146-.013.32-.066.46-.106.227-.06.435-.047.67-.106.106-.027.213-.06.32-.094v-.06c-.12-.12-.21-.283-.334-.395a8.867 8.867 0 00-1.104-.823c-.21-.134-.476-.22-.697-.334-.08-.04-.214-.06-.26-.127-.12-.146-.19-.34-.275-.514a17.69 17.69 0 01-.547-1.163c-.12-.262-.193-.523-.34-.763-.69-1.137-1.437-1.826-2.586-2.5-.247-.14-.543-.2-.856-.274-.167-.008-.334-.02-.5-.027-.11-.047-.216-.174-.31-.235-.38-.24-1.364-.76-1.644-.072-.18.434.267.862.422 1.082.115.153.26.328.34.5.047.116.06.235.107.356.106.294.207.622.347.897.073.14.153.287.247.413.054.073.146.107.167.227-.094.136-.1.334-.154.5-.24.757-.146 1.693.194 2.25.107.166.362.534.703.393.3-.12.234-.5.32-.835.02-.08.007-.133.048-.187v.015c.094.188.188.367.274.555.206.328.566.668.867.895.16.12.287.328.487.402v-.02h-.015c-.043-.058-.1-.086-.154-.133a3.445 3.445 0 01-.35-.4 8.76 8.76 0 01-.747-1.218c-.11-.21-.202-.436-.29-.643-.04-.08-.04-.2-.107-.24-.1.146-.247.273-.32.453-.127.288-.14.642-.188 1.01-.027.007-.014 0-.027.014-.214-.052-.287-.274-.367-.46-.2-.475-.233-1.238-.06-1.785.047-.14.247-.582.167-.716-.042-.127-.174-.2-.247-.303a2.478 2.478 0 01-.24-.427c-.16-.374-.24-.788-.414-1.162-.08-.173-.22-.354-.334-.513-.127-.18-.267-.307-.368-.52-.033-.073-.08-.194-.027-.274.014-.054.042-.075.094-.09.088-.072.335.022.422.062.247.1.455.194.662.334.094.066.195.193.315.226h.14c.214.047.455.014.655.073.355.114.675.28.962.46a5.953 5.953 0 012.085 2.286c.08.154.115.295.188.455.14.33.313.663.455.982.14.315.275.636.476.897.1.14.502.213.682.286.133.06.34.115.46.188.23.14.454.3.67.454.11.076.443.243.463.378z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Neovim.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Neovim.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Neovim.imageset/Neovim.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Neovim</title><path d="M2.214 4.954v13.615L7.655 24V10.314L3.312 3.845 2.214 4.954zm4.999 17.98l-4.557-4.548V5.136l.59-.596 3.967 5.908v12.485zm14.573-4.457l-.862.937-4.24-6.376V0l5.068 5.092.034 13.385zM7.431.001l12.998 19.835-3.637 3.637L3.787 3.683 7.43 0z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Node.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Node.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Node.imageset/Node.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Node.js</title><path d="M11.998,24c-0.321,0-0.641-0.084-0.922-0.247l-2.936-1.737c-0.438-0.245-0.224-0.332-0.08-0.383 c0.585-0.203,0.703-0.25,1.328-0.604c0.065-0.037,0.151-0.023,0.218,0.017l2.256,1.339c0.082,0.045,0.197,0.045,0.272,0l8.795-5.076 c0.082-0.047,0.134-0.141,0.134-0.238V6.921c0-0.099-0.053-0.192-0.137-0.242l-8.791-5.072c-0.081-0.047-0.189-0.047-0.271,0 L3.075,6.68C2.99,6.729,2.936,6.825,2.936,6.921v10.15c0,0.097,0.054,0.189,0.139,0.235l2.409,1.392 c1.307,0.654,2.108-0.116,2.108-0.89V7.787c0-0.142,0.114-0.253,0.256-0.253h1.115c0.139,0,0.255,0.112,0.255,0.253v10.021 c0,1.745-0.95,2.745-2.604,2.745c-0.508,0-0.909,0-2.026-0.551L2.28,18.675c-0.57-0.329-0.922-0.945-0.922-1.604V6.921 c0-0.659,0.353-1.275,0.922-1.603l8.795-5.082c0.557-0.315,1.296-0.315,1.848,0l8.794,5.082c0.57,0.329,0.924,0.944,0.924,1.603 v10.15c0,0.659-0.354,1.273-0.924,1.604l-8.794,5.078C12.643,23.916,12.324,24,11.998,24z M19.099,13.993 c0-1.9-1.284-2.406-3.987-2.763c-2.731-0.361-3.009-0.548-3.009-1.187c0-0.528,0.235-1.233,2.258-1.233 c1.807,0,2.473,0.389,2.747,1.607c0.024,0.115,0.129,0.199,0.247,0.199h1.141c0.071,0,0.138-0.031,0.186-0.081 c0.048-0.054,0.074-0.123,0.067-0.196c-0.177-2.098-1.571-3.076-4.388-3.076c-2.508,0-4.004,1.058-4.004,2.833 c0,1.925,1.488,2.457,3.895,2.695c2.88,0.282,3.103,0.703,3.103,1.269c0,0.983-0.789,1.402-2.642,1.402 c-2.327,0-2.839-0.584-3.011-1.742c-0.02-0.124-0.126-0.215-0.253-0.215h-1.137c-0.141,0-0.254,0.112-0.254,0.253 c0,1.482,0.806,3.248,4.655,3.248C17.501,17.007,19.099,15.91,19.099,13.993z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Npm.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Npm.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Npm.imageset/Npm.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>npm</title><path d="M1.763 0C.786 0 0 .786 0 1.763v20.474C0 23.214.786 24 1.763 24h20.474c.977 0 1.763-.786 1.763-1.763V1.763C24 .786 23.214 0 22.237 0zM5.13 5.323l13.837.019-.009 13.836h-3.464l.01-10.382h-3.456L12.04 19.17H5.113z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/OpenCode.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "OpenCode.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/OpenCode.imageset/OpenCode.svg
··· 1 + <svg fill="currentColor" fill-rule="evenodd" height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>opencode</title><path d="M16 6H8v12h8V6zm4 16H4V2h16v20z"></path></svg>
+16
supacode/Assets.xcassets/CommandIcons/Pnpm.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Pnpm.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Pnpm.imageset/Pnpm.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>pnpm</title><path d="M0 0v7.5h7.5V0zm8.25 0v7.5h7.498V0zm8.25 0v7.5H24V0zM2 2h3.5v3.5H2zm8.25 0h3.498v3.5H10.25zm8.25 0H22v3.5h-3.5zM8.25 8.25v7.5h7.498v-7.5zm8.25 0v7.5H24v-7.5zm2 2H22v3.5h-3.5zM0 16.5V24h7.5v-7.5zm8.25 0V24h7.498v-7.5zm8.25 0V24H24v-7.5z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Podman.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Podman.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Podman.imageset/Podman.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Podman</title><path d="M17.2.275L6.75.308a.259.259 0 0 0-.203.098L.056 8.602a.259.259 0 0 0-.05.219l2.356 10.194a.26.26 0 0 0 .14.174l9.43 4.511a.258.258 0 0 0 .224-.002l9.401-4.566a.259.259 0 0 0 .141-.175L23.993 8.75a.258.258 0 0 0-.051-.22L17.403.374A.259.259 0 0 0 17.2.275zm-.123.517l6.385 7.966-2.242 9.964-9.177 4.457-9.205-4.402L.54 8.827 6.875.824zM11.46 2.857c-.933 0-1.84.1-2.426.332h-.002c-1.554.569-2.725 2.105-3.074 3.952v.004c-.309 1.463-.392 2.703-.556 3.824-.07.481-.159.94-.283 1.387-.628.497-1.079 1.263-1.244 2.138v.004c-.116.547-.181 1.04-.237 1.5h-.644v.518h8.891c-.061.464-.122.996-.181 1.42H7.596v.517h7.939c-.242-.078-.486-.218-.756-.502h-.697l-.85.488-.232-.396.162-.092h-1.069c.113-.776.17-1.601.373-2.564v-.004c.22-1.164.96-2.112 1.895-2.453l.004-.002h.002c.318-.127.928-.205 1.543-.205.613 0 1.244.075 1.622.207.935.341 1.676 1.29 1.895 2.453v.004c.204.963.26 1.788.373 2.564h-.742l.162.092-.233.396-.85-.488h-.75c-.219.25-.474.412-.747.502h4.392v-.518h-.842c-.103-.743-.181-1.67-.382-2.623v-.002a4.14 4.14 0 0 0-.264-.863h1.863v-.517h-2.13a3.488 3.488 0 0 0-.8-.906h1.8v-.518H17.95a8.862 8.862 0 0 1-.193-.775h1.484v-.518h-1.576c-.013-.081-.027-.161-.039-.244-.164-1.12-.246-2.36-.555-3.824v-.004c-.348-1.848-1.52-3.383-3.075-3.952l-.002-.002h-.002c-.65-.227-1.596-.33-2.531-.33zm0 .386c.904 0 1.833.11 2.404.309h.002c1.4.514 2.5 1.934 2.826 3.666v.003c.303 1.436.385 2.66.552 3.805.076.515.173 1.013.315 1.505-.449-.135-1.05-.197-1.648-.197-.12 0-.236.003-.352.008l-1.863-1.865a2.17 2.17 0 0 0 .11-.246l2.13 1.23.13-.224-2.185-1.262c.016-.069.027-.14.036-.21l2.302.616.068-.248-2.354-.63c-.02-1.153-1.008-2.078-2.208-2.078-1.205 0-2.196.931-2.206 2.091l-2.303.617.066.25 2.252-.605c.01.076.024.151.041.224L7.436 11.24l.129.222 2.087-1.207c.034.089.074.176.12.258l-1.266 1.266a6.959 6.959 0 0 0-1.045-.075c-.603 0-1.186.064-1.578.22a2.668 2.668 0 0 0-.285.124c.076-.335.137-.675.187-1.021.168-1.144.248-2.37.551-3.805l.002-.001v-.002c.326-1.733 1.426-3.153 2.828-3.666h.002l.004-.002c.488-.194 1.381-.307 2.287-.307zM8.473 5.194a1.295 1.295 0 0 0-.965.502l-.117.153.306.236.12-.152a.923.923 0 0 1 .673-.352.92.92 0 0 1 .67.262l.139.134.271-.275-.136-.137a1.293 1.293 0 0 0-.961-.37zm6.39 0a1.289 1.289 0 0 0-.96.371l-.138.137.274.275.136-.134a.923.923 0 0 1 .672-.262.923.923 0 0 1 .674.352l.119.152.307-.236-.12-.153c-.23-.3-.587-.486-.964-.502zM8.53 6.708c-.642 0-1.164.538-1.164 1.19 0 .65.522 1.187 1.164 1.187.643 0 1.164-.536 1.164-1.188 0-.651-.521-1.19-1.164-1.19zm6.273 0c-.643 0-1.162.538-1.162 1.19 0 .65.52 1.187 1.162 1.187.643 0 1.164-.536 1.164-1.188 0-.651-.521-1.19-1.164-1.19zm-6.273.387c.428 0 .776.355.776.802 0 .447-.348.8-.776.8a.785.785 0 0 1-.775-.8c0-.035.002-.07.006-.103.07.191.248.318.445.318a.487.487 0 0 0 .477-.496.49.49 0 0 0-.383-.486.759.759 0 0 1 .23-.035zm6.273 0c.428 0 .777.355.777.802 0 .447-.349.8-.777.8a.785.785 0 0 1-.77-.9c.072.19.248.315.444.315a.486.486 0 0 0 .479-.496.491.491 0 0 0-.383-.484.755.755 0 0 1 .23-.037zm-3.08.716c1.012 0 1.819.775 1.819 1.723 0 .947-.807 1.722-1.819 1.722s-1.82-.775-1.82-1.722c0-.948.808-1.723 1.82-1.723zm-.002.528c-.142 0-.258.043-.355.076a.804.804 0 0 1-.232.054c-.107 0-.2.047-.268.127a.568.568 0 0 0-.104.207c-.04.134-.062.268-.08.315a.276.276 0 0 0 .032.25c.033.056.071.1.117.146.09.092.206.183.322.268.12.088.237.166.326.224l-.008.09c-.043.036-.14.102-.324.178a.533.533 0 0 1-.299.025.43.43 0 0 1-.236-.172c.015-.138.044-.293.068-.449l-.376-.095c-.05.238-.067.43-.094.64l.037.059c.143.224.318.344.506.392a.908.908 0 0 0 .52-.033 1.57 1.57 0 0 0 .444-.242c.088.067.244.174.446.242a.908.908 0 0 0 .52.033.868.868 0 0 0 .507-.392l.037-.059a6.292 6.292 0 0 0-.096-.637l-.377.092c.032.148.051.32.07.451a.434.434 0 0 1-.237.17.533.533 0 0 1-.3-.025c-.178-.068-.272-.14-.325-.178l-.006-.084c.09-.058.209-.137.336-.23.115-.085.231-.176.322-.268a.72.72 0 0 0 .117-.146.273.273 0 0 0 .031-.25c-.018-.047-.039-.181-.08-.315a.564.564 0 0 0-.103-.207.343.343 0 0 0-.268-.127.815.815 0 0 1-.234-.054c-.097-.033-.212-.076-.354-.076zm.002.386c.057 0 .134.024.23.057.09.03.208.07.337.076.04.102.06.237.09.338a.361.361 0 0 1-.041.045 2.66 2.66 0 0 1-.276.228c-.165.122-.271.188-.342.233a5.287 5.287 0 0 1-.34-.233 2.557 2.557 0 0 1-.275-.228.34.34 0 0 1-.04-.047c.035-.119.046-.234.089-.34.08.012.246-.042.336-.072a.837.837 0 0 1 .232-.057zm-3.234.61a.635.635 0 0 0-.611.517l1.084-.289a.614.614 0 0 0-.473-.228zm6.336 0a.61.61 0 0 0-.436.187c.352.096.69.184 1.033.275a.632.632 0 0 0-.597-.462zm-.623.607c-.007.035-.002.07-.002.103l.921.532a.648.648 0 0 0 .276-.313l-1.195-.322zm-5.086.05l-1.18.315c.078.15.207.264.362.316l.797-.46c.018-.059.015-.12.021-.17zm4.441.714l1.656 1.658a4.19 4.19 0 0 0-.826.146l-.95-1.647a2.51 2.51 0 0 0 .12-.157zm-3.646.03c.04.055.083.118.129.169l-.658 1.134a2.656 2.656 0 0 0-.276-.119l-.002-.002a3.3 3.3 0 0 0-.292-.082zm3.338.317l.892 1.547c-.623.251-1.149.725-1.523 1.33h-1.652c-.262-.75-.741-1.38-1.358-1.764l.623-1.082c.394.347.919.559 1.492.559a2.25 2.25 0 0 0 1.526-.59zM7.46 12.09c.574 0 1.167.073 1.518.195.867.319 1.555 1.203 1.76 2.285l.001.002v.002c.109.513.173.98.227 1.424H9.86a.386.386 0 0 0-.494 0H9.11a1.351 1.351 0 0 0-.078-.418.799.799 0 0 0 .569.238c.45 0 .814-.375.814-.828a.824.824 0 0 0-.814-.828.822.822 0 0 0-.791 1.016 1.495 1.495 0 0 0-1.18-.559c-.798 0-1.46.611-1.48 1.38h-.342a.386.386 0 0 0-.494 0H4.028c.054-.445.116-.912.224-1.425l.002-.002v-.002c.205-1.084.894-1.97 1.764-2.287h.002l.004-.002c.295-.117.863-.191 1.437-.19zm-1.91 1.105a.898.898 0 0 0-.67.348l-.119.154.307.237.119-.155a.525.525 0 0 1 .379-.197.52.52 0 0 1 .377.147l.138.136.272-.275-.137-.137a.895.895 0 0 0-.666-.258zm4.094 0a.9.9 0 0 0-.668.258l-.137.137.273.275.137-.136a.522.522 0 0 1 .377-.147.525.525 0 0 1 .379.197l.119.155.307-.237-.12-.154a.894.894 0 0 0-.667-.348zm4.222.735a.947.947 0 0 0-.707.365l-.117.154.306.237.12-.155a.568.568 0 0 1 .413-.213.571.571 0 0 1 .414.159l.14.136.27-.275-.138-.137a.942.942 0 0 0-.701-.271zm4.374 0a.942.942 0 0 0-.7.271l-.14.137.272.275.139-.136a.571.571 0 0 1 .414-.159.568.568 0 0 1 .414.213l.119.155.306-.237-.117-.154a.947.947 0 0 0-.707-.365zm-12.65.232a.824.824 0 0 0-.815.828c0 .453.365.828.814.828.45 0 .815-.375.815-.828a.824.824 0 0 0-.815-.828zm5.518.285h1.242a4.137 4.137 0 0 0-.263.864v.002c-.05.237-.092.464-.127.685h-.602a16.77 16.77 0 0 0-.236-1.5l-.002-.002c-.003-.016-.009-.032-.012-.049zm-5.519.102a.43.43 0 0 1 .426.441.43.43 0 0 1-.426.442c-.22 0-.4-.171-.422-.397a.298.298 0 0 0 .215.092.31.31 0 0 0 .305-.316.317.317 0 0 0-.129-.258c.01-.001.02-.004.031-.004zm4.014 0c.235 0 .427.193.427.441a.433.433 0 0 1-.427.442.427.427 0 0 1-.422-.405.3.3 0 0 0 .256.145.31.31 0 0 0 .304-.317.314.314 0 0 0-.207-.298c.023-.004.045-.008.069-.008zm4.304.414a.865.865 0 0 0-.856.87c0 .478.382.874.856.874a.868.868 0 0 0 .857-.873.867.867 0 0 0-.857-.871zm4.292 0a.867.867 0 0 0-.814 1.14 1.597 1.597 0 0 0-1.295-.652c-.846 0-1.546.65-1.568 1.463l-1.525.408.066.248 1.477-.394c.004.028.009.06.015.087l-1.418.817.131.222 1.367-.789c.235.552.801.94 1.455.94.66 0 1.233-.397 1.463-.957l1.398.806.13-.222-1.45-.836c.005-.025.008-.053.012-.078l1.511.404.067-.248-1.563-.418a1.438 1.438 0 0 0-.107-.5c.157.186.39.303.648.303a.867.867 0 0 0 .856-.873.865.865 0 0 0-.856-.871zm-10.567.043c.598 0 1.071.444 1.092.992h-.41c.007-.01.016-.02.023-.033a.24.24 0 0 0 .025-.22c-.005-.016-.021-.102-.05-.196a.416.416 0 0 0-.078-.156.282.282 0 0 0-.225-.108.499.499 0 0 1-.129-.031c-.062-.021-.142-.05-.248-.05-.106 0-.188.029-.25.05a.49.49 0 0 1-.127.031.29.29 0 0 0-.225.108.424.424 0 0 0-.08.156c-.029.094-.043.18-.048.195a.242.242 0 0 0 .023.22c.008.014.017.023.025.034h-.41c.02-.548.494-.992 1.092-.992zm6.275.344c.259 0 .47.211.47.484a.477.477 0 0 1-.47.486.472.472 0 0 1-.467-.453.322.322 0 0 0 .246.115c.18 0 .326-.15.326-.338a.34.34 0 0 0-.156-.289c.017-.002.033-.005.05-.005zm4.292 0c.26 0 .469.211.469.484 0 .272-.21.486-.469.486a.477.477 0 0 1-.47-.486c0-.016.002-.031.004-.047a.33.33 0 0 0 .312.24c.18 0 .326-.15.326-.338a.338.338 0 0 0-.256-.332.475.475 0 0 1 .084-.007zm-10.567.24c.021 0 .063.01.125.031.086.03.117.039.186.049.012.041.022.088.033.129a1.475 1.475 0 0 1-.168.138c-.038.028-.064.045-.088.061h-.176c-.024-.016-.052-.033-.09-.06a1.602 1.602 0 0 1-.168-.14l.034-.128c.107-.014.146-.04.185-.049a.504.504 0 0 1 .127-.031zm8.458.25c.661 0 1.184.502 1.184 1.113 0 .156-.035.304-.096.44l-.002-.024-.022-.156a2.443 2.443 0 0 0-.04-.24l-.377.093.044.274a.24.24 0 0 1-.115.074.299.299 0 0 1-.168-.014c-.087-.03-.132-.063-.18-.094.057-.037.13-.084.198-.134.08-.06.16-.123.226-.19a.542.542 0 0 0 .092-.111.245.245 0 0 0 .026-.225c-.008-.019-.022-.112-.053-.21a.444.444 0 0 0-.084-.163.286.286 0 0 0-.23-.107.566.566 0 0 1-.14-.037c-.065-.022-.152-.055-.263-.055-.11 0-.195.032-.262.055a.575.575 0 0 1-.14.037.294.294 0 0 0-.23.107.436.436 0 0 0-.083.162c-.03.1-.045.192-.052.211a.246.246 0 0 0 .025.225.534.534 0 0 0 .09.111c.066.067.146.13.226.19.068.05.138.095.194.132a.57.57 0 0 1-.18.096.305.305 0 0 1-.17.014.237.237 0 0 1-.111-.076c.008-.09.026-.177.04-.272l-.376-.094c-.032.146-.045.286-.063.409a1.052 1.052 0 0 1-.09-.428c0-.611.521-1.113 1.182-1.113zm0 .623c.026 0 .074.01.14.033.066.025.169.052.206.055l.035.156c-.04.04-.112.1-.184.152-.095.07-.14.095-.197.131-.056-.036-.1-.061-.195-.13a1.236 1.236 0 0 1-.184-.157l.035-.152a1.04 1.04 0 0 0 .206-.055.523.523 0 0 1 .138-.033zm-2.22.353a.43.43 0 0 0-.385.272l.656-.176a.416.416 0 0 0-.271-.096zm4.333 0a.414.414 0 0 0-.22.07l.603.16a.426.426 0 0 0-.383-.23zm-4.054.567l-.607.162a.436.436 0 0 0 .125.113zm3.925.002l.407.234a.443.443 0 0 0 .087-.102zm-1.986.234c.067.047.165.108.285.148a.68.68 0 0 0 .389.024.57.57 0 0 0 .232-.121 1.201 1.201 0 0 1-.904.394c-.356 0-.67-.145-.885-.375a.58.58 0 0 0 .207.102c.144.036.28.014.391-.024.12-.04.218-.1.285-.148zm-9.524 1.61v.517h6.214v-.518zm3.619 1.292v.517H15.3v-.517z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/PostgreSQL.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "PostgreSQL.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/PostgreSQL.imageset/PostgreSQL.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>PostgreSQL</title><path d="M23.5594 14.7228a.5269.5269 0 0 0-.0563-.1191c-.139-.2632-.4768-.3418-1.0074-.2321-1.6533.3411-2.2935.1312-2.5256-.0191 1.342-2.0482 2.445-4.522 3.0411-6.8297.2714-1.0507.7982-3.5237.1222-4.7316a1.5641 1.5641 0 0 0-.1509-.235C21.6931.9086 19.8007.0248 17.5099.0005c-1.4947-.0158-2.7705.3461-3.1161.4794a9.449 9.449 0 0 0-.5159-.0816 8.044 8.044 0 0 0-1.3114-.1278c-1.1822-.0184-2.2038.2642-3.0498.8406-.8573-.3211-4.7888-1.645-7.2219.0788C.9359 2.1526.3086 3.8733.4302 6.3043c.0409.818.5069 3.334 1.2423 5.7436.4598 1.5065.9387 2.7019 1.4334 3.582.553.9942 1.1259 1.5933 1.7143 1.7895.4474.1491 1.1327.1441 1.8581-.7279.8012-.9635 1.5903-1.8258 1.9446-2.2069.4351.2355.9064.3625 1.39.3772a.0569.0569 0 0 0 .0004.0041 11.0312 11.0312 0 0 0-.2472.3054c-.3389.4302-.4094.5197-1.5002.7443-.3102.064-1.1344.2339-1.1464.8115-.0025.1224.0329.2309.0919.3268.2269.4231.9216.6097 1.015.6331 1.3345.3335 2.5044.092 3.3714-.6787-.017 2.231.0775 4.4174.3454 5.0874.2212.5529.7618 1.9045 2.4692 1.9043.2505 0 .5263-.0291.8296-.0941 1.7819-.3821 2.5557-1.1696 2.855-2.9059.1503-.8707.4016-2.8753.5388-4.1012.0169-.0703.0357-.1207.057-.1362.0007-.0005.0697-.0471.4272.0307a.3673.3673 0 0 0 .0443.0068l.2539.0223.0149.001c.8468.0384 1.9114-.1426 2.5312-.4308.6438-.2988 1.8057-1.0323 1.5951-1.6698zM2.371 11.8765c-.7435-2.4358-1.1779-4.8851-1.2123-5.5719-.1086-2.1714.4171-3.6829 1.5623-4.4927 1.8367-1.2986 4.8398-.5408 6.108-.13-.0032.0032-.0066.0061-.0098.0094-2.0238 2.044-1.9758 5.536-1.9708 5.7495-.0002.0823.0066.1989.0162.3593.0348.5873.0996 1.6804-.0735 2.9184-.1609 1.1504.1937 2.2764.9728 3.0892.0806.0841.1648.1631.2518.2374-.3468.3714-1.1004 1.1926-1.9025 2.1576-.5677.6825-.9597.5517-1.0886.5087-.3919-.1307-.813-.5871-1.2381-1.3223-.4796-.839-.9635-2.0317-1.4155-3.5126zm6.0072 5.0871c-.1711-.0428-.3271-.1132-.4322-.1772.0889-.0394.2374-.0902.4833-.1409 1.2833-.2641 1.4815-.4506 1.9143-1.0002.0992-.126.2116-.2687.3673-.4426a.3549.3549 0 0 0 .0737-.1298c.1708-.1513.2724-.1099.4369-.0417.156.0646.3078.26.3695.4752.0291.1016.0619.2945-.0452.4444-.9043 1.2658-2.2216 1.2494-3.1676 1.0128zm2.094-3.988-.0525.141c-.133.3566-.2567.6881-.3334 1.003-.6674-.0021-1.3168-.2872-1.8105-.8024-.6279-.6551-.9131-1.5664-.7825-2.5004.1828-1.3079.1153-2.4468.079-3.0586-.005-.0857-.0095-.1607-.0122-.2199.2957-.2621 1.6659-.9962 2.6429-.7724.4459.1022.7176.4057.8305.928.5846 2.7038.0774 3.8307-.3302 4.7363-.084.1866-.1633.3629-.2311.5454zm7.3637 4.5725c-.0169.1768-.0358.376-.0618.5959l-.146.4383a.3547.3547 0 0 0-.0182.1077c-.0059.4747-.054.6489-.115.8693-.0634.2292-.1353.4891-.1794 1.0575-.11 1.4143-.8782 2.2267-2.4172 2.5565-1.5155.3251-1.7843-.4968-2.0212-1.2217a6.5824 6.5824 0 0 0-.0769-.2266c-.2154-.5858-.1911-1.4119-.1574-2.5551.0165-.5612-.0249-1.9013-.3302-2.6462.0044-.2932.0106-.5909.019-.8918a.3529.3529 0 0 0-.0153-.1126 1.4927 1.4927 0 0 0-.0439-.208c-.1226-.4283-.4213-.7866-.7797-.9351-.1424-.059-.4038-.1672-.7178-.0869.067-.276.1831-.5875.309-.9249l.0529-.142c.0595-.16.134-.3257.213-.5012.4265-.9476 1.0106-2.2453.3766-5.1772-.2374-1.0981-1.0304-1.6343-2.2324-1.5098-.7207.0746-1.3799.3654-1.7088.5321a5.6716 5.6716 0 0 0-.1958.1041c.0918-1.1064.4386-3.1741 1.7357-4.4823a4.0306 4.0306 0 0 1 .3033-.276.3532.3532 0 0 0 .1447-.0644c.7524-.5706 1.6945-.8506 2.802-.8325.4091.0067.8017.0339 1.1742.081 1.939.3544 3.2439 1.4468 4.0359 2.3827.8143.9623 1.2552 1.9315 1.4312 2.4543-1.3232-.1346-2.2234.1268-2.6797.779-.9926 1.4189.543 4.1729 1.2811 5.4964.1353.2426.2522.4522.2889.5413.2403.5825.5515.9713.7787 1.2552.0696.087.1372.1714.1885.245-.4008.1155-1.1208.3825-1.0552 1.717-.0123.1563-.0423.4469-.0834.8148-.0461.2077-.0702.4603-.0994.7662zm.8905-1.6211c-.0405-.8316.2691-.9185.5967-1.0105a2.8566 2.8566 0 0 0 .135-.0406 1.202 1.202 0 0 0 .1342.103c.5703.3765 1.5823.4213 3.0068.1344-.2016.1769-.5189.3994-.9533.6011-.4098.1903-1.0957.333-1.7473.3636-.7197.0336-1.0859-.0807-1.1721-.151zm.5695-9.2712c-.0059.3508-.0542.6692-.1054 1.0017-.055.3576-.112.7274-.1264 1.1762-.0142.4368.0404.8909.0932 1.3301.1066.887.216 1.8003-.2075 2.7014a3.5272 3.5272 0 0 1-.1876-.3856c-.0527-.1276-.1669-.3326-.3251-.6162-.6156-1.1041-2.0574-3.6896-1.3193-4.7446.3795-.5427 1.3408-.5661 2.1781-.463zm.2284 7.0137a12.3762 12.3762 0 0 0-.0853-.1074l-.0355-.0444c.7262-1.1995.5842-2.3862.4578-3.4385-.0519-.4318-.1009-.8396-.0885-1.2226.0129-.4061.0666-.7543.1185-1.0911.0639-.415.1288-.8443.1109-1.3505.0134-.0531.0188-.1158.0118-.1902-.0457-.4855-.5999-1.938-1.7294-3.253-.6076-.7073-1.4896-1.4972-2.6889-2.0395.5251-.1066 1.2328-.2035 2.0244-.1859 2.0515.0456 3.6746.8135 4.8242 2.2824a.908.908 0 0 1 .0667.1002c.7231 1.3556-.2762 6.2751-2.9867 10.5405zm-8.8166-6.1162c-.025.1794-.3089.4225-.6211.4225a.5821.5821 0 0 1-.0809-.0056c-.1873-.026-.3765-.144-.5059-.3156-.0458-.0605-.1203-.178-.1055-.2844.0055-.0401.0261-.0985.0925-.1488.1182-.0894.3518-.1226.6096-.0867.3163.0441.6426.1938.6113.4186zm7.9305-.4114c.0111.0792-.049.201-.1531.3102-.0683.0717-.212.1961-.4079.2232a.5456.5456 0 0 1-.075.0052c-.2935 0-.5414-.2344-.5607-.3717-.024-.1765.2641-.3106.5611-.352.297-.0414.6111.0088.6356.1851z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Python.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Python.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Python.imageset/Python.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Python</title><path d="M14.25.18l.9.2.73.26.59.3.45.32.34.34.25.34.16.33.1.3.04.26.02.2-.01.13V8.5l-.05.63-.13.55-.21.46-.26.38-.3.31-.33.25-.35.19-.35.14-.33.1-.3.07-.26.04-.21.02H8.77l-.69.05-.59.14-.5.22-.41.27-.33.32-.27.35-.2.36-.15.37-.1.35-.07.32-.04.27-.02.21v3.06H3.17l-.21-.03-.28-.07-.32-.12-.35-.18-.36-.26-.36-.36-.35-.46-.32-.59-.28-.73-.21-.88-.14-1.05-.05-1.23.06-1.22.16-1.04.24-.87.32-.71.36-.57.4-.44.42-.33.42-.24.4-.16.36-.1.32-.05.24-.01h.16l.06.01h8.16v-.83H6.18l-.01-2.75-.02-.37.05-.34.11-.31.17-.28.25-.26.31-.23.38-.2.44-.18.51-.15.58-.12.64-.1.71-.06.77-.04.84-.02 1.27.05zm-6.3 1.98l-.23.33-.08.41.08.41.23.34.33.22.41.09.41-.09.33-.22.23-.34.08-.41-.08-.41-.23-.33-.33-.22-.41-.09-.41.09zm13.09 3.95l.28.06.32.12.35.18.36.27.36.35.35.47.32.59.28.73.21.88.14 1.04.05 1.23-.06 1.23-.16 1.04-.24.86-.32.71-.36.57-.4.45-.42.33-.42.24-.4.16-.36.09-.32.05-.24.02-.16-.01h-8.22v.82h5.84l.01 2.76.02.36-.05.34-.11.31-.17.29-.25.25-.31.24-.38.2-.44.17-.51.15-.58.13-.64.09-.71.07-.77.04-.84.01-1.27-.04-1.07-.14-.9-.2-.73-.25-.59-.3-.45-.33-.34-.34-.25-.34-.16-.33-.1-.3-.04-.25-.02-.2.01-.13v-5.34l.05-.64.13-.54.21-.46.26-.38.3-.32.33-.24.35-.2.35-.14.33-.1.3-.06.26-.04.21-.02.13-.01h5.84l.69-.05.59-.14.5-.21.41-.28.33-.32.27-.35.2-.36.15-.36.1-.35.07-.32.04-.28.02-.21V6.07h2.09l.14.01zm-6.47 14.25l-.23.33-.08.41.08.41.23.33.33.23.41.08.41-.08.33-.23.23-.33.08-.41-.08-.41-.23-.33-.33-.23-.41-.08-.41.08z"/></svg>
+42
supacode/Assets.xcassets/CommandIcons/README.md
··· 1 + # Command Icons 2 + 3 + Brand artwork used by the auto-detected tab icon 4 + (`CommandIconMap` → `TabIconImage`). All SVGs ship as monochrome 5 + templates (`template-rendering-intent: "template"` + 6 + `preserves-vector-representation: true`) so they tint with the 7 + surrounding `foregroundStyle` and adapt to dark / light appearance 8 + without per-mode variants. 9 + 10 + ## Sources 11 + 12 + | Source | License | Imagesets | 13 + | ------ | ------- | --------- | 14 + | [Simple Icons](https://simpleicons.org/) | [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/) | AWS, Azure, Bun, Curl, Deno, Docker, Git, GitHub, Go, GoogleCloud, Gradle, Homebrew, Kubernetes, MySQL, Neovim, Node, Npm, Pnpm, Podman, PostgreSQL, Python, Rust, SQLite, Swift, Terraform, Tmux, TypeScript, Vim, VSCode, Xcode, Yarn, Gemini | 15 + | [Lobe Icons](https://github.com/lobehub/lobe-icons) | [MIT](https://github.com/lobehub/lobe-icons/blob/master/LICENSE) | Amp, ClaudeCode, Codex, GitHubCopilot, Kimi, OpenCode | 16 + 17 + `ClaudeCode` is sourced from the Lobe Icons `claude.svg` mark and 18 + re-authored as a single `fill-rule="evenodd"` path so the `>_` glyph 19 + renders as a native cutout under SwiftUI template tinting (the 20 + upstream two-path version relies on multi-colour `fill` that 21 + `Image(_:)` can't reproduce). 22 + 23 + ## Trademarks 24 + 25 + The image files are released under permissive licenses, but the 26 + **marks themselves remain the trademarks of their respective 27 + holders**. Inclusion here is for tool integration only — surfacing a 28 + brand alongside the matching CLI is a long-standing convention in 29 + terminal apps (iTerm2, Warp, Wezterm, …) and not an endorsement. 30 + Remove or replace any entry whose holder objects. 31 + 32 + ## Adding a new entry 33 + 34 + 1. Drop a single-colour SVG (use `currentColor` or a bare path) into 35 + `<Name>.imageset/`. 36 + 2. Add a `Contents.json` mirroring an existing imageset 37 + (`preserves-vector-representation: true` + 38 + `template-rendering-intent: "template"`). 39 + 3. Reference the asset in `CommandIconMap`: 40 + `TabIconSource(systemSymbol: "<sf-fallback>", assetName: "<Name>")`. 41 + 4. (Optional) Verify how it looks via 42 + **Debug → Icon Catalog** in a DEBUG build.
+16
supacode/Assets.xcassets/CommandIcons/Rust.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Rust.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Rust.imageset/Rust.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Rust</title><path d="M23.8346 11.7033l-1.0073-.6236a13.7268 13.7268 0 00-.0283-.2936l.8656-.8069a.3483.3483 0 00-.1154-.578l-1.1066-.414a8.4958 8.4958 0 00-.087-.2856l.6904-.9587a.3462.3462 0 00-.2257-.5446l-1.1663-.1894a9.3574 9.3574 0 00-.1407-.2622l.49-1.0761a.3437.3437 0 00-.0274-.3361.3486.3486 0 00-.3006-.154l-1.1845.0416a6.7444 6.7444 0 00-.1873-.2268l.2723-1.153a.3472.3472 0 00-.417-.4172l-1.1532.2724a14.0183 14.0183 0 00-.2278-.1873l.0415-1.1845a.3442.3442 0 00-.49-.328l-1.076.491c-.0872-.0476-.1742-.0952-.2623-.1407l-.1903-1.1673A.3483.3483 0 0016.256.955l-.9597.6905a8.4867 8.4867 0 00-.2855-.086l-.414-1.1066a.3483.3483 0 00-.5781-.1154l-.8069.8666a9.2936 9.2936 0 00-.2936-.0284L12.2946.1683a.3462.3462 0 00-.5892 0l-.6236 1.0073a13.7383 13.7383 0 00-.2936.0284L9.9803.3374a.3462.3462 0 00-.578.1154l-.4141 1.1065c-.0962.0274-.1903.0567-.2855.086L7.744.955a.3483.3483 0 00-.5447.2258L7.009 2.348a9.3574 9.3574 0 00-.2622.1407l-1.0762-.491a.3462.3462 0 00-.49.328l.0416 1.1845a7.9826 7.9826 0 00-.2278.1873L3.8413 3.425a.3472.3472 0 00-.4171.4171l.2713 1.1531c-.0628.075-.1255.1509-.1863.2268l-1.1845-.0415a.3462.3462 0 00-.328.49l.491 1.0761a9.167 9.167 0 00-.1407.2622l-1.1662.1894a.3483.3483 0 00-.2258.5446l.6904.9587a13.303 13.303 0 00-.087.2855l-1.1065.414a.3483.3483 0 00-.1155.5781l.8656.807a9.2936 9.2936 0 00-.0283.2935l-1.0073.6236a.3442.3442 0 000 .5892l1.0073.6236c.008.0982.0182.1964.0283.2936l-.8656.8079a.3462.3462 0 00.1155.578l1.1065.4141c.0273.0962.0567.1914.087.2855l-.6904.9587a.3452.3452 0 00.2268.5447l1.1662.1893c.0456.088.0922.1751.1408.2622l-.491 1.0762a.3462.3462 0 00.328.49l1.1834-.0415c.0618.0769.1235.1528.1873.2277l-.2713 1.1541a.3462.3462 0 00.4171.4161l1.153-.2713c.075.0638.151.1255.2279.1863l-.0415 1.1845a.3442.3442 0 00.49.327l1.0761-.49c.087.0486.1741.0951.2622.1407l.1903 1.1662a.3483.3483 0 00.5447.2268l.9587-.6904a9.299 9.299 0 00.2855.087l.414 1.1066a.3452.3452 0 00.5781.1154l.8079-.8656c.0972.0111.1954.0203.2936.0294l.6236 1.0073a.3472.3472 0 00.5892 0l.6236-1.0073c.0982-.0091.1964-.0183.2936-.0294l.8069.8656a.3483.3483 0 00.578-.1154l.4141-1.1066a8.4626 8.4626 0 00.2855-.087l.9587.6904a.3452.3452 0 00.5447-.2268l.1903-1.1662c.088-.0456.1751-.0931.2622-.1407l1.0762.49a.3472.3472 0 00.49-.327l-.0415-1.1845a6.7267 6.7267 0 00.2267-.1863l1.1531.2713a.3472.3472 0 00.4171-.416l-.2713-1.1542c.0628-.0749.1255-.1508.1863-.2278l1.1845.0415a.3442.3442 0 00.328-.49l-.49-1.076c.0475-.0872.0951-.1742.1407-.2623l1.1662-.1893a.3483.3483 0 00.2258-.5447l-.6904-.9587.087-.2855 1.1066-.414a.3462.3462 0 00.1154-.5781l-.8656-.8079c.0101-.0972.0202-.1954.0283-.2936l1.0073-.6236a.3442.3442 0 000-.5892zm-6.7413 8.3551a.7138.7138 0 01.2986-1.396.714.714 0 11-.2997 1.396zm-.3422-2.3142a.649.649 0 00-.7715.5l-.3573 1.6685c-1.1035.501-2.3285.7795-3.6193.7795a8.7368 8.7368 0 01-3.6951-.814l-.3574-1.6684a.648.648 0 00-.7714-.499l-1.473.3158a8.7216 8.7216 0 01-.7613-.898h7.1676c.081 0 .1356-.0141.1356-.088v-2.536c0-.074-.0536-.0881-.1356-.0881h-2.0966v-1.6077h2.2677c.2065 0 1.1065.0587 1.394 1.2088.0901.3533.2875 1.5044.4232 1.8729.1346.413.6833 1.2381 1.2685 1.2381h3.5716a.7492.7492 0 00.1296-.0131 8.7874 8.7874 0 01-.8119.9526zM6.8369 20.024a.714.714 0 11-.2997-1.396.714.714 0 01.2997 1.396zM4.1177 8.9972a.7137.7137 0 11-1.304.5791.7137.7137 0 011.304-.579zm-.8352 1.9813l1.5347-.6824a.65.65 0 00.33-.8585l-.3158-.7147h1.2432v5.6025H3.5669a8.7753 8.7753 0 01-.2834-3.348zm6.7343-.5437V8.7836h2.9601c.153 0 1.0792.1772 1.0792.8697 0 .575-.7107.7815-1.2948.7815zm10.7574 1.4862c0 .2187-.008.4363-.0243.651h-.9c-.09 0-.1265.0586-.1265.1477v.413c0 .973-.5487 1.1846-1.0296 1.2382-.4576.0517-.9648-.1913-1.0275-.4717-.2704-1.5186-.7198-1.8436-1.4305-2.4034.8817-.5599 1.799-1.386 1.799-2.4915 0-1.1936-.819-1.9458-1.3769-2.3153-.7825-.5163-1.6491-.6195-1.883-.6195H5.4682a8.7651 8.7651 0 014.907-2.7699l1.0974 1.151a.648.648 0 00.9182.0213l1.227-1.1743a8.7753 8.7753 0 016.0044 4.2762l-.8403 1.8982a.652.652 0 00.33.8585l1.6178.7188c.0283.2875.0425.577.0425.8717zm-9.3006-9.5993a.7128.7128 0 11.984 1.0316.7137.7137 0 01-.984-1.0316zm8.3389 6.71a.7107.7107 0 01.9395-.3625.7137.7137 0 11-.9405.3635z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/SQLite.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "SQLite.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/SQLite.imageset/SQLite.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>SQLite</title><path d="M21.678.521c-1.032-.92-2.28-.55-3.513.544a8.71 8.71 0 0 0-.547.535c-2.109 2.237-4.066 6.38-4.674 9.544.237.48.422 1.093.544 1.561a13.044 13.044 0 0 1 .164.703s-.019-.071-.096-.296l-.05-.146a1.689 1.689 0 0 0-.033-.08c-.138-.32-.518-.995-.686-1.289-.143.423-.27.818-.376 1.176.484.884.778 2.4.778 2.4s-.025-.099-.147-.442c-.107-.303-.644-1.244-.772-1.464-.217.804-.304 1.346-.226 1.478.152.256.296.698.422 1.186.286 1.1.485 2.44.485 2.44l.017.224a22.41 22.41 0 0 0 .056 2.748c.095 1.146.273 2.13.5 2.657l.155-.084c-.334-1.038-.47-2.399-.41-3.967.09-2.398.642-5.29 1.661-8.304 1.723-4.55 4.113-8.201 6.3-9.945-1.993 1.8-4.692 7.63-5.5 9.788-.904 2.416-1.545 4.684-1.931 6.857.666-2.037 2.821-2.912 2.821-2.912s1.057-1.304 2.292-3.166c-.74.169-1.955.458-2.362.629-.6.251-.762.337-.762.337s1.945-1.184 3.613-1.72C21.695 7.9 24.195 2.767 21.678.521m-18.573.543A1.842 1.842 0 0 0 1.27 2.9v16.608a1.84 1.84 0 0 0 1.835 1.834h9.418a22.953 22.953 0 0 1-.052-2.707c-.006-.062-.011-.141-.016-.2a27.01 27.01 0 0 0-.473-2.378c-.121-.47-.275-.898-.369-1.057-.116-.197-.098-.31-.097-.432 0-.12.015-.245.037-.386a9.98 9.98 0 0 1 .234-1.045l.217-.028c-.017-.035-.014-.065-.031-.097l-.041-.381a32.8 32.8 0 0 1 .382-1.194l.2-.019c-.008-.016-.01-.038-.018-.053l-.043-.316c.63-3.28 2.587-7.443 4.8-9.791.066-.069.133-.128.198-.194Z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Swift.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Swift.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Swift.imageset/Swift.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Swift</title><path d="M7.508 0c-.287 0-.573 0-.86.002-.241.002-.483.003-.724.01-.132.003-.263.009-.395.015A9.154 9.154 0 0 0 4.348.15 5.492 5.492 0 0 0 2.85.645 5.04 5.04 0 0 0 .645 2.848c-.245.48-.4.972-.495 1.5-.093.52-.122 1.05-.136 1.576a35.2 35.2 0 0 0-.012.724C0 6.935 0 7.221 0 7.508v8.984c0 .287 0 .575.002.862.002.24.005.481.012.722.014.526.043 1.057.136 1.576.095.528.25 1.02.495 1.5a5.03 5.03 0 0 0 2.205 2.203c.48.244.97.4 1.498.495.52.093 1.05.124 1.576.138.241.007.483.009.724.01.287.002.573.002.86.002h8.984c.287 0 .573 0 .86-.002.241-.001.483-.003.724-.01a10.523 10.523 0 0 0 1.578-.138 5.322 5.322 0 0 0 1.498-.495 5.035 5.035 0 0 0 2.203-2.203c.245-.48.4-.972.495-1.5.093-.52.124-1.05.138-1.576.007-.241.009-.481.01-.722.002-.287.002-.575.002-.862V7.508c0-.287 0-.573-.002-.86a33.662 33.662 0 0 0-.01-.724 10.5 10.5 0 0 0-.138-1.576 5.328 5.328 0 0 0-.495-1.5A5.039 5.039 0 0 0 21.152.645 5.32 5.32 0 0 0 19.654.15a10.493 10.493 0 0 0-1.578-.138 34.98 34.98 0 0 0-.722-.01C17.067 0 16.779 0 16.492 0H7.508zm6.035 3.41c4.114 2.47 6.545 7.162 5.549 11.131-.024.093-.05.181-.076.272l.002.001c2.062 2.538 1.5 5.258 1.236 4.745-1.072-2.086-3.066-1.568-4.088-1.043a6.803 6.803 0 0 1-.281.158l-.02.012-.002.002c-2.115 1.123-4.957 1.205-7.812-.022a12.568 12.568 0 0 1-5.64-4.838c.649.48 1.35.902 2.097 1.252 3.019 1.414 6.051 1.311 8.197-.002C9.651 12.73 7.101 9.67 5.146 7.191a10.628 10.628 0 0 1-1.005-1.384c2.34 2.142 6.038 4.83 7.365 5.576C8.69 8.408 6.208 4.743 6.324 4.86c4.436 4.47 8.528 6.996 8.528 6.996.154.085.27.154.36.213.085-.215.16-.437.224-.668.708-2.588-.09-5.548-1.893-7.992z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Terraform.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Terraform.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Terraform.imageset/Terraform.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Terraform</title><path d="M1.44 0v7.575l6.561 3.79V3.787zm21.12 4.227l-6.561 3.791v7.574l6.56-3.787zM8.72 4.23v7.575l6.561 3.787V8.018zm0 8.405v7.575L15.28 24v-7.578z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Tmux.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Tmux.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Tmux.imageset/Tmux.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>tmux</title><path d="M24 2.251V10.5H12.45V0h9.3A2.251 2.251 0 0 1 24 2.251zM12.45 11.4H24v10.5h-.008A2.25 2.25 0 0 1 21.75 24H2.25a2.247 2.247 0 0 1-2.242-2.1H0V2.251A2.251 2.251 0 0 1 2.25 0h9.3v21.6h.9V11.4zm11.242 10.5H.308a1.948 1.948 0 0 0 1.942 1.8h19.5a1.95 1.95 0 0 0 1.942-1.8z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/TypeScript.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "TypeScript.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/TypeScript.imageset/TypeScript.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>TypeScript</title><path d="M1.125 0C.502 0 0 .502 0 1.125v21.75C0 23.498.502 24 1.125 24h21.75c.623 0 1.125-.502 1.125-1.125V1.125C24 .502 23.498 0 22.875 0zm17.363 9.75c.612 0 1.154.037 1.627.111a6.38 6.38 0 0 1 1.306.34v2.458a3.95 3.95 0 0 0-.643-.361 5.093 5.093 0 0 0-.717-.26 5.453 5.453 0 0 0-1.426-.2c-.3 0-.573.028-.819.086a2.1 2.1 0 0 0-.623.242c-.17.104-.3.229-.393.374a.888.888 0 0 0-.14.49c0 .196.053.373.156.529.104.156.252.304.443.444s.423.276.696.41c.273.135.582.274.926.416.47.197.892.407 1.266.628.374.222.695.473.963.753.268.279.472.598.614.957.142.359.214.776.214 1.253 0 .657-.125 1.21-.373 1.656a3.033 3.033 0 0 1-1.012 1.085 4.38 4.38 0 0 1-1.487.596c-.566.12-1.163.18-1.79.18a9.916 9.916 0 0 1-1.84-.164 5.544 5.544 0 0 1-1.512-.493v-2.63a5.033 5.033 0 0 0 3.237 1.2c.333 0 .624-.03.872-.09.249-.06.456-.144.623-.25.166-.108.29-.234.373-.38a1.023 1.023 0 0 0-.074-1.089 2.12 2.12 0 0 0-.537-.5 5.597 5.597 0 0 0-.807-.444 27.72 27.72 0 0 0-1.007-.436c-.918-.383-1.602-.852-2.053-1.405-.45-.553-.676-1.222-.676-2.005 0-.614.123-1.141.369-1.582.246-.441.58-.804 1.004-1.089a4.494 4.494 0 0 1 1.47-.629 7.536 7.536 0 0 1 1.77-.201zm-15.113.188h9.563v2.166H9.506v9.646H6.789v-9.646H3.375z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/VSCode.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "VSCode.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/VSCode.imageset/VSCode.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Visual Studio Code</title><path d="M23.15 2.587L18.21.21a1.494 1.494 0 0 0-1.705.29l-9.46 8.63-4.12-3.128a.999.999 0 0 0-1.276.057L.327 7.261A1 1 0 0 0 .326 8.74L3.899 12 .326 15.26a1 1 0 0 0 .001 1.479L1.65 17.94a.999.999 0 0 0 1.276.057l4.12-3.128 9.46 8.63a1.492 1.492 0 0 0 1.704.29l4.942-2.377A1.5 1.5 0 0 0 24 20.06V3.939a1.5 1.5 0 0 0-.85-1.352zm-5.146 14.861L10.826 12l7.178-5.448v10.896z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Vim.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Vim.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Vim.imageset/Vim.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Vim</title><path d="M24 11.986h-.027l-4.318-4.318 4.303-4.414V1.461l-.649-.648h-8.198l-.66.605v1.045L12.015.027V0L12 .014 11.986 0v.027l-1.29 1.291-.538-.539H2.035l-.638.692v1.885l.616.616h.72v5.31L.027 11.987H0L.014 12 0 12.014h.027l2.706 2.706v6.467l.907.523h2.322l1.857-1.904 4.166 4.166V24l.015-.014.014.014v-.028l2.51-2.509h.485c.111 0 .211-.07.25-.179l.146-.426c.028-.084.012-.172-.037-.239l1.462-1.462-.612 1.962c-.043.141.036.289.177.332.025.008.052.012.078.012h1.824c.106-.001.201-.064.243-.163l.165-.394c.025-.065.024-.138-.004-.203-.027-.065-.08-.116-.146-.142-.029-.012-.062-.019-.097-.02h-.075l.84-2.644h1.232l-1.016 3.221c-.043.141.036.289.176.332.025.008.052.012.079.012h2.002c.11 0 .207-.066.248-.17l.164-.428c.051-.138-.021-.29-.158-.341-.029-.011-.06-.017-.091-.017h-.145l1.131-3.673c.027-.082.012-.173-.039-.24l-.375-.504-.003-.005c-.051-.064-.127-.102-.209-.102h-1.436c-.071 0-.141.03-.19.081l-.4.439h-.624l-.042-.046 4.445-4.445H24L23.986 12l.014-.014zM9.838 21.139l1.579-4.509h-.501l.297-.304h1.659l-1.563 4.555h.623l-.079.258H9.838zm3.695-7.516l.15.151-.269.922-.225.226h-.969l-.181-.181.311-.871.288-.247h.895zM5.59 20.829H3.877l-.262-.15V3.091H2.379l-.1-.1V1.815l.143-.154h7.371l.213.214v1.108l-.142.173H8.785v8.688l8.807-8.688h-2.086l-.175-.188V1.805l.121-.111h7.49l.132.133v1.07L12.979 13.25h-.373c-.015-.001-.028 0-.042.001l-.02.003c-.045.01-.086.03-.119.06l-.343.295-.004.003c-.033.031-.059.069-.073.111l-.296.83-6.119 6.276zm14.768-3.952l.474-.519h1.334l.309.415-1.265 4.107h.493l-.08.209H19.84l1.124-3.564h-2.015l-1.077 3.391h.424l-.073.174h-1.605l1.107-3.548h-2.096l-1.062 3.339h.436l-.072.209H13.27l1.514-4.46H14.198l.091-.271h1.65l.519.537h.906l.491-.554h1.061l.489.535h.953z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Xcode.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Xcode.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Xcode.imageset/Xcode.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Xcode</title><path d="M19.06 5.3327c.4517-.1936.7744-.2581 1.097-.1936.5163.1291.7744.5163.968.7098.1936.3872.9034.7744 1.2261.8389.2581.0645.7098-.6453 1.0325-1.2906.3227-.5808.5163-1.3552.4517-1.5488-.0645-.1936-.968-.5808-1.1616-.5808-.1291 0-.3872.1291-.8389.0645-.4517-.0645-.9034-.5808-1.1616-.968-.4517-.6453-1.097-1.0325-1.6778-1.3552-.6453-.3227-1.3552-.5163-2.065-.6453-1.0325-.2581-2.065-.4517-3.0975-.3227-.5808.0645-1.2906.1291-1.8069.3227-.0645 0-.1936.1936-.0645.1936s.5808.0645.5808.0645-.5807.1292-.5807.2583c0 .1291.0645.1291.1291.1291.0645 0 1.4842-.0645 2.065 0 .6453.1291 1.3552.4517 1.8069 1.2261.7744 1.4197.4517 2.7749.2581 3.2266-.968 2.1295-8.6472 15.2294-9.0344 16.1328-.3873.9034-.5163 1.4842.5807 2.065s1.6778.3227 2.0005-.0645c.3872-.5163 7.0339-17.1654 9.2925-18.2624zm-3.6138 8.7117h1.5488c1.0325 0 1.2261.5163 1.2261.7098.0645.5163-.1936 1.1616-1.2261 1.1616h-.968l.7744 1.2906c.4517.7744.2581 1.1616 0 1.4197-.3872.3872-1.2261.3872-1.6778-.4517l-.9034-1.5488c-.6453 1.4197-1.2906 2.9684-2.065 4.7753h4.0009c1.9359 0 3.5492-1.6133 3.5492-3.5492V6.5588c-.0645-.1291-.1936-.0645-.2581 0-.3872.4517-1.4842 2.0004-4.001 7.4856zm-9.8087 8.0019h-.3227c-2.3231 0-4.1945-1.8714-4.1945-4.1945V7.0105c0-2.3231 1.8714-4.1945 4.1945-4.1945h9.3571c-.1936-.1936-.968-.5163-1.7423-.4517-.3227 0-.968.1291-1.3552-.1291-.3872-.3227-.3227-.5163-.9034-.5163H4.9277c-2.6458 0-4.7753 2.1295-4.7753 4.7753v11.7447c0 2.6458 2.1295 4.7753 4.4527 4.7108.6452 0 .8388-.5162 1.0324-.9034zM20.4152 6.9459v10.9058c0 2.3231-1.8714 4.1945-4.1945 4.1945H11.897s-.3872 1.0325.8389 1.0325h3.8719c2.6458 0 4.7753-2.1295 4.7753-4.7753V8.8173c.0646-.9034-.7098-1.4842-.9679-1.8714zm-18.5851.0646v10.8413c0 1.9359 1.6133 3.5492 3.5492 3.5492h.5808c0-.0645.7744-1.4197 2.4522-4.2591.1936-.3872.4517-.7744.7098-1.2261H4.4114c-.5808 0-.9034-.3872-.968-.7098-.1291-.5163.1936-1.1616.9034-1.1616h2.3877l3.033-5.2916s-.7098-1.2906-.9034-1.6133c-.2582-.4517-.1291-.9034.129-1.1615.3872-.3872 1.0325-.5808 1.6778.4517l.2581.3872.2581-.3872c.5808-.8389.968-.7744 1.2906-.7098.5163.1291.8389.7098.3872 1.6133L8.864 14.0444h1.3552c.4517-.7744.9034-1.5488 1.3552-2.3877-.0645-.3227-.1291-.7098-.0645-1.0325.0645-.5163.3227-.968.6453-1.3552l.3872.6453c1.2261-2.1295 2.1295-3.9364 2.3877-4.6463.1291-.3872.3227-1.1616.1291-1.8069H5.3794c-2.0005.0001-3.5493 1.6134-3.5493 3.5494zM4.605 17.7872c0-.0645.7744-1.4197.7744-1.4197 1.2261-.3227 1.8069.4517 1.8714.5163 0 0-.8389 1.4842-1.097 1.7423s-.5808.3227-.9034.2581c-.5164-.129-.839-.6453-.6454-1.097z"/></svg>
+16
supacode/Assets.xcassets/CommandIcons/Yarn.imageset/Contents.json
··· 1 + { 2 + "images" : [ 3 + { 4 + "filename" : "Yarn.svg", 5 + "idiom" : "universal" 6 + } 7 + ], 8 + "info" : { 9 + "author" : "xcode", 10 + "version" : 1 11 + }, 12 + "properties" : { 13 + "preserves-vector-representation" : true, 14 + "template-rendering-intent" : "template" 15 + } 16 + }
+1
supacode/Assets.xcassets/CommandIcons/Yarn.imageset/Yarn.svg
··· 1 + <svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Yarn</title><path d="M12 0C5.375 0 0 5.375 0 12s5.375 12 12 12 12-5.375 12-12S18.625 0 12 0zm.768 4.105c.183 0 .363.053.525.157.125.083.287.185.755 1.154.31-.088.468-.042.551-.019.204.056.366.19.463.375.477.917.542 2.553.334 3.605-.241 1.232-.755 2.029-1.131 2.576.324.329.778.899 1.117 1.825.278.774.31 1.478.273 2.015a5.51 5.51 0 0 0 .602-.329c.593-.366 1.487-.917 2.553-.931.714-.009 1.269.445 1.353 1.103a1.23 1.23 0 0 1-.945 1.362c-.649.158-.95.278-1.821.843-1.232.797-2.539 1.242-3.012 1.39a1.686 1.686 0 0 1-.704.343c-.737.181-3.266.315-3.466.315h-.046c-.783 0-1.214-.241-1.45-.491-.658.329-1.51.19-2.122-.134a1.078 1.078 0 0 1-.58-1.153 1.243 1.243 0 0 1-.153-.195c-.162-.25-.528-.936-.454-1.946.056-.723.556-1.367.88-1.71a5.522 5.522 0 0 1 .408-2.256c.306-.727.885-1.348 1.32-1.737-.32-.537-.644-1.367-.329-2.21.227-.602.412-.936.82-1.08h-.005c.199-.074.389-.153.486-.259a3.418 3.418 0 0 1 2.298-1.103c.037-.093.079-.185.125-.283.31-.658.639-1.029 1.024-1.168a.94.94 0 0 1 .328-.06zm.006.7c-.507.016-1.001 1.519-1.001 1.519s-1.27-.204-2.266.871c-.199.218-.468.334-.746.44-.079.028-.176.023-.417.672-.371.991.625 2.094.625 2.094s-1.186.839-1.626 1.881c-.486 1.144-.338 2.261-.338 2.261s-.843.732-.899 1.487c-.051.663.139 1.2.343 1.515.227.343.51.176.51.176s-.561.653-.037.931c.477.25 1.283.394 1.71-.037.31-.31.371-1.001.486-1.283.028-.065.12.111.209.199.097.093.264.195.264.195s-.755.324-.445 1.066c.102.246.468.403 1.066.398.222-.005 2.664-.139 3.313-.296.375-.088.505-.283.505-.283s1.566-.431 2.998-1.357c.917-.598 1.293-.76 2.034-.936.612-.148.57-1.098-.241-1.084-.839.009-1.575.44-2.196.825-1.163.718-1.742.672-1.742.672l-.018-.032c-.079-.13.371-1.293-.134-2.678-.547-1.515-1.413-1.881-1.344-1.997.297-.5 1.038-1.297 1.334-2.78.176-.899.13-2.377-.269-3.151-.074-.144-.732.241-.732.241s-.616-1.371-.788-1.483a.271.271 0 0 0-.157-.046z"/></svg>
+55
supacode/Features/Debug/BusinessLogic/DebugWindowManager.swift
··· 1 + import AppKit 2 + import ComposableArchitecture 3 + import SwiftUI 4 + 5 + #if DEBUG 6 + 7 + /// Manages the singleton Debug Window. Lifecycle mirrors 8 + /// `SettingsWindowManager`: cache the `NSWindow`, deminiaturise + 9 + /// front it on subsequent shows, never release on close so opening 10 + /// is cheap. Configured once during app bootstrap with the root 11 + /// store so the window can mirror the user's appearance setting. 12 + @MainActor 13 + final class DebugWindowManager { 14 + static let shared = DebugWindowManager() 15 + 16 + private var window: NSWindow? 17 + private var store: StoreOf<AppFeature>? 18 + 19 + private init() {} 20 + 21 + func configure(store: StoreOf<AppFeature>) { 22 + self.store = store 23 + } 24 + 25 + func show() { 26 + if let existing = window { 27 + if existing.isMiniaturized { 28 + existing.deminiaturize(nil) 29 + } 30 + existing.makeKeyAndOrderFront(nil) 31 + return 32 + } 33 + 34 + guard let store else { return } 35 + let host = NSHostingController(rootView: DebugView(store: store)) 36 + let new = NSWindow(contentViewController: host) 37 + new.title = "Prowl Debug" 38 + new.identifier = NSUserInterfaceItemIdentifier("debug") 39 + new.styleMask = [.titled, .closable, .miniaturizable, .resizable] 40 + new.tabbingMode = .disallowed 41 + new.toolbarStyle = .unified 42 + new.toolbar = NSToolbar(identifier: "DebugToolbar") 43 + if #unavailable(macOS 15.0) { 44 + new.toolbar?.showsBaselineSeparator = false 45 + } 46 + new.isReleasedWhenClosed = false 47 + new.setContentSize(NSSize(width: 800, height: 600)) 48 + new.minSize = NSSize(width: 700, height: 500) 49 + new.center() 50 + new.makeKeyAndOrderFront(nil) 51 + window = new 52 + } 53 + } 54 + 55 + #endif
+16
supacode/Features/Debug/Views/DebugSection.swift
··· 1 + import Foundation 2 + 3 + #if DEBUG 4 + 5 + /// Sidebar entries for the Debug Window. Add a case here, an entry 6 + /// in `DebugView`'s sidebar list, and a switch arm in the detail 7 + /// area to register a new debug surface. 8 + enum DebugSection: Hashable { 9 + /// Catalogue of every `CommandIconMap` entry alongside its rendered 10 + /// icon. Lets us eyeball the auto-detected tab-icon set after 11 + /// adding new branded artwork or sanity-checking that an asset 12 + /// actually paints in the SwiftUI runtime. 13 + case iconCatalog 14 + } 15 + 16 + #endif
+47
supacode/Features/Debug/Views/DebugView.swift
··· 1 + import ComposableArchitecture 2 + import SwiftUI 3 + 4 + #if DEBUG 5 + 6 + /// Root of the Debug Window. NavigationSplitView with a sidebar so 7 + /// future debug surfaces (detector state, analytics events, 8 + /// ghostty internals…) can be added by extending `DebugSection` 9 + /// and the sidebar list / detail switch below. The store is held 10 + /// only to mirror the app-wide appearance setting on this window; 11 + /// individual debug surfaces don't have to thread it. 12 + struct DebugView: View { 13 + let store: StoreOf<AppFeature> 14 + @State private var selection: DebugSection = .iconCatalog 15 + 16 + var body: some View { 17 + NavigationSplitView(columnVisibility: .constant(.all)) { 18 + List(selection: $selection) { 19 + Label("Icon Catalog", systemImage: "square.grid.2x2") 20 + .tag(DebugSection.iconCatalog) 21 + } 22 + .listStyle(.sidebar) 23 + .frame(minWidth: 200, maxHeight: .infinity) 24 + .navigationSplitViewColumnWidth(200) 25 + } detail: { 26 + Group { 27 + switch selection { 28 + case .iconCatalog: 29 + IconCatalogView() 30 + .navigationTitle("Icon Catalog") 31 + .navigationSubtitle("CommandIconMap entries (DEBUG)") 32 + } 33 + } 34 + .frame(maxWidth: .infinity, maxHeight: .infinity) 35 + } 36 + .navigationSplitViewStyle(.balanced) 37 + .frame(minWidth: 700, minHeight: 500) 38 + .background { 39 + // Standalone NSWindow doesn't pick up `.preferredColorScheme` 40 + // (only WindowGroup scenes do), so route through the same 41 + // bridge SettingsView uses to honour the user's appearance. 42 + WindowAppearanceSetter(colorScheme: store.settings.appearanceMode.colorScheme) 43 + } 44 + } 45 + } 46 + 47 + #endif
+74
supacode/Features/Debug/Views/IconCatalogView.swift
··· 1 + import SwiftUI 2 + 3 + #if DEBUG 4 + 5 + /// DEBUG-only catalogue of the auto-detected tab icons. Each row 6 + /// renders a `CommandIconMap` entry through the same `TabIconImage` 7 + /// the actual tab UI uses, so the asset / SF Symbol fallback / size 8 + /// behaviour shown here matches what users see on a real tab. 9 + /// 10 + /// `.searchable` puts the filter field in the window toolbar 11 + /// (NavigationSplitView's detail toolbar slot on macOS). Filtering 12 + /// is a case-insensitive substring match on the token, so typing 13 + /// `git` surfaces `git`, `gh`, `lazygit`, … 14 + struct IconCatalogView: View { 15 + @State private var searchText: String = "" 16 + 17 + var body: some View { 18 + let entries = filteredEntries 19 + ScrollView { 20 + if entries.isEmpty { 21 + ContentUnavailableView.search(text: searchText) 22 + .frame(maxWidth: .infinity, minHeight: 200) 23 + } else { 24 + LazyVStack(spacing: 0) { 25 + ForEach(entries, id: \.token) { entry in 26 + IconCatalogRow(token: entry.token, icon: entry.icon) 27 + Divider().padding(.leading, 60) 28 + } 29 + } 30 + .padding(.horizontal) 31 + } 32 + } 33 + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) 34 + .searchable(text: $searchText, placement: .toolbar, prompt: "Filter commands") 35 + } 36 + 37 + private var filteredEntries: [(token: String, icon: TabIconSource)] { 38 + let all = CommandIconMap.debugAllEntries 39 + let needle = searchText.trimmingCharacters(in: .whitespacesAndNewlines) 40 + guard !needle.isEmpty else { return all } 41 + return all.filter { $0.token.localizedCaseInsensitiveContains(needle) } 42 + } 43 + } 44 + 45 + private struct IconCatalogRow: View { 46 + let token: String 47 + let icon: TabIconSource 48 + 49 + var body: some View { 50 + HStack(spacing: 16) { 51 + TabIconImage(rawName: icon.storageString, pointSize: 24) 52 + .foregroundStyle(.primary) 53 + .frame(width: 32, height: 32, alignment: .center) 54 + VStack(alignment: .leading, spacing: 2) { 55 + Text(token) 56 + .font(.body.monospaced().weight(.semibold)) 57 + Text(detailLine) 58 + .font(.caption.monospaced()) 59 + .foregroundStyle(.secondary) 60 + } 61 + Spacer(minLength: 0) 62 + } 63 + .padding(.vertical, 10) 64 + } 65 + 66 + private var detailLine: String { 67 + if let asset = icon.assetName { 68 + return "asset:\(asset) · fallback sf:\(icon.systemSymbol)" 69 + } 70 + return "sf:\(icon.systemSymbol)" 71 + } 72 + } 73 + 74 + #endif
+14 -8
supacode/Features/Shelf/Views/ShelfSpineView.swift
··· 350 350 } 351 351 .accessibilityHidden(true) 352 352 } else { 353 - Image(systemName: tab.icon ?? ShelfMetrics.defaultTabIcon) 354 - .imageScale(.medium) 355 - .foregroundStyle(foregroundTint) 356 - // Dim tabs without a hotkey when ⌘ is held, so the "this slot 357 - // can't be jumped to via Cmd+N" affordance is legible without 358 - // shifting any layout. 359 - .opacity(commandKeyObserver.isPressed && hotkeyIndex == nil ? 0.45 : 1) 360 - .accessibilityHidden(true) 353 + TabIconImage( 354 + rawName: tab.icon ?? ShelfMetrics.defaultTabIcon, 355 + pointSize: ShelfMetrics.tabIconPointSize 356 + ) 357 + .foregroundStyle(foregroundTint) 358 + // Dim tabs without a hotkey when ⌘ is held, so the "this slot 359 + // can't be jumped to via Cmd+N" affordance is legible without 360 + // shifting any layout. 361 + .opacity(commandKeyObserver.isPressed && hotkeyIndex == nil ? 0.45 : 1) 362 + .accessibilityHidden(true) 361 363 } 362 364 } 363 365 ··· 418 420 static let headerMaxLength: CGFloat = 160 419 421 /// Fallback icon when a tab has no custom icon set. 420 422 static let defaultTabIcon: String = "terminal" 423 + /// Point size used by `TabIconImage` for both the SF Symbol 424 + /// (`.font(.system(size:))`) and the asset (`.frame`) branches so 425 + /// branded artwork visually matches the SF-Symbol fallback. 426 + static let tabIconPointSize: CGFloat = 18 421 427 }
+141
supacode/Features/Terminal/Models/CommandIconMap.swift
··· 1 + import Foundation 2 + 3 + /// Resolves a tab icon from a command title surfaced by the 4 + /// auto-detector (typically the OSC 2 title set by the shell's 5 + /// `preexec`). 6 + /// 7 + /// Lookup is case-insensitive on the *first whitespace-delimited 8 + /// token*. Examples: `"swift build"` and `"swift test"` route through 9 + /// the `swift` entry; `"claude"` routes through `claude`. 10 + /// 11 + /// Returns `nil` when nothing matches; the auto-detector then leaves 12 + /// the tab's existing icon untouched (selection-2 semantics — a 13 + /// previously-detected icon is preserved across unknown commands). 14 + enum CommandIconMap { 15 + static func iconForFirstToken(_ title: String) -> TabIconSource? { 16 + let token = firstToken(of: title).lowercased() 17 + return firstTokenMapping[token] 18 + } 19 + 20 + private static func firstToken(of title: String) -> String { 21 + title 22 + .split(separator: " ", omittingEmptySubsequences: true) 23 + .first 24 + .map(String.init) 25 + ?? title 26 + } 27 + 28 + /// First-token table. Grouped by category and alphabetised within 29 + /// each group. SF Symbols only at this layer keep things glanceable 30 + /// before asset rendering is wired; entries that ship branded 31 + /// artwork should add `assetName:` and let renderers prefer it. 32 + private static let firstTokenMapping: [String: TabIconSource] = [ 33 + // Coding agents 34 + "claude": TabIconSource(systemSymbol: "sparkle", assetName: "ClaudeCode"), 35 + "codex": TabIconSource(systemSymbol: "sparkle", assetName: "Codex"), 36 + "gemini": TabIconSource(systemSymbol: "sparkle", assetName: "Gemini"), 37 + "opencode": TabIconSource(systemSymbol: "sparkle", assetName: "OpenCode"), 38 + "amp": TabIconSource(systemSymbol: "sparkle", assetName: "Amp"), 39 + "kimi": TabIconSource(systemSymbol: "sparkle", assetName: "Kimi"), 40 + "copilot": TabIconSource(systemSymbol: "sparkle", assetName: "GitHubCopilot"), 41 + "aider": TabIconSource(systemSymbol: "sparkle"), 42 + "droid": TabIconSource(systemSymbol: "sparkle"), 43 + 44 + // Editors / IDEs / pagers 45 + "vim": TabIconSource(systemSymbol: "pencil.and.scribble", assetName: "Vim"), 46 + "nvim": TabIconSource(systemSymbol: "pencil.and.scribble", assetName: "Neovim"), 47 + "nano": TabIconSource(systemSymbol: "pencil.and.scribble"), 48 + "code": TabIconSource( 49 + systemSymbol: "chevron.left.forwardslash.chevron.right", 50 + assetName: "VSCode" 51 + ), 52 + 53 + // Package managers / runners — `npx` and `bunx` are the 54 + // ad-hoc-package execution counterparts to `npm` and `bun`, 55 + // share the icons. `pip` is Python's package manager and rides 56 + // on the Python asset. 57 + "npm": TabIconSource(systemSymbol: "shippingbox", assetName: "Npm"), 58 + "npx": TabIconSource(systemSymbol: "shippingbox", assetName: "Npm"), 59 + "pnpm": TabIconSource(systemSymbol: "shippingbox", assetName: "Pnpm"), 60 + "yarn": TabIconSource(systemSymbol: "shippingbox", assetName: "Yarn"), 61 + "bun": TabIconSource(systemSymbol: "shippingbox", assetName: "Bun"), 62 + "bunx": TabIconSource(systemSymbol: "shippingbox", assetName: "Bun"), 63 + "brew": TabIconSource(systemSymbol: "shippingbox", assetName: "Homebrew"), 64 + "pip": TabIconSource(systemSymbol: "shippingbox", assetName: "Python"), 65 + "pip3": TabIconSource(systemSymbol: "shippingbox", assetName: "Python"), 66 + 67 + // Runtime / version managers 68 + "mise": TabIconSource(systemSymbol: "arrow.up.arrow.down"), 69 + 70 + // Languages / runtimes 71 + "node": TabIconSource(systemSymbol: "terminal", assetName: "Node"), 72 + "go": TabIconSource(systemSymbol: "terminal", assetName: "Go"), 73 + "deno": TabIconSource(systemSymbol: "terminal", assetName: "Deno"), 74 + "python": TabIconSource(systemSymbol: "terminal", assetName: "Python"), 75 + "python3": TabIconSource(systemSymbol: "terminal", assetName: "Python"), 76 + 77 + // Terminal multiplexers 78 + "tmux": TabIconSource(systemSymbol: "rectangle.split.3x1", assetName: "Tmux"), 79 + 80 + // VCS — `lazygit` is a TUI front-end for git, share the icon. 81 + "git": TabIconSource(systemSymbol: "arrow.triangle.branch", assetName: "Git"), 82 + "gh": TabIconSource(systemSymbol: "arrow.triangle.branch", assetName: "GitHub"), 83 + "lazygit": TabIconSource(systemSymbol: "arrow.triangle.branch", assetName: "Git"), 84 + 85 + // Build tools 86 + "make": TabIconSource(systemSymbol: "hammer"), 87 + "swift": TabIconSource(systemSymbol: "hammer", assetName: "Swift"), 88 + "cargo": TabIconSource(systemSymbol: "hammer", assetName: "Rust"), 89 + "xcodebuild": TabIconSource(systemSymbol: "hammer", assetName: "Xcode"), 90 + "gradle": TabIconSource(systemSymbol: "hammer", assetName: "Gradle"), 91 + "tsc": TabIconSource(systemSymbol: "hammer", assetName: "TypeScript"), 92 + 93 + // Container / orchestration — `lazydocker` is a TUI for docker, 94 + // shares the icon. 95 + "docker": TabIconSource(systemSymbol: "shippingbox.fill", assetName: "Docker"), 96 + "kubectl": TabIconSource(systemSymbol: "shippingbox.fill", assetName: "Kubernetes"), 97 + "podman": TabIconSource(systemSymbol: "shippingbox.fill", assetName: "Podman"), 98 + "lazydocker": TabIconSource(systemSymbol: "shippingbox.fill", assetName: "Docker"), 99 + 100 + // IaC / cloud CLIs 101 + "terraform": TabIconSource(systemSymbol: "cloud", assetName: "Terraform"), 102 + "aws": TabIconSource(systemSymbol: "cloud", assetName: "AWS"), 103 + "az": TabIconSource(systemSymbol: "cloud", assetName: "Azure"), 104 + "gcloud": TabIconSource(systemSymbol: "cloud", assetName: "GoogleCloud"), 105 + 106 + // Network / remote 107 + "ssh": TabIconSource(systemSymbol: "network"), 108 + "mosh": TabIconSource(systemSymbol: "network"), 109 + "curl": TabIconSource(systemSymbol: "network", assetName: "Curl"), 110 + "wget": TabIconSource(systemSymbol: "arrow.down.circle"), 111 + 112 + // Process / system viewers 113 + "htop": TabIconSource(systemSymbol: "waveform.path.ecg"), 114 + "btop": TabIconSource(systemSymbol: "waveform.path.ecg"), 115 + "top": TabIconSource(systemSymbol: "waveform.path.ecg"), 116 + 117 + // Database REPLs 118 + "psql": TabIconSource(systemSymbol: "cylinder.split.1x2", assetName: "PostgreSQL"), 119 + "mysql": TabIconSource(systemSymbol: "cylinder.split.1x2", assetName: "MySQL"), 120 + "sqlite3": TabIconSource(systemSymbol: "cylinder.split.1x2", assetName: "SQLite"), 121 + 122 + // Logs / streams 123 + "tail": TabIconSource(systemSymbol: "text.justifyleft"), 124 + "journalctl": TabIconSource(systemSymbol: "text.justifyleft"), 125 + ] 126 + } 127 + 128 + #if DEBUG 129 + 130 + extension CommandIconMap { 131 + /// All first-token mapping entries, sorted alphabetically by 132 + /// token. Surfaced for the Debug Window's Icon Catalog so the 133 + /// auto-detected set can be eyeballed in one place. 134 + static var debugAllEntries: [(token: String, icon: TabIconSource)] { 135 + firstTokenMapping 136 + .map { (token: $0.key, icon: $0.value) } 137 + .sorted { $0.token < $1.token } 138 + } 139 + } 140 + 141 + #endif
+53
supacode/Features/Terminal/Models/TabIconSource.swift
··· 1 + import Foundation 2 + 3 + /// Specifies the artwork to use for a tab icon. `systemSymbol` is an 4 + /// always-available SF Symbol fallback; `assetName` is an optional, 5 + /// more specific PNG/SVG shipped in the asset catalog (used for 6 + /// branded CLI tools like docker/git/claude where stock SF Symbols 7 + /// don't read well). 8 + /// 9 + /// Renderers prefer `assetName` when present, falling back to 10 + /// `systemSymbol` when the asset is missing or asset rendering isn't 11 + /// yet wired into a particular call site. 12 + struct TabIconSource: Equatable, Hashable, Sendable { 13 + /// SF Symbol drawn via `Image(systemName:)`. 14 + let systemSymbol: String 15 + /// Asset catalog entry. When set, renderers paint `Image(_:)` for 16 + /// this name and ignore `systemSymbol`; when missing, they fall 17 + /// back to the SF Symbol. 18 + let assetName: String? 19 + 20 + init(systemSymbol: String, assetName: String? = nil) { 21 + self.systemSymbol = systemSymbol 22 + self.assetName = assetName 23 + } 24 + 25 + /// Serialised form stored in `TerminalTabItem.icon`. SF Symbols are 26 + /// stored bare (so existing `tab.icon = "terminal"` keeps working 27 + /// for the user-icon-picker path); assets carry a marker so the 28 + /// renderer can switch APIs. 29 + var storageString: String { 30 + if let assetName { 31 + return ResolvedTabIcon.assetMarker + assetName 32 + } 33 + return systemSymbol 34 + } 35 + } 36 + 37 + /// What `TerminalTabItem.icon` resolves to once parsed by the 38 + /// renderer. Built from a stored string via `parse(_:)` — the inverse 39 + /// of `TabIconSource.storageString`. Lives next to `TabIconSource` 40 + /// because the two share the marker convention. 41 + enum ResolvedTabIcon: Equatable, Hashable, Sendable { 42 + case systemSymbol(String) 43 + case asset(name: String) 44 + 45 + static let assetMarker = "@asset:" 46 + 47 + static func parse(_ raw: String) -> ResolvedTabIcon { 48 + if raw.hasPrefix(assetMarker) { 49 + return .asset(name: String(raw.dropFirst(assetMarker.count))) 50 + } 51 + return .systemSymbol(raw) 52 + } 53 + }
+114
supacode/Features/Terminal/Models/WorktreeTerminalState.swift
··· 50 50 /// Surfaces running a tracked Custom Command. The stored name is surfaced as a success 51 51 /// toast when the command exits with code 0. One-shot: removed on the first finish event. 52 52 private var pendingCustomCommands: [UUID: String] = [:] 53 + /// Per-surface set of titles known to be the shell's idle prompt 54 + /// (the title `precmd` restores between commands). Populated by 55 + /// observing the first title that arrives after each 56 + /// `command_finished` — reliably the precmd-set prompt. Subsequent 57 + /// occurrences are skipped so they can't clobber the icon set by a 58 + /// real command. 59 + private var learnedIdleTitlesBySurface: [UUID: Set<String>] = [:] 60 + /// Surfaces whose next title-change should be added to 61 + /// `learnedIdleTitlesBySurface`. Armed by `command_finished`, 62 + /// consumed by the next title arrival. 63 + private var awaitingIdleTitleLearningBySurface: Set<UUID> = [] 53 64 var hasUnseenNotification: Bool { 54 65 notifications.contains { !$0.isRead } 55 66 } ··· 525 536 } catch { 526 537 newSurface.closeSurface() 527 538 surfaces.removeValue(forKey: newSurface.id) 539 + cleanupCommandDetectorState(forSurfaceId: newSurface.id) 528 540 return nil 529 541 } 530 542 } ··· 593 605 } catch { 594 606 newSurface.closeSurface() 595 607 surfaces.removeValue(forKey: newSurface.id) 608 + cleanupCommandDetectorState(forSurfaceId: newSurface.id) 596 609 597 610 return false 598 611 } ··· 987 1000 if self.focusedSurfaceIdByTab[tabId] == view.id { 988 1001 self.tabManager.updateTitle(tabId, title: title) 989 1002 } 1003 + self.noteTitleForCommandDetection(title, surfaceId: view.id, tabId: tabId) 990 1004 } 991 1005 view.bridge.onSplitAction = { [weak self, weak view] action in 992 1006 guard let self, let view else { return false } ··· 1369 1383 continuation.finish() 1370 1384 } 1371 1385 1386 + noteCommandFinishedForCommandDetection(surfaceId: surfaceId) 1387 + 1372 1388 // Custom command success toast. One-shot: removed regardless of outcome. 1373 1389 if let commandName = pendingCustomCommands.removeValue(forKey: surfaceId), exitCode == 0 { 1374 1390 let durationMs = Int(durationNs / 1_000_000) ··· 1406 1422 appendNotification(title: title, body: body, surfaceId: surfaceId) 1407 1423 } 1408 1424 1425 + // MARK: - Tab Icon Auto-Detection 1426 + // 1427 + // Strategy: each OSC 2 title change is matched against 1428 + // `CommandIconMap` (substring rules first, then first-token). A hit 1429 + // applies the icon immediately — no debounce. Rationale: the 1430 + // mapping is a curated allow-list, so a hit is by definition a 1431 + // command we're happy to brand the tab with; a miss leaves the 1432 + // existing icon untouched (selection-2 semantics). 1433 + // 1434 + // Idle-prompt suppression keeps the lookup focused on real 1435 + // commands: the first title after each `command_finished` is the 1436 + // shell's `precmd`-set prompt, and gets memorised into a learned- 1437 + // idle set so we never reach the mapping with a `user@host`-style 1438 + // string. Shape heuristics (`isLikelyIdleTitleByShape`) cover the 1439 + // bootstrap window before the learner has seen anything. 1440 + // 1441 + // The mapping-hit-equals-apply rule also unblocks short-lived 1442 + // commands (`git status`, `cd foo`) and TUIs that immediately 1443 + // overwrite their preexec title (`codex` → repo name) — both used 1444 + // to slip past a debounce-based detector. 1445 + 1446 + func noteTitleForCommandDetection(_ rawTitle: String, surfaceId: UUID, tabId: TerminalTabID) { 1447 + let title = rawTitle.trimmingCharacters(in: .whitespacesAndNewlines) 1448 + guard !title.isEmpty else { return } 1449 + // Learn this surface's idle prompt: the first title after 1450 + // `command_finished` is reliably the precmd-set one. 1451 + if awaitingIdleTitleLearningBySurface.remove(surfaceId) != nil { 1452 + learnedIdleTitlesBySurface[surfaceId, default: []].insert(title) 1453 + } 1454 + // Drop idle prompts so they can't reach the mapping lookup. 1455 + if Self.isLikelyIdleTitleByShape(title) { return } 1456 + if learnedIdleTitlesBySurface[surfaceId]?.contains(title) == true { return } 1457 + guard let icon = CommandIconMap.iconForFirstToken(title) else { return } 1458 + applyResolvedIcon(icon, surfaceId: surfaceId, tabId: tabId) 1459 + } 1460 + 1461 + func noteCommandFinishedForCommandDetection(surfaceId: UUID) { 1462 + // Arm the idle-prompt learner: the next title arrival is the 1463 + // precmd-set prompt and should join the learned-idle set. 1464 + awaitingIdleTitleLearningBySurface.insert(surfaceId) 1465 + } 1466 + 1467 + /// Drop the per-surface detector state. Called when a surface is 1468 + /// closed or its parent tab is torn down so we don't retain 1469 + /// learned-idle sets keyed by ids that will never emit again. 1470 + func cleanupCommandDetectorState(forSurfaceId surfaceId: UUID) { 1471 + learnedIdleTitlesBySurface.removeValue(forKey: surfaceId) 1472 + awaitingIdleTitleLearningBySurface.remove(surfaceId) 1473 + } 1474 + 1475 + /// Heuristic shape-only detection for shell idle prompts. The 1476 + /// bootstrap filter — before `awaitingIdleTitleLearning` has caught 1477 + /// the precmd-set prompt at least once on this surface — for two 1478 + /// common forms: 1479 + /// 1. `user@host[:path]` — contains `@` plus `:` or `/`, no spaces. 1480 + /// 2. Pure path — starts with `~`, `/`, or `…`, no spaces. 1481 + /// Real commands typically contain a space (program + args) or a 1482 + /// short single token (`ls`, `claude`, `vim`) that doesn't match 1483 + /// either shape, so the false-negative risk is small. 1484 + /// 1485 + /// Exposed (`internal static`) for direct unit testing — does not 1486 + /// touch instance state. 1487 + static func isLikelyIdleTitleByShape(_ title: String) -> Bool { 1488 + guard !title.contains(" ") else { return false } 1489 + if title.contains("@"), title.contains(":") || title.contains("/") { 1490 + return true 1491 + } 1492 + if title.hasPrefix("~") || title.hasPrefix("/") || title.hasPrefix("…") { 1493 + return true 1494 + } 1495 + return false 1496 + } 1497 + 1498 + /// Apply an already-resolved icon to the tab. Honours focus and 1499 + /// user-icon-lock; encodes the icon through `storageString` so 1500 + /// `assetName`-bearing entries pick up the `@asset:` marker the 1501 + /// renderers parse via `ResolvedTabIcon`. 1502 + private func applyResolvedIcon( 1503 + _ icon: TabIconSource, 1504 + surfaceId: UUID, 1505 + tabId: TerminalTabID 1506 + ) { 1507 + // Per-tab UI is single-headed: only the focused surface in a 1508 + // multi-split tab gets to drive its tab's icon. Stops a 1509 + // background split's command from silently overriding what the 1510 + // user is currently looking at. 1511 + guard focusedSurfaceIdByTab[tabId] == surfaceId else { return } 1512 + guard let tab = tabManager.tabs.first(where: { $0.id == tabId }) else { return } 1513 + guard !tab.isIconLocked else { return } 1514 + let serialised = icon.storageString 1515 + guard tab.icon != serialised else { return } 1516 + tabManager.updateIcon(tabId, icon: serialised) 1517 + } 1518 + 1409 1519 static func formatDuration(_ seconds: Int) -> String { 1410 1520 if seconds < 60 { 1411 1521 return "\(seconds)s" ··· 1427 1537 surfaces.removeValue(forKey: surface.id) 1428 1538 autoCloseSurfaceIds.remove(surface.id) 1429 1539 pendingCustomCommands.removeValue(forKey: surface.id) 1540 + cleanupCommandDetectorState(forSurfaceId: surface.id) 1430 1541 } 1431 1542 focusedSurfaceIdByTab.removeValue(forKey: tabId) 1432 1543 tabIsRunningById.removeValue(forKey: tabId) ··· 1570 1681 surfaces.removeValue(forKey: view.id) 1571 1682 autoCloseSurfaceIds.remove(view.id) 1572 1683 pendingCustomCommands.removeValue(forKey: view.id) 1684 + cleanupCommandDetectorState(forSurfaceId: view.id) 1573 1685 return 1574 1686 } 1575 1687 guard let node = tree.find(id: view.id) else { ··· 1577 1689 surfaces.removeValue(forKey: view.id) 1578 1690 autoCloseSurfaceIds.remove(view.id) 1579 1691 pendingCustomCommands.removeValue(forKey: view.id) 1692 + cleanupCommandDetectorState(forSurfaceId: view.id) 1580 1693 return 1581 1694 } 1582 1695 let nextSurface = ··· 1588 1701 surfaces.removeValue(forKey: view.id) 1589 1702 autoCloseSurfaceIds.remove(view.id) 1590 1703 pendingCustomCommands.removeValue(forKey: view.id) 1704 + cleanupCommandDetectorState(forSurfaceId: view.id) 1591 1705 if newTree.isEmpty { 1592 1706 trees.removeValue(forKey: tabId) 1593 1707 focusedSurfaceIdByTab.removeValue(forKey: tabId)
+1 -2
supacode/Features/Terminal/TabBar/Views/TerminalTabLabelView.swift
··· 17 17 .controlSize(.small) 18 18 .tint(isActive ? TerminalTabBarColors.activeText : TerminalTabBarColors.inactiveText) 19 19 } else if let icon = tab.icon { 20 - Image(systemName: icon) 21 - .imageScale(.small) 20 + TabIconImage(rawName: icon, pointSize: 12) 22 21 .foregroundStyle(isActive ? TerminalTabBarColors.activeText : TerminalTabBarColors.inactiveText) 23 22 } 24 23 }
+38
supacode/Features/Terminal/Views/TabIconImage.swift
··· 1 + import SwiftUI 2 + 3 + /// Renders the icon for a `TerminalTabItem`. Decodes the storage 4 + /// string via `ResolvedTabIcon` and dispatches to either 5 + /// `Image(systemName:)` (SF Symbol) or `Image(_:)` (asset catalog). 6 + /// Both branches honour the surrounding `foregroundStyle` because 7 + /// asset entries ship as template SVGs (`@asset:` marker — see 8 + /// `TabIconSource.storageString` and `Assets.xcassets/CommandIcons`). 9 + /// 10 + /// `pointSize` is the on-screen size both branches target: the SF 11 + /// Symbol path uses `.font(.system(size:))` so the symbol scales 12 + /// with the value; the asset path uses `.resizable() + frame` for 13 + /// the same final footprint. Keeping both branches at the same 14 + /// nominal size avoids visual jumps when a tab switches between an 15 + /// SF Symbol fallback and a branded asset. 16 + struct TabIconImage: View { 17 + let rawName: String 18 + let pointSize: CGFloat 19 + 20 + var body: some View { 21 + Group { 22 + switch ResolvedTabIcon.parse(rawName) { 23 + case .systemSymbol(let name): 24 + Image(systemName: name) 25 + .font(.system(size: pointSize)) 26 + case .asset(let name): 27 + Image(name) 28 + .resizable() 29 + .scaledToFit() 30 + .frame(width: pointSize, height: pointSize) 31 + } 32 + } 33 + // Tab icons are decorative — `tab.title` already provides the 34 + // accessible label for the tab. Callers that need a custom label 35 + // can override after construction. 36 + .accessibilityHidden(true) 37 + } 38 + }
+94
supacodeTests/CommandIconMapTests.swift
··· 1 + import Testing 2 + 3 + @testable import supacode 4 + 5 + struct CommandIconMapTests { 6 + // MARK: - First-token resolution 7 + 8 + @Test func resolvesExactToken() throws { 9 + let icon = try #require(CommandIconMap.iconForFirstToken("git")) 10 + #expect(icon.systemSymbol == "arrow.triangle.branch") 11 + #expect(icon.assetName == "Git") 12 + } 13 + 14 + @Test func resolvesByFirstTokenWithArgs() { 15 + // "git status" should match the `git` entry, not look up "git status". 16 + #expect(CommandIconMap.iconForFirstToken("git status")?.assetName == "Git") 17 + #expect(CommandIconMap.iconForFirstToken("swift build --release")?.assetName == "Swift") 18 + #expect(CommandIconMap.iconForFirstToken("docker compose up -d")?.assetName == "Docker") 19 + } 20 + 21 + @Test func lookupIsCaseInsensitive() { 22 + #expect(CommandIconMap.iconForFirstToken("GIT")?.assetName == "Git") 23 + #expect(CommandIconMap.iconForFirstToken("Docker")?.assetName == "Docker") 24 + #expect(CommandIconMap.iconForFirstToken("CLAUDE")?.assetName == "ClaudeCode") 25 + } 26 + 27 + @Test func returnsNilForUnknownToken() { 28 + #expect(CommandIconMap.iconForFirstToken("never-heard-of-this-cli") == nil) 29 + #expect(CommandIconMap.iconForFirstToken("xyzzy") == nil) 30 + } 31 + 32 + @Test func returnsNilForEmptyTitle() { 33 + #expect(CommandIconMap.iconForFirstToken("") == nil) 34 + } 35 + 36 + @Test func handlesLeadingWhitespace() { 37 + // `split(omittingEmpty:)` skips the leading space so the first 38 + // real token still resolves. 39 + #expect(CommandIconMap.iconForFirstToken(" git status")?.assetName == "Git") 40 + } 41 + 42 + // MARK: - Aliases reuse the right asset 43 + 44 + @Test func packageManagerAliasesShareAssets() { 45 + // Runners share the icon of their parent package manager. 46 + #expect(CommandIconMap.iconForFirstToken("npx")?.assetName == "Npm") 47 + #expect(CommandIconMap.iconForFirstToken("bunx")?.assetName == "Bun") 48 + #expect(CommandIconMap.iconForFirstToken("pip")?.assetName == "Python") 49 + #expect(CommandIconMap.iconForFirstToken("pip3")?.assetName == "Python") 50 + } 51 + 52 + @Test func tuiFrontendsShareAssets() { 53 + // lazygit/lazydocker are TUI frontends — share the icon. 54 + #expect(CommandIconMap.iconForFirstToken("lazygit")?.assetName == "Git") 55 + #expect(CommandIconMap.iconForFirstToken("lazydocker")?.assetName == "Docker") 56 + } 57 + 58 + @Test func pythonAliasMapsToPython() { 59 + #expect(CommandIconMap.iconForFirstToken("python")?.assetName == "Python") 60 + #expect(CommandIconMap.iconForFirstToken("python3")?.assetName == "Python") 61 + } 62 + 63 + // MARK: - Coding agents 64 + 65 + @Test func codingAgentsResolved() { 66 + // Sample of the coding-agent set — they all share the sparkle SF 67 + // Symbol fallback, asset names match the imageset folders. 68 + #expect(CommandIconMap.iconForFirstToken("claude")?.assetName == "ClaudeCode") 69 + #expect(CommandIconMap.iconForFirstToken("codex")?.assetName == "Codex") 70 + #expect(CommandIconMap.iconForFirstToken("gemini")?.assetName == "Gemini") 71 + #expect(CommandIconMap.iconForFirstToken("copilot")?.assetName == "GitHubCopilot") 72 + // aider/droid have no brand asset — sparkle fallback only. 73 + #expect(CommandIconMap.iconForFirstToken("aider")?.systemSymbol == "sparkle") 74 + #expect(CommandIconMap.iconForFirstToken("aider")?.assetName == nil) 75 + #expect(CommandIconMap.iconForFirstToken("droid")?.systemSymbol == "sparkle") 76 + } 77 + 78 + // MARK: - Debug catalog 79 + 80 + @Test func debugAllEntriesIsSorted() { 81 + let tokens = CommandIconMap.debugAllEntries.map(\.token) 82 + #expect(tokens == tokens.sorted()) 83 + } 84 + 85 + @Test func debugAllEntriesCoversWellKnownTokens() { 86 + let tokens = Set(CommandIconMap.debugAllEntries.map(\.token)) 87 + // Spot-check that the debug surface actually exposes the tokens 88 + // a user is most likely to hunt for. 89 + let mustHave: Set<String> = [ 90 + "git", "docker", "claude", "vim", "ssh", "npm", "swift", 91 + ] 92 + #expect(mustHave.isSubset(of: tokens)) 93 + } 94 + }
+79
supacodeTests/IconDetectorIdleHeuristicTests.swift
··· 1 + import Testing 2 + 3 + @testable import supacode 4 + 5 + /// Pure-shape detection of the shell's idle prompt 6 + /// (`isLikelyIdleTitleByShape`). The bootstrap filter that runs 7 + /// before the per-surface learner has memorised the prompt at least 8 + /// once. 9 + struct IconDetectorIdleHeuristicTests { 10 + // MARK: - Idle prompt shapes 11 + 12 + @Test func detectsUserAtHostWithColonPath() { 13 + #expect(WorktreeTerminalState.isLikelyIdleTitleByShape("onevcat@Mac:~/Sync/github/YiTong")) 14 + } 15 + 16 + @Test func detectsUserAtHostWithSlashOnly() { 17 + #expect(WorktreeTerminalState.isLikelyIdleTitleByShape("onevcat@Mac:/usr/local/etc")) 18 + } 19 + 20 + @Test func detectsTildePath() { 21 + #expect(WorktreeTerminalState.isLikelyIdleTitleByShape("~/Sync/github")) 22 + } 23 + 24 + @Test func detectsAbsolutePath() { 25 + #expect(WorktreeTerminalState.isLikelyIdleTitleByShape("/usr/local/bin")) 26 + } 27 + 28 + @Test func detectsTruncatedPathWithEllipsis() { 29 + // zsh's "compact path" renders as `…/Sync/github/YiTong`. 30 + #expect(WorktreeTerminalState.isLikelyIdleTitleByShape("…/Sync/github/YiTong")) 31 + } 32 + 33 + // MARK: - Real commands should not be flagged 34 + 35 + @Test func commandWithSpaceIsNotIdle() { 36 + // Anything with a space is treated as a real command (program + 37 + // args) — this is the primary discriminator. 38 + #expect(!WorktreeTerminalState.isLikelyIdleTitleByShape("git status")) 39 + #expect(!WorktreeTerminalState.isLikelyIdleTitleByShape("vim file.swift")) 40 + #expect(!WorktreeTerminalState.isLikelyIdleTitleByShape("docker compose up")) 41 + } 42 + 43 + @Test func barCommandTokenIsNotIdle() { 44 + // Single-token commands without `@`, `~`, `/`, or `…` are real 45 + // commands. 46 + #expect(!WorktreeTerminalState.isLikelyIdleTitleByShape("claude")) 47 + #expect(!WorktreeTerminalState.isLikelyIdleTitleByShape("vim")) 48 + #expect(!WorktreeTerminalState.isLikelyIdleTitleByShape("npm")) 49 + } 50 + 51 + @Test func tuiTitleIsNotIdle() { 52 + // TUI tools that rewrite their own title (claude → spinner glyphs) 53 + // contain spaces and should still be classified as commands. 54 + #expect(!WorktreeTerminalState.isLikelyIdleTitleByShape("✳ Claude Code")) 55 + #expect(!WorktreeTerminalState.isLikelyIdleTitleByShape("⠐ Claude Code")) 56 + } 57 + 58 + @Test func emptyTitleIsNotIdle() { 59 + // Empty handled by the caller; the heuristic itself returns false 60 + // (no `@`, no leading `~`/`/`/`…`). 61 + #expect(!WorktreeTerminalState.isLikelyIdleTitleByShape("")) 62 + } 63 + 64 + // MARK: - Edge cases 65 + 66 + @Test func atSymbolWithoutPathSeparatorIsNotIdle() { 67 + // `git@github.com` would be a typical SSH remote, not an idle 68 + // prompt. Without `:` or `/` it's not classified as idle. 69 + #expect(!WorktreeTerminalState.isLikelyIdleTitleByShape("git@github.com")) 70 + } 71 + 72 + @Test func absolutePathExecutableIsClassifiedAsIdle() { 73 + // Documented limitation: `/usr/bin/python3` (rare invocation 74 + // form) shape-matches as a "path" prompt and gets skipped. The 75 + // tradeoff is fine — typical use is `python3`, not the absolute 76 + // path. 77 + #expect(WorktreeTerminalState.isLikelyIdleTitleByShape("/usr/bin/python3")) 78 + } 79 + }
+70
supacodeTests/TabIconSourceTests.swift
··· 1 + import Testing 2 + 3 + @testable import supacode 4 + 5 + struct TabIconSourceTests { 6 + // MARK: - storageString encoding 7 + 8 + @Test func sfSymbolOnlySerialisesBare() { 9 + // SF-Symbol-only entries serialise as the bare symbol name so 10 + // the existing IconPicker storage path keeps working unchanged. 11 + let icon = TabIconSource(systemSymbol: "terminal") 12 + #expect(icon.storageString == "terminal") 13 + } 14 + 15 + @Test func assetEntrySerialisesWithMarker() { 16 + // Asset-bearing entries get the `@asset:` prefix the renderer 17 + // parses via `ResolvedTabIcon`. 18 + let icon = TabIconSource(systemSymbol: "shippingbox", assetName: "Docker") 19 + #expect(icon.storageString == "@asset:Docker") 20 + } 21 + 22 + @Test func assetEntryOmitsSystemSymbolFromStorage() { 23 + // `systemSymbol` stays only as a fallback for renderers that 24 + // can't resolve the asset; storage carries the asset. 25 + let icon = TabIconSource(systemSymbol: "sparkle", assetName: "ClaudeCode") 26 + #expect(icon.storageString == "@asset:ClaudeCode") 27 + #expect(!icon.storageString.contains("sparkle")) 28 + } 29 + 30 + // MARK: - ResolvedTabIcon parsing 31 + 32 + @Test func parsesBareStringAsSystemSymbol() { 33 + let resolved = ResolvedTabIcon.parse("terminal") 34 + #expect(resolved == .systemSymbol("terminal")) 35 + } 36 + 37 + @Test func parsesAssetMarker() { 38 + let resolved = ResolvedTabIcon.parse("@asset:Docker") 39 + #expect(resolved == .asset(name: "Docker")) 40 + } 41 + 42 + @Test func parsesAssetMarkerWithSpaces() { 43 + // Asset names can contain spaces (e.g. "Visual Studio Code"), so 44 + // the parser must keep everything after the marker prefix intact. 45 + let resolved = ResolvedTabIcon.parse("@asset:Visual Studio Code") 46 + #expect(resolved == .asset(name: "Visual Studio Code")) 47 + } 48 + 49 + @Test func sfSymbolStringWithColonStaysSymbol() { 50 + // Edge: SF Symbol names never start with `@asset:`, so a literal 51 + // colon-bearing symbol (none today, but defensive) doesn't trip 52 + // the parser. 53 + let resolved = ResolvedTabIcon.parse("foo:bar") 54 + #expect(resolved == .systemSymbol("foo:bar")) 55 + } 56 + 57 + // MARK: - Round-trip 58 + 59 + @Test func sfSymbolRoundTrip() { 60 + let source = TabIconSource(systemSymbol: "hammer") 61 + let parsed = ResolvedTabIcon.parse(source.storageString) 62 + #expect(parsed == .systemSymbol("hammer")) 63 + } 64 + 65 + @Test func assetRoundTrip() { 66 + let source = TabIconSource(systemSymbol: "shippingbox", assetName: "Npm") 67 + let parsed = ResolvedTabIcon.parse(source.storageString) 68 + #expect(parsed == .asset(name: "Npm")) 69 + } 70 + }