Problem
The pattern shell(...) → Data → JSONSerialization → [String: Any] → manual key extraction appears 20+ times across IssueTracker and SessionService. Every call site duplicates error handling (try? / guard let data), JSON casting, and field extraction. This is the single largest source of code duplication in the project, and using try? everywhere means failures are invisible.
Proposed Improvement
Create a generic shellJSON<T: Decodable>(_ args: String...) async throws -> T helper that runs the shell command and decodes the output into a Codable struct. Define small Codable structs for each GitHub/GitLab response shape. Replace try? with proper error propagation or at minimum logged errors.
Effort
Medium (2–3 hours). Define ~5 Codable response types + one helper function, then mechanically replace call sites.
Files Affected
Sources/Crow/App/IssueTracker.swift (17 instances of shell+JSON)
Sources/Crow/App/SessionService.swift (6 instances)
- New or extended:
Sources/Crow/App/ShellHelpers.swift
- New:
Sources/Crow/App/GitHubModels.swift (Codable response types)
Priority: 3/10
Problem
The pattern
shell(...) → Data → JSONSerialization → [String: Any] → manual key extractionappears 20+ times across IssueTracker and SessionService. Every call site duplicates error handling (try?/guard let data), JSON casting, and field extraction. This is the single largest source of code duplication in the project, and usingtry?everywhere means failures are invisible.Proposed Improvement
Create a generic
shellJSON<T: Decodable>(_ args: String...) async throws -> Thelper that runs the shell command and decodes the output into a Codable struct. Define small Codable structs for each GitHub/GitLab response shape. Replacetry?with proper error propagation or at minimum logged errors.Effort
Medium (2–3 hours). Define ~5 Codable response types + one helper function, then mechanically replace call sites.
Files Affected
Sources/Crow/App/IssueTracker.swift(17 instances of shell+JSON)Sources/Crow/App/SessionService.swift(6 instances)Sources/Crow/App/ShellHelpers.swiftSources/Crow/App/GitHubModels.swift(Codable response types)Priority: 3/10