Skip to content
Merged
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: 3 additions & 3 deletions cmd/gh-aw/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -662,11 +662,11 @@ Use "` + string(constants.CLIExtensionPrefix) + ` help all" to show help for all
// Add flags to new command
newCmd.Flags().BoolP("force", "f", false, "Overwrite existing files without confirmation")
newCmd.Flags().BoolP("interactive", "i", false, "Launch interactive workflow creation wizard")
newCmd.Flags().StringP("engine", "e", "", "Override AI engine (claude, codex, copilot, custom)")
newCmd.Flags().StringP("engine", "e", "", "Override AI engine (copilot, claude, codex, gemini, crush)")
cli.RegisterEngineFlagCompletion(newCmd)

// Add AI flag to compile and add commands
compileCmd.Flags().StringP("engine", "e", "", "Override AI engine (claude, codex, copilot, custom)")
compileCmd.Flags().StringP("engine", "e", "", "Override AI engine (copilot, claude, codex, gemini, crush)")
compileCmd.Flags().String("action-mode", "", "Action script inlining mode (inline, dev, release). Auto-detected if not specified")
compileCmd.Flags().String("action-tag", "", "Override action SHA or tag for actions/setup (overrides action-mode to release). Accepts full SHA or tag name")
compileCmd.Flags().String("actions-repo", "", "Override the external actions repository used in action mode (default: github/gh-aw-actions)")
Expand Down Expand Up @@ -727,7 +727,7 @@ Use "` + string(constants.CLIExtensionPrefix) + ` help all" to show help for all
// Add flags to run command
runCmd.Flags().Int("repeat", 0, "Number of additional times to run after the initial execution (e.g., --repeat 3 runs 4 times total)")
runCmd.Flags().Bool("enable-if-needed", false, "Enable the workflow before running if needed, and restore state afterward")
runCmd.Flags().StringP("engine", "e", "", "Override AI engine (claude, codex, copilot, custom)")
runCmd.Flags().StringP("engine", "e", "", "Override AI engine (copilot, claude, codex, gemini, crush)")
runCmd.Flags().StringP("repo", "r", "", "Target repository ([HOST/]owner/repo format). Defaults to current repository")
runCmd.Flags().String("ref", "", "Branch or tag name to run the workflow on (default: current branch)")
runCmd.Flags().Bool("auto-merge-prs", false, "Auto-merge any pull requests created during the workflow execution")
Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/add_wizard_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func NewAddWizardCommand(validateEngine func(string) error) *cobra.Command {
Long: `Interactively add one or more agentic workflows with guided setup.

This command walks you through:
- Selecting an AI engine (Copilot, Claude, or Codex)
- Selecting an AI engine (Copilot, Claude, Codex, Gemini, or Crush)
- Configuring API keys and secrets
- Creating a pull request with the workflow
- Optionally running the workflow immediately
Expand Down
16 changes: 16 additions & 0 deletions pkg/cli/add_wizard_command_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//go:build !integration

package cli

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestAddWizardCommandMentionsCrush(t *testing.T) {
cmd := NewAddWizardCommand(func(string) error { return nil })
require.NotNil(t, cmd, "Add wizard command should be created")
assert.Contains(t, cmd.Long, "Copilot, Claude, Codex, Gemini, or Crush", "Add wizard help should mention all interactive engine options")
}
2 changes: 1 addition & 1 deletion pkg/cli/completion_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func NewCompletionCommand() *cobra.Command {
Tab completion provides:
- Command name completion (add, compile, run, etc.)
- Workflow name completion for commands that accept workflow arguments
- Engine name completion for --engine flag (copilot, claude, codex, custom)
- Engine name completion for --engine flag (copilot, claude, codex, gemini, crush)
- Directory path completion for --dir flag
- Helpful descriptions for workflows when available

Expand Down
10 changes: 8 additions & 2 deletions pkg/cli/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@ package cli

import "github.com/spf13/cobra"

const engineFlagHelpList = "copilot, claude, codex, gemini, crush"

func engineFlagUsage(prefix string) string {
return prefix + " (" + engineFlagHelpList + ")"
}

// addEngineFlag adds the --engine/-e flag to a command.
// This flag allows overriding the AI engine type.
func addEngineFlag(cmd *cobra.Command) {
cmd.Flags().StringP("engine", "e", "", "Override AI engine (claude, codex, copilot, custom)")
cmd.Flags().StringP("engine", "e", "", engineFlagUsage("Override AI engine"))
}

// addEngineFilterFlag adds the --engine/-e flag to a command for filtering.
// This flag allows filtering results by AI engine type.
func addEngineFilterFlag(cmd *cobra.Command) {
cmd.Flags().StringP("engine", "e", "", "Filter logs by AI engine (claude, codex, copilot, custom)")
cmd.Flags().StringP("engine", "e", "", engineFlagUsage("Filter logs by AI engine"))
}
Comment on lines 11 to 21

// addRepoFlag adds the --repo/-r flag to a command.
Expand Down
27 changes: 27 additions & 0 deletions pkg/cli/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,30 @@ func createDisableCommandStub() *cobra.Command {
cmd.Flags().StringP("repo", "r", "", "Target repository")
return cmd
}

func TestEngineFlagUsageText(t *testing.T) {
t.Parallel()

overrideCmd := &cobra.Command{Use: "override-test"}
addEngineFlag(overrideCmd)

engineFlag := overrideCmd.Flags().Lookup("engine")
if engineFlag == nil {
t.Fatal("Expected --engine override flag to exist")
}

if engineFlag.Usage != "Override AI engine (copilot, claude, codex, gemini, crush)" {
t.Errorf("Unexpected --engine override usage text: %s", engineFlag.Usage)
}

filterCmd := &cobra.Command{Use: "filter-test"}
addEngineFilterFlag(filterCmd)
filterFlag := filterCmd.Flags().Lookup("engine")
if filterFlag == nil {
t.Fatal("Expected --engine filter flag to exist")
}

if filterFlag.Usage != "Filter logs by AI engine (copilot, claude, codex, gemini, crush)" {
t.Errorf("Unexpected --engine filter usage text: %s", filterFlag.Usage)
}
}
4 changes: 2 additions & 2 deletions pkg/cli/health_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Shows health metrics for workflows including:
- Success/failure rates over time period
- Trend indicators (↑ improving, → stable, ↓ degrading)
- Average execution duration
- Alerts when success rate drops below threshold
- Warnings when success rate drops below threshold

When called without a workflow name, displays summary for all workflows.
When called with a specific workflow name, displays detailed metrics for that workflow.
Expand All @@ -51,7 +51,7 @@ Examples:
` + string(constants.CLIExtensionPrefix) + ` health # Summary of all workflows (last 7 days)
` + string(constants.CLIExtensionPrefix) + ` health issue-monster # Detailed metrics for specific workflow
` + string(constants.CLIExtensionPrefix) + ` health --days 30 # Summary for last 30 days
` + string(constants.CLIExtensionPrefix) + ` health --threshold 90 # Alert if below 90% success rate
` + string(constants.CLIExtensionPrefix) + ` health --threshold 90 # Warn if below 90% success rate
` + string(constants.CLIExtensionPrefix) + ` health --json # Output in JSON format
` + string(constants.CLIExtensionPrefix) + ` health issue-monster --days 90 # 90-day metrics for workflow`,
Args: cobra.MaximumNArgs(1),
Expand Down
1 change: 1 addition & 0 deletions pkg/cli/health_command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func TestHealthCommand(t *testing.T) {
assert.NotNil(t, cmd, "Health command should be created")
assert.Equal(t, "health", cmd.Name(), "Command name should be 'health'")
assert.True(t, cmd.HasAvailableFlags(), "Command should have flags")
assert.Contains(t, cmd.Long, "Warnings when success rate drops below threshold", "Health help should consistently use warnings terminology")

// Check that required flags are registered
daysFlag := cmd.Flags().Lookup("days")
Expand Down
17 changes: 7 additions & 10 deletions pkg/cli/init_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,11 @@ func NewInitCommand() *cobra.Command {
Short: "Initialize the repository for agentic workflows",
Long: `Initialize the repository for agentic workflows by configuring .gitattributes and creating the dispatcher agent file.

Interactive Mode (default):
Usage:
gh aw init

When invoked without flags, init enters interactive mode and prompts you to:
- Select which AI engine to use (Copilot, Claude, or Codex)
- Automatically configure engine-specific settings (e.g., MCP for Copilot)
- Detect and configure secrets from your environment
- Set up repository Actions secrets automatically

This command performs non-interactive repository setup and does not prompt for
engine selection or secret configuration.

This command:
- Configures .gitattributes to mark .lock.yml files as generated
Expand Down Expand Up @@ -59,8 +56,8 @@ After running this command, you can:
- Create new workflows from scratch with: ` + string(constants.CLIExtensionPrefix) + ` new <workflow-name>

Examples:
` + string(constants.CLIExtensionPrefix) + ` init # Interactive mode
` + string(constants.CLIExtensionPrefix) + ` init -v # Interactive with verbose output
` + string(constants.CLIExtensionPrefix) + ` init # Initialize repository with defaults
` + string(constants.CLIExtensionPrefix) + ` init -v # Initialize with verbose output
` + string(constants.CLIExtensionPrefix) + ` init --no-mcp # Skip MCP configuration
` + string(constants.CLIExtensionPrefix) + ` init --codespaces # Configure Codespaces
` + string(constants.CLIExtensionPrefix) + ` init --codespaces repo1,repo2 # Codespaces with additional repos
Expand Down Expand Up @@ -117,7 +114,7 @@ Examples:
},
}

cmd.Flags().StringP("engine", "e", "", "Override AI engine (claude, codex, copilot, custom)")
cmd.Flags().StringP("engine", "e", "", "Override AI engine (copilot, claude, codex, gemini, crush)")
_ = cmd.Flags().MarkHidden("engine") // Hide the engine flag from help output (internal use only)
cmd.Flags().Bool("no-mcp", false, "Skip configuring gh-aw MCP server integration for GitHub Copilot Agent")
cmd.Flags().String("codespaces", "", "Create devcontainer.json for GitHub Codespaces with agentic workflows support. Specify comma-separated repository names in the same organization (e.g., repo1,repo2), or use without value for current repo only")
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/init_command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ func TestInitCommandHelp(t *testing.T) {
t.Error("Expected help text to mention Copilot")
}

if !strings.Contains(helpText, "Interactive Mode") {
t.Error("Expected help text to mention Interactive Mode")
if !strings.Contains(helpText, "non-interactive repository setup") {
t.Error("Expected help text to mention non-interactive setup")
}
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/logs_filtering_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func TestLogsCommandFlags(t *testing.T) {
t.Fatal("Engine flag not found")
}

if engineFlag.Usage != "Filter logs by AI engine (claude, codex, copilot, custom)" {
if engineFlag.Usage != "Filter logs by AI engine (copilot, claude, codex, gemini, crush)" {
t.Errorf("Unexpected engine flag usage text: %s", engineFlag.Usage)
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/project_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Examples:
func NewProjectNewCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "new <title>",
Short: "Create a new GitHub Project V2",
Short: "Create a new GitHub Project V2 board",
Long: `Create a new GitHub Project V2 board owned by a user or organization.

The project can optionally be linked to a specific repository.
Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/project_command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestNewProjectNewCommand(t *testing.T) {
cmd := NewProjectNewCommand()
require.NotNil(t, cmd, "Command should be created")
assert.Equal(t, "new <title>", cmd.Use, "Command usage should be 'new <title>'")
assert.Contains(t, cmd.Short, "Create a new GitHub Project V2", "Short description should be about creating projects")
assert.Contains(t, cmd.Short, "Create a new GitHub Project V2 board", "Short description should mention board creation")

// Check flags
ownerFlag := cmd.Flags().Lookup("owner")
Expand Down
8 changes: 6 additions & 2 deletions pkg/cli/upgrade_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ This command:
3. Updates GitHub Actions versions in .github/aw/actions-lock.json (unless --no-actions is set)
4. Compiles all workflows to generate lock files (like 'compile' command)

Flag behavior:
- --no-fix skips codemods, action version updates, and workflow compilation
- --no-actions and --no-compile are only applied when --no-fix is not set

DEPENDENCY HEALTH AUDIT:
Use --audit to check dependency health without performing upgrades. This includes:
- Outdated Go dependencies with available updates
Expand Down Expand Up @@ -105,8 +109,8 @@ Examples:

cmd.Flags().StringP("dir", "d", "", "Workflow directory (default: .github/workflows)")
cmd.Flags().Bool("no-fix", false, "Skip codemods, action version updates, and workflow compilation (only update agent files)")
cmd.Flags().Bool("no-actions", false, "Skip updating GitHub Actions versions")
cmd.Flags().Bool("no-compile", false, "Skip recompiling workflows (do not modify lock files)")
cmd.Flags().Bool("no-actions", false, "Skip updating GitHub Actions versions (ignored when --no-fix is set)")
cmd.Flags().Bool("no-compile", false, "Skip recompiling workflows (do not modify lock files; ignored when --no-fix is set)")
cmd.Flags().Bool("create-pull-request", false, "Create a pull request with the upgrade changes")
cmd.Flags().Bool("pr", false, "Alias for --create-pull-request")
_ = cmd.Flags().MarkHidden("pr") // Hide the short alias from help output
Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/validate_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Examples:
},
}

cmd.Flags().StringP("engine", "e", "", "Override AI engine (claude, codex, copilot, custom)")
addEngineFlag(cmd)
cmd.Flags().StringP("dir", "d", "", "Workflow directory (default: .github/workflows)")
cmd.Flags().Bool("strict", false, "Override frontmatter to enforce strict mode validation for all workflows (enforces action pinning, network config, safe-outputs, refuses write permissions and deprecated fields). Note: Workflows default to strict mode unless frontmatter sets strict: false")
cmd.Flags().BoolP("json", "j", false, "Output results in JSON format")
Expand Down