Skip to content

Commit fefb0d9

Browse files
kevinelliottclaude
andcommitted
Add JSON output support to agents list command
Adds --json flag to `agentpipe agents list` command that outputs agent information in JSON format instead of human-readable tables. Features: - Regular list mode: Shows name, command, description, docs, installed status, path, version, and install command - Outdated mode: Shows version information with update status - Both modes support parallel version checking for performance - Clean JSON structure with appropriate omitempty fields Example usage: - agentpipe agents list --json - agentpipe agents list --outdated --json - agentpipe agents list --installed --json --current 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 4c8e630 commit fefb0d9

File tree

1 file changed

+146
-15
lines changed

1 file changed

+146
-15
lines changed

cmd/agents.go

Lines changed: 146 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"os"
67
"os/exec"
@@ -17,6 +18,7 @@ var (
1718
listInstalled bool
1819
listOutdated bool
1920
listCurrent bool
21+
listJSON bool
2022
)
2123

2224
// agentsCmd represents the agents command
@@ -83,10 +85,25 @@ func init() {
8385
agentsListCmd.Flags().BoolVar(&listInstalled, "installed", false, "List only installed agents")
8486
agentsListCmd.Flags().BoolVar(&listOutdated, "outdated", false, "List outdated agents with version comparison table")
8587
agentsListCmd.Flags().BoolVar(&listCurrent, "current", false, "Check and display latest versions from the web")
88+
agentsListCmd.Flags().BoolVar(&listJSON, "json", false, "Output in JSON format")
8689
agentsInstallCmd.Flags().BoolVar(&installAll, "all", false, "Install all agents")
8790
agentsUpgradeCmd.Flags().BoolVar(&installAll, "all", false, "Upgrade all agents")
8891
}
8992

93+
// AgentListJSON represents an agent in JSON output
94+
type AgentListJSON struct {
95+
Name string `json:"name"`
96+
Command string `json:"command"`
97+
Description string `json:"description"`
98+
Docs string `json:"docs"`
99+
Installed bool `json:"installed"`
100+
Path string `json:"path,omitempty"`
101+
Version string `json:"version,omitempty"`
102+
LatestVersion string `json:"latest_version,omitempty"`
103+
HasUpdate bool `json:"has_update,omitempty"`
104+
InstallCmd string `json:"install_cmd,omitempty"`
105+
}
106+
90107
func runAgentsList(cmd *cobra.Command, args []string) {
91108
agents := registry.GetAll()
92109

@@ -117,6 +134,12 @@ func runAgentsList(cmd *cobra.Command, args []string) {
117134
filteredAgents = append(filteredAgents, agent)
118135
}
119136

137+
// Handle JSON output
138+
if listJSON {
139+
outputAgentsJSON(filteredAgents, showVersionInfo)
140+
return
141+
}
142+
120143
// Determine title based on flags
121144
title := "AI Agent CLIs"
122145
if listInstalled {
@@ -207,21 +230,18 @@ func runAgentsList(cmd *cobra.Command, args []string) {
207230
fmt.Println()
208231
}
209232

233+
// agentVersionRow represents version information for an agent
234+
type agentVersionRow struct {
235+
name string
236+
installed bool
237+
current string
238+
latest string
239+
hasUpdate bool
240+
canCheck bool
241+
}
242+
210243
// showOutdatedTable displays a table of agents with version comparison
211244
func showOutdatedTable(agents []*registry.AgentDefinition) {
212-
fmt.Println("\n📊 Agent Version Status")
213-
fmt.Println(strings.Repeat("=", 85))
214-
fmt.Println()
215-
216-
// Build table data
217-
type row struct {
218-
name string
219-
installed bool
220-
current string
221-
latest string
222-
hasUpdate bool
223-
canCheck bool
224-
}
225245

226246
// Fetch version info in parallel
227247
type versionResult struct {
@@ -232,7 +252,7 @@ func showOutdatedTable(agents []*registry.AgentDefinition) {
232252
}
233253

234254
resultChan := make(chan versionResult, len(agents))
235-
rows := make([]row, len(agents))
255+
rows := make([]agentVersionRow, len(agents))
236256
outdatedCount := 0
237257

238258
// Launch parallel version checks
@@ -273,7 +293,7 @@ func showOutdatedTable(agents []*registry.AgentDefinition) {
273293
agent := agents[result.index]
274294
installed := result.current != "not installed"
275295

276-
r := row{
296+
r := agentVersionRow{
277297
name: agent.Name,
278298
installed: installed,
279299
current: result.current,
@@ -299,6 +319,17 @@ func showOutdatedTable(agents []*registry.AgentDefinition) {
299319
}
300320
close(resultChan)
301321

322+
// Output JSON format if requested
323+
if listJSON {
324+
outputOutdatedJSON(rows)
325+
return
326+
}
327+
328+
// Human-readable format
329+
fmt.Println("\n📊 Agent Version Status")
330+
fmt.Println(strings.Repeat("=", 85))
331+
fmt.Println()
332+
302333
// Print table header
303334
fmt.Printf("%-12s %-24s %-24s %s\n",
304335
"Agent", "Installed Version", "Latest Version", "Update")
@@ -523,6 +554,106 @@ func runAgentsUpgrade(cmd *cobra.Command, args []string) {
523554
}
524555
}
525556

557+
// outputAgentsJSON outputs agent list in JSON format
558+
func outputAgentsJSON(agents []*registry.AgentDefinition, showVersionInfo bool) {
559+
var jsonAgents []AgentListJSON
560+
561+
for _, agent := range agents {
562+
installed := isAgentInstalled(agent.Command)
563+
564+
agentJSON := AgentListJSON{
565+
Name: agent.Name,
566+
Command: agent.Command,
567+
Description: agent.Description,
568+
Docs: agent.Docs,
569+
Installed: installed,
570+
}
571+
572+
if installed {
573+
if path, err := exec.LookPath(agent.Command); err == nil {
574+
agentJSON.Path = path
575+
}
576+
577+
version := registry.GetInstalledVersion(agent.Command)
578+
if version != "" {
579+
agentJSON.Version = version
580+
}
581+
582+
// Check for updates if showVersionInfo is true
583+
if showVersionInfo && agent.PackageManager != "" {
584+
latest, err := agent.GetLatestVersion()
585+
if err == nil {
586+
agentJSON.LatestVersion = latest
587+
if version != "" {
588+
cmp, _ := registry.CompareVersions(version, latest)
589+
agentJSON.HasUpdate = cmp < 0
590+
}
591+
}
592+
}
593+
} else {
594+
// Get install command for non-installed agents
595+
installCmd, err := agent.GetInstallCommand()
596+
if err == nil {
597+
if agent.IsInstallable() {
598+
agentJSON.InstallCmd = fmt.Sprintf("agentpipe agents install %s", strings.ToLower(agent.Name))
599+
} else {
600+
agentJSON.InstallCmd = installCmd
601+
}
602+
}
603+
604+
// Show latest version if showVersionInfo is set
605+
if showVersionInfo && agent.PackageManager != "" {
606+
latest, err := agent.GetLatestVersion()
607+
if err == nil {
608+
agentJSON.LatestVersion = latest
609+
}
610+
}
611+
}
612+
613+
jsonAgents = append(jsonAgents, agentJSON)
614+
}
615+
616+
output, err := json.MarshalIndent(jsonAgents, "", " ")
617+
if err != nil {
618+
fmt.Fprintf(os.Stderr, "Error generating JSON output: %v\n", err)
619+
os.Exit(1)
620+
}
621+
622+
fmt.Println(string(output))
623+
}
624+
625+
// outputOutdatedJSON outputs agent version information in JSON format
626+
func outputOutdatedJSON(rows []agentVersionRow) {
627+
type OutdatedAgentJSON struct {
628+
Name string `json:"name"`
629+
Installed bool `json:"installed"`
630+
CurrentVer string `json:"current_version"`
631+
LatestVer string `json:"latest_version"`
632+
HasUpdate bool `json:"has_update"`
633+
CanCheckVer bool `json:"can_check_version"`
634+
}
635+
636+
var jsonAgents []OutdatedAgentJSON
637+
for _, r := range rows {
638+
jsonAgents = append(jsonAgents, OutdatedAgentJSON{
639+
Name: r.name,
640+
Installed: r.installed,
641+
CurrentVer: r.current,
642+
LatestVer: r.latest,
643+
HasUpdate: r.hasUpdate,
644+
CanCheckVer: r.canCheck,
645+
})
646+
}
647+
648+
output, err := json.MarshalIndent(jsonAgents, "", " ")
649+
if err != nil {
650+
fmt.Fprintf(os.Stderr, "Error generating JSON output: %v\n", err)
651+
os.Exit(1)
652+
}
653+
654+
fmt.Println(string(output))
655+
}
656+
526657
// isAgentInstalled checks if an agent CLI is available in PATH
527658
func isAgentInstalled(command string) bool {
528659
_, err := exec.LookPath(command)

0 commit comments

Comments
 (0)