Skip to content

Commit 735a106

Browse files
arimxyerclaude
andcommitted
Add --web flag to open changelog sources in browser
Works on all commands: - aic <source> --web: opens that tool's changelog - aic status --web: opens all changelogs - aic latest --web: opens all changelogs Cross-platform support (xdg-open, open, start). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 06c9df6 commit 735a106

File tree

1 file changed

+56
-5
lines changed

1 file changed

+56
-5
lines changed

main.go

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import (
66
"io"
77
"net/http"
88
"os"
9+
"os/exec"
910
"regexp"
11+
"runtime"
1012
"sort"
1113
"strings"
1214
"sync"
@@ -31,33 +33,39 @@ type ChangelogEntry struct {
3133
type Source struct {
3234
Name string
3335
DisplayName string
36+
URL string
3437
FetchFunc func() ([]ChangelogEntry, error)
3538
}
3639

3740
var sources = map[string]Source{
3841
"claude": {
3942
Name: "claude",
4043
DisplayName: "Claude Code",
44+
URL: "https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md",
4145
FetchFunc: fetchClaudeChangelog,
4246
},
4347
"codex": {
4448
Name: "codex",
4549
DisplayName: "OpenAI Codex",
50+
URL: "https://github.com/openai/codex/releases",
4651
FetchFunc: fetchCodexChangelog,
4752
},
4853
"opencode": {
4954
Name: "opencode",
5055
DisplayName: "OpenCode",
56+
URL: "https://github.com/sst/opencode/releases",
5157
FetchFunc: fetchOpenCodeChangelog,
5258
},
5359
"gemini": {
5460
Name: "gemini",
5561
DisplayName: "Gemini CLI",
62+
URL: "https://github.com/google-gemini/gemini-cli/releases",
5663
FetchFunc: fetchGeminiChangelog,
5764
},
5865
"copilot": {
5966
Name: "copilot",
6067
DisplayName: "GitHub Copilot CLI",
68+
URL: "https://github.com/github/copilot-cli/blob/main/changelog.md",
6169
FetchFunc: fetchCopilotChangelog,
6270
},
6371
}
@@ -83,22 +91,40 @@ func main() {
8391
}
8492

8593
if args[0] == "latest" {
86-
var jsonOutput bool
94+
var jsonOutput, webOpen bool
8795
for i := 1; i < len(args); i++ {
88-
if args[i] == "-json" || args[i] == "--json" {
96+
switch args[i] {
97+
case "-json", "--json":
8998
jsonOutput = true
99+
case "-web", "--web":
100+
webOpen = true
90101
}
91102
}
103+
if webOpen {
104+
for _, src := range sources {
105+
openBrowser(src.URL)
106+
}
107+
os.Exit(0)
108+
}
92109
runLatestCommand(jsonOutput)
93110
os.Exit(0)
94111
}
95112

96113
if args[0] == "status" {
97-
var jsonOutput bool
114+
var jsonOutput, webOpen bool
98115
for i := 1; i < len(args); i++ {
99-
if args[i] == "-json" || args[i] == "--json" {
116+
switch args[i] {
117+
case "-json", "--json":
100118
jsonOutput = true
119+
case "-web", "--web":
120+
webOpen = true
121+
}
122+
}
123+
if webOpen {
124+
for _, src := range sources {
125+
openBrowser(src.URL)
101126
}
127+
os.Exit(0)
102128
}
103129
runStatusCommand(jsonOutput)
104130
os.Exit(0)
@@ -115,7 +141,7 @@ func main() {
115141
os.Exit(1)
116142
}
117143

118-
var jsonOutput, mdOutput, listVersions bool
144+
var jsonOutput, mdOutput, listVersions, webOpen bool
119145
var targetVersion string
120146

121147
for i := 1; i < len(args); i++ {
@@ -126,6 +152,8 @@ func main() {
126152
mdOutput = true
127153
case "-list", "--list":
128154
listVersions = true
155+
case "-web", "--web":
156+
webOpen = true
129157
case "-version", "--version":
130158
if i+1 < len(args) {
131159
targetVersion = args[i+1]
@@ -134,6 +162,11 @@ func main() {
134162
}
135163
}
136164

165+
if webOpen {
166+
openBrowser(source.URL)
167+
os.Exit(0)
168+
}
169+
137170
entries, err := source.FetchFunc()
138171
if err != nil {
139172
fmt.Fprintf(os.Stderr, "Error fetching changelog: %v\n", err)
@@ -196,6 +229,7 @@ func printUsage() {
196229
fmt.Fprintf(os.Stderr, " -md Output as markdown\n")
197230
fmt.Fprintf(os.Stderr, " -list List all versions\n")
198231
fmt.Fprintf(os.Stderr, " -version <ver> Get specific version\n")
232+
fmt.Fprintf(os.Stderr, " -web Open changelog source in browser\n")
199233
fmt.Fprintf(os.Stderr, " -v, --version Show aic version\n")
200234
fmt.Fprintf(os.Stderr, " -h, --help Show this help\n\n")
201235
fmt.Fprintf(os.Stderr, "Examples:\n")
@@ -205,6 +239,8 @@ func printUsage() {
205239
fmt.Fprintf(os.Stderr, " aic gemini -version 0.21.0 # Specific Gemini version\n")
206240
fmt.Fprintf(os.Stderr, " aic latest # All releases in last 24h\n")
207241
fmt.Fprintf(os.Stderr, " aic status # Status table of all tools\n")
242+
fmt.Fprintf(os.Stderr, " aic claude -web # Open Claude changelog in browser\n")
243+
fmt.Fprintf(os.Stderr, " aic status -web # Open all changelogs in browser\n")
208244
}
209245

210246
func runLatestCommand(jsonOutput bool) {
@@ -450,6 +486,21 @@ func truncateString(s string, maxLen int) string {
450486
return s[:maxLen-3] + "..."
451487
}
452488

489+
func openBrowser(url string) {
490+
var cmd *exec.Cmd
491+
switch runtime.GOOS {
492+
case "darwin":
493+
cmd = exec.Command("open", url)
494+
case "windows":
495+
cmd = exec.Command("cmd", "/c", "start", url)
496+
default: // linux, freebsd, etc.
497+
cmd = exec.Command("xdg-open", url)
498+
}
499+
if err := cmd.Start(); err != nil {
500+
fmt.Fprintf(os.Stderr, "Error opening browser: %v\n", err)
501+
}
502+
}
503+
453504
func formatRelativeTime(t time.Time) string {
454505
if t.IsZero() {
455506
return "-"

0 commit comments

Comments
 (0)