Skip to content
Draft
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
6 changes: 4 additions & 2 deletions internal/cli/agent/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import (
"github.com/agentregistry-dev/agentregistry/internal/cli/agent/project"
"github.com/agentregistry-dev/agentregistry/internal/cli/common"
"github.com/agentregistry-dev/agentregistry/internal/cli/common/docker"
"github.com/agentregistry-dev/agentregistry/pkg/cli/annotations"
"github.com/agentregistry-dev/agentregistry/pkg/models"
"github.com/spf13/cobra"
)

var BuildCmd = &cobra.Command{
Use: "build [project-directory]",
Short: "Build Docker images for an agent project",
Use: "build [project-directory]",
Annotations: map[string]string{annotations.SkipDaemonAnnotation: "true"},
Short: "Build Docker images for an agent project",
Long: `Build Docker images for an agent project created with the init command.

This command looks for agent.yaml in the specified directory, regenerates template artifacts,
Expand Down
6 changes: 4 additions & 2 deletions internal/cli/agent/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/agentregistry-dev/agentregistry/internal/cli/agent/frameworks"
"github.com/agentregistry-dev/agentregistry/internal/cli/agent/frameworks/common"
"github.com/agentregistry-dev/agentregistry/internal/version"
"github.com/agentregistry-dev/agentregistry/pkg/cli/annotations"
"github.com/agentregistry-dev/agentregistry/pkg/validators"
"github.com/spf13/cobra"
)
Expand All @@ -22,8 +23,9 @@ const (
)

var InitCmd = &cobra.Command{
Use: "init [framework] [language] [agent-name]",
Short: "Initialize a new agent project",
Use: "init [framework] [language] [agent-name]",
Annotations: map[string]string{annotations.SkipDaemonAnnotation: "true"},
Short: "Initialize a new agent project",
Long: `Initialize a new agent project using the specified framework and language.

Supported frameworks and languages:
Expand Down
10 changes: 6 additions & 4 deletions internal/cli/configure/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"path/filepath"

"github.com/agentregistry-dev/agentregistry/internal/cli/common"
"github.com/agentregistry-dev/agentregistry/pkg/cli/annotations"
"github.com/spf13/cobra"
)

Expand All @@ -25,10 +26,11 @@ var clientConfigurers = map[string]ClientConfigurer{

// NewConfigureCmd creates the configure command
var ConfigureCmd = &cobra.Command{
Use: "configure [client-name]",
Short: "Configure a client",
Long: `Creates the .json configuration for each client, so it can connect to arctl.`,
Args: cobra.MaximumNArgs(1),
Use: "configure [client-name]",
Annotations: map[string]string{annotations.SkipDaemonAnnotation: "true"},
Short: "Configure a client",
Long: `Creates the .json configuration for each client, so it can connect to arctl.`,
Args: cobra.MaximumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
// Show supported clients if no argument provided
if len(args) == 0 {
Expand Down
6 changes: 4 additions & 2 deletions internal/cli/mcp/add_tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import (
"github.com/agentregistry-dev/agentregistry/internal/cli/mcp/frameworks"
"github.com/agentregistry-dev/agentregistry/internal/cli/mcp/manifest"
"github.com/agentregistry-dev/agentregistry/internal/cli/mcp/templates"
"github.com/agentregistry-dev/agentregistry/pkg/cli/annotations"
"github.com/spf13/cobra"
)

var AddToolCmd = &cobra.Command{
Use: "add-tool [tool-name]",
Short: "Add a new MCP tool to your project",
Use: "add-tool [tool-name]",
Annotations: map[string]string{annotations.SkipDaemonAnnotation: "true"},
Short: "Add a new MCP tool to your project",
Long: `Generate a new MCP tool that will be automatically loaded by the server.

This command creates a new tool file in src/tools/ with a generic template.
Expand Down
6 changes: 4 additions & 2 deletions internal/cli/mcp/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ import (
"github.com/agentregistry-dev/agentregistry/internal/cli/common/docker"
"github.com/agentregistry-dev/agentregistry/internal/cli/mcp/build"
"github.com/agentregistry-dev/agentregistry/internal/cli/mcp/manifest"
"github.com/agentregistry-dev/agentregistry/pkg/cli/annotations"
"github.com/agentregistry-dev/agentregistry/pkg/printer"

"github.com/spf13/cobra"
)

var BuildCmd = &cobra.Command{
Use: "build",
Short: "Build MCP server as a Docker image",
Use: "build",
Annotations: map[string]string{annotations.SkipDaemonAnnotation: "true"},
Short: "Build MCP server as a Docker image",
Long: `Build an MCP server from the current project.

This command will detect the project type and build the appropriate
Expand Down
6 changes: 4 additions & 2 deletions internal/cli/mcp/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ import (
"github.com/agentregistry-dev/agentregistry/internal/cli/mcp/frameworks"
"github.com/agentregistry-dev/agentregistry/internal/cli/mcp/manifest"
"github.com/agentregistry-dev/agentregistry/internal/cli/mcp/templates"
"github.com/agentregistry-dev/agentregistry/pkg/cli/annotations"
"github.com/agentregistry-dev/agentregistry/pkg/validators"

"github.com/spf13/cobra"
)

var InitCmd = &cobra.Command{
Use: "init [project-type] [project-name]",
Short: "Initialize a new MCP server project",
Use: "init [project-type] [project-name]",
Annotations: map[string]string{annotations.SkipDaemonAnnotation: "true"},
Short: "Initialize a new MCP server project",
Long: `Initialize a new MCP server project with dynamic tool loading.

This command provides subcommands to initialize a new MCP server project
Expand Down
6 changes: 4 additions & 2 deletions internal/cli/skill/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/agentregistry-dev/agentregistry/internal/cli/common"
"github.com/agentregistry-dev/agentregistry/internal/cli/common/docker"
"github.com/agentregistry-dev/agentregistry/pkg/cli/annotations"
"github.com/agentregistry-dev/agentregistry/pkg/printer"
"github.com/spf13/cobra"
)
Expand All @@ -15,8 +16,9 @@ import (
const skillDockerfile = "FROM scratch\nCOPY . .\n"

var BuildCmd = &cobra.Command{
Use: "build <skill-folder-path>",
Short: "Build a skill as a Docker image",
Use: "build <skill-folder-path>",
Annotations: map[string]string{annotations.SkipDaemonAnnotation: "true"},
Short: "Build a skill as a Docker image",
Long: `Build a skill from a local folder containing SKILL.md.

This command reads the SKILL.md frontmatter to determine the skill name,
Expand Down
10 changes: 6 additions & 4 deletions internal/cli/skill/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ import (
"path/filepath"

"github.com/agentregistry-dev/agentregistry/internal/cli/skill/templates"
"github.com/agentregistry-dev/agentregistry/pkg/cli/annotations"
"github.com/agentregistry-dev/agentregistry/pkg/validators"

"github.com/spf13/cobra"
)

var InitCmd = &cobra.Command{
Use: "init [skill-name]",
Short: "Initialize a new agentic skill project",
Long: `Initialize a new agentic skill project.`,
RunE: runInit,
Use: "init [skill-name]",
Annotations: map[string]string{annotations.SkipDaemonAnnotation: "true"},
Short: "Initialize a new agentic skill project",
Long: `Initialize a new agentic skill project.`,
RunE: runInit,
}

var (
Expand Down
8 changes: 5 additions & 3 deletions internal/cli/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/agentregistry-dev/agentregistry/internal/client"
"github.com/agentregistry-dev/agentregistry/internal/version"
"github.com/agentregistry-dev/agentregistry/pkg/cli/annotations"
)

var apiClient *client.Client
Expand All @@ -31,9 +32,10 @@ type versionOutput struct {
var jsonOutput bool

var VersionCmd = &cobra.Command{
Use: "version",
Short: "Show version information",
Long: `Displays the version of arctl.`,
Use: "version",
Short: "Show version information",
Long: `Displays the version of arctl.`,
Annotations: map[string]string{annotations.SkipDaemonAnnotation: "true"},
Run: func(cmd *cobra.Command, args []string) {
output := versionOutput{
ArctlVersion: version.Version,
Expand Down
8 changes: 8 additions & 0 deletions pkg/cli/annotations/annotations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package annotations

// SkipDaemonAnnotation is the cobra.Command annotation key that opts a command
// out of PersistentPreRunE setup (daemon connection, API client creation, etc.).
// Add it to any command's Annotations map with the value "true" to skip.
//
// Annotations: map[string]string{annotations.SkipDaemonAnnotation: "true"}
const SkipDaemonAnnotation = "skipDaemon"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should this be just called "SkipDaemon" ? since it's in the annotation package already

37 changes: 9 additions & 28 deletions pkg/cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/agentregistry-dev/agentregistry/internal/cli/prompt"
"github.com/agentregistry-dev/agentregistry/internal/cli/skill"
"github.com/agentregistry-dev/agentregistry/internal/client"
"github.com/agentregistry-dev/agentregistry/pkg/cli/annotations"
"github.com/agentregistry-dev/agentregistry/pkg/daemon/dockercompose"
"github.com/agentregistry-dev/agentregistry/pkg/types"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -149,40 +150,20 @@ func normalizeBaseURL(raw string) string {
return "http://" + trimmed
}

// preRunSkipCommands defines which commands skip pre-run setup (no API client needed).
// Key: parent name; value: set of subcommand names that skip setup.
var preRunSkipCommands = map[string]map[string]bool{
"arctl": {
"completion": true,
"configure": true,
"version": true,
},
"agent": {
"build": true,
"init": true,
},
"mcp": {
"add-tool": true,
"build": true,
"init": true,
},
"skill": {
"build": true,
"init": true,
},
}

// preRunBehavior returns whether to skip pre-run setup (e.g. agent/mcp/skill init).
// preRunBehavior returns whether to skip pre-run setup by walking the command
// hierarchy for the annotations.SkipDaemonAnnotation. Any ancestor having the annotation
// causes all descendants to skip as well. Cobra's auto-generated "completion"
// command cannot be annotated, so it is handled as a special case.
func preRunBehavior(cmd *cobra.Command) (skipSetup bool) {
if cmd == nil {
return false
}
for c := cmd; c != nil; c = c.Parent() {
parent := c.Parent()
if parent == nil {
break
if c.Annotations[annotations.SkipDaemonAnnotation] == "true" {
return true
}
if subcommands, ok := preRunSkipCommands[parent.Name()]; ok && subcommands[c.Name()] {
// Cobra's auto-generated completion command cannot be annotated.
if c.Name() == "completion" && c.Parent() != nil && c.Parent().Name() == "arctl" {
return true
}
}
Expand Down
23 changes: 13 additions & 10 deletions pkg/cli/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"testing"

"github.com/agentregistry-dev/agentregistry/internal/client"
"github.com/agentregistry-dev/agentregistry/pkg/cli/annotations"
"github.com/agentregistry-dev/agentregistry/pkg/types"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -35,39 +36,41 @@ func TestNormalizeBaseURL(t *testing.T) {
}

func TestPreRunBehavior(t *testing.T) {
skipAnnotation := map[string]string{annotations.SkipDaemonAnnotation: "true"}

root := &cobra.Command{Use: "arctl"}

agentCmd := &cobra.Command{Use: "agent"}
initCmd := &cobra.Command{Use: "init"}
buildCmd := &cobra.Command{Use: "build"}
initCmd := &cobra.Command{Use: "init", Annotations: skipAnnotation}
buildCmd := &cobra.Command{Use: "build", Annotations: skipAnnotation}
listCmd := &cobra.Command{Use: "list"}
agentCmd.AddCommand(initCmd)
agentCmd.AddCommand(buildCmd)
agentCmd.AddCommand(listCmd)

mcpCmd := &cobra.Command{Use: "mcp"}
mcpInitCmd := &cobra.Command{Use: "init"}
mcpBuildCmd := &cobra.Command{Use: "build"}
mcpAddToolCmd := &cobra.Command{Use: "add-tool"}
mcpInitCmd := &cobra.Command{Use: "init", Annotations: skipAnnotation}
mcpBuildCmd := &cobra.Command{Use: "build", Annotations: skipAnnotation}
mcpAddToolCmd := &cobra.Command{Use: "add-tool", Annotations: skipAnnotation}
mcpCmd.AddCommand(mcpInitCmd)
mcpCmd.AddCommand(mcpBuildCmd)
mcpCmd.AddCommand(mcpAddToolCmd)

skillCmd := &cobra.Command{Use: "skill"}
skillInitCmd := &cobra.Command{Use: "init"}
skillBuildCmd := &cobra.Command{Use: "build"}
skillInitCmd := &cobra.Command{Use: "init", Annotations: skipAnnotation}
skillBuildCmd := &cobra.Command{Use: "build", Annotations: skipAnnotation}
skillCmd.AddCommand(skillInitCmd)
skillCmd.AddCommand(skillBuildCmd)

// Subcommand under "mcp init" (e.g. arctl mcp init python mymcp)
// Subcommand under "mcp init" — inherits skip from annotated ancestor
initPythonCmd := &cobra.Command{Use: "python"}
mcpInitCmd.AddCommand(initPythonCmd)

configureCmd := &cobra.Command{Use: "configure"}
configureCmd := &cobra.Command{Use: "configure", Annotations: skipAnnotation}
completionCmd := &cobra.Command{Use: "completion"}
zshCompletionCmd := &cobra.Command{Use: "zsh"}
completionCmd.AddCommand(zshCompletionCmd)
versionCmd := &cobra.Command{Use: "version"}
versionCmd := &cobra.Command{Use: "version", Annotations: skipAnnotation}
root.AddCommand(agentCmd, mcpCmd, skillCmd, configureCmd, completionCmd, versionCmd)

tests := []struct {
Expand Down
Loading