Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions Chops/Models/ToolSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ import SwiftUI
enum ToolSource: String, Codable, CaseIterable, Identifiable {
case agents
case claude
case claudeInternal
case cursor
case windsurf
case codex
case codexInternal
case codebuddy
case copilot
case aider
case amp
Expand All @@ -21,9 +24,12 @@ enum ToolSource: String, Codable, CaseIterable, Identifiable {
var displayName: String {
switch self {
case .claude: "Claude Code"
case .claudeInternal: "Claude Internal"
case .cursor: "Cursor"
case .windsurf: "Windsurf"
case .codex: "Codex"
case .codexInternal: "Codex Internal"
case .codebuddy: "CodeBuddy"
case .copilot: "Copilot"
case .aider: "Aider"
case .amp: "Amp"
Expand All @@ -41,9 +47,12 @@ enum ToolSource: String, Codable, CaseIterable, Identifiable {
var iconName: String {
switch self {
case .claude: "brain.head.profile"
case .claudeInternal: "brain.head.profile"
case .cursor: "cursorarrow.rays"
case .windsurf: "wind"
case .codex: "book.closed"
case .codexInternal: "book.closed"
case .codebuddy: "hammer"
case .copilot: "airplane"
case .aider: "wrench.and.screwdriver"
case .amp: "bolt.fill"
Expand All @@ -61,8 +70,11 @@ enum ToolSource: String, Codable, CaseIterable, Identifiable {
var logoAssetName: String? {
switch self {
case .claude: "tool-claude"
case .claudeInternal: "tool-claude"
case .cursor: "tool-cursor"
case .codex: "tool-codex"
case .codexInternal: "tool-codex"
case .codebuddy: "tool-codebuddy"
case .windsurf: "tool-windsurf"
case .copilot: "tool-copilot"
case .amp: "tool-amp"
Expand All @@ -76,9 +88,12 @@ enum ToolSource: String, Codable, CaseIterable, Identifiable {
var color: Color {
switch self {
case .claude: .orange
case .claudeInternal: .brown
case .cursor: .blue
case .windsurf: .teal
case .codex: .green
case .codexInternal: .mint
case .codebuddy: .blue
case .copilot: .purple
case .aider: .yellow
case .amp: .pink
Expand All @@ -96,8 +111,11 @@ enum ToolSource: String, Codable, CaseIterable, Identifiable {
let home = FileManager.default.homeDirectoryForCurrentUser.path
switch self {
case .claude: return ["\(home)/.claude/agents"]
case .claudeInternal: return ["\(home)/.claude-internal/agents"]
case .cursor: return ["\(home)/.cursor/agents"]
case .codex: return ["\(home)/.codex/agents"]
case .codexInternal: return ["\(home)/.codex-internal/agents"]
case .codebuddy: return ["\(home)/.codebuddy/agents"]
default: return []
}
}
Expand All @@ -112,9 +130,12 @@ enum ToolSource: String, Codable, CaseIterable, Identifiable {
}()
switch self {
case .claude: return ["\(home)/.claude/skills"]
case .claudeInternal: return ["\(home)/.claude-internal/skills"]
case .cursor: return ["\(home)/.cursor/skills", "\(home)/.cursor/rules"]
case .windsurf: return ["\(home)/.codeium/windsurf/memories", "\(home)/.windsurf/rules"]
case .codex: return ["\(home)/.codex/skills"]
case .codexInternal: return ["\(home)/.codex-internal/skills"]
case .codebuddy: return ["\(home)/.codebuddy/skills"]
case .copilot: return ["\(home)/.copilot/skills"]
case .aider: return []
case .amp: return ["\(configHome)/amp/skills"]
Expand All @@ -141,6 +162,10 @@ enum ToolSource: String, Codable, CaseIterable, Identifiable {
|| fm.fileExists(atPath: "\(home)/.claude/CLAUDE.md")
|| fm.fileExists(atPath: "\(home)/.claude/plugins/installed_plugins.json")
|| Self.cliBinaryExists("claude")
case .claudeInternal:
return fm.fileExists(atPath: "\(home)/.claude-internal/settings.json")
|| fm.fileExists(atPath: "\(home)/.claude-internal/CLAUDE.md")
|| Self.cliBinaryExists("claude-internal")
case .cursor:
return fm.fileExists(atPath: "/Applications/Cursor.app")
|| fm.fileExists(atPath: "\(home)/.cursor/argv.json")
Expand All @@ -151,6 +176,14 @@ enum ToolSource: String, Codable, CaseIterable, Identifiable {
return fm.fileExists(atPath: "\(home)/.codex/config.toml")
|| fm.fileExists(atPath: "\(home)/.codex/auth.json")
|| Self.cliBinaryExists("codex")
case .codexInternal:
return fm.fileExists(atPath: "\(home)/.codex-internal/config.toml")
|| fm.fileExists(atPath: "\(home)/.codex-internal/auth.json")
|| Self.cliBinaryExists("codex-internal")
case .codebuddy:
return fm.fileExists(atPath: "\(home)/.codebuddy/settings.json")
|| fm.fileExists(atPath: "\(home)/.codebuddy/CODEBUDDY.md")
|| Self.cliBinaryExists("codebuddy")
case .amp:
let configHome = ProcessInfo.processInfo.environment["XDG_CONFIG_HOME"]
.flatMap { $0.isEmpty ? nil : $0 } ?? "\(home)/.config"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"images" : [
{
"filename" : "logo.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "original"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions Chops/Services/SkillScanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ final class SkillScanner {
(".cursor/agents", .cursor, .agent),
(".codex/skills", .codex, .skill),
(".codex/agents", .codex, .agent),
(".codebuddy/skills", .codebuddy, .skill),
(".codebuddy/agents", .codebuddy, .agent),
(".windsurf/rules", .windsurf, .skill),
(".github", .copilot, .skill),
(".github/agents", .copilot, .agent),
Expand Down
9 changes: 6 additions & 3 deletions Chops/Views/Shared/NewSkillSheet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ struct NewSkillSheet: View {
@State private var selectedTool: ToolSource = .claude
@State private var errorMessage: String?

private let skillCreatableTools: [ToolSource] = [.claude, .agents, .cursor, .codex, .amp, .opencode, .pi, .antigravity]
private let agentCreatableTools: [ToolSource] = [.claude, .cursor, .codex]
private let skillCreatableTools: [ToolSource] = [.claude, .agents, .cursor, .codex, .codebuddy, .amp, .opencode, .pi, .antigravity]
private let agentCreatableTools: [ToolSource] = [.claude, .cursor, .codex, .codebuddy]

private var itemKind: ItemKind { appState.newItemKind }
private var isAgent: Bool { itemKind == .agent }
Expand Down Expand Up @@ -113,6 +113,9 @@ struct NewSkillSheet: View {
case .codex:
basePath = "\(fm.homeDirectoryForCurrentUser.path)/.codex/skills/\(sanitizedName)"
fileName = "SKILL.md"
case .codebuddy:
basePath = "\(fm.homeDirectoryForCurrentUser.path)/.codebuddy/skills/\(sanitizedName)"
fileName = "SKILL.md"
case .amp:
basePath = "\(configHome)/amp/skills/\(sanitizedName)"
fileName = "SKILL.md"
Expand Down Expand Up @@ -204,7 +207,7 @@ struct NewSkillSheet: View {

Add your skill instructions here.
"""
case .codex, .amp, .opencode, .pi, .agents, .antigravity:
case .codex, .codebuddy, .amp, .opencode, .pi, .agents, .antigravity:
return """
---
name: \(skillID)
Expand Down
3 changes: 3 additions & 0 deletions Chops/Views/Shared/ToolBadge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,12 @@ extension ToolSource {
var shortLabel: String {
switch self {
case .claude: "CC"
case .claudeInternal: "CI"
case .cursor: "CU"
case .windsurf: "WS"
case .codex: "CX"
case .codexInternal: "XI"
case .codebuddy: "CB"
case .copilot: "CP"
case .aider: "AI"
case .amp: "AM"
Expand Down