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
52 changes: 26 additions & 26 deletions .surface
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ CMD basecamp templates update
CMD basecamp timeline
CMD basecamp timesheet
CMD basecamp timesheet project
CMD basecamp timesheet recording
CMD basecamp timesheet item
CMD basecamp timesheet report
CMD basecamp todo
CMD basecamp todolistgroups
Expand Down Expand Up @@ -4660,30 +4660,30 @@ FLAG basecamp timesheet project --styled type=bool
FLAG basecamp timesheet project --to type=string
FLAG basecamp timesheet project --todolist type=string
FLAG basecamp timesheet project --verbose type=count
FLAG basecamp timesheet recording --account type=string
FLAG basecamp timesheet recording --agent type=bool
FLAG basecamp timesheet recording --cache-dir type=string
FLAG basecamp timesheet recording --count type=bool
FLAG basecamp timesheet recording --end type=string
FLAG basecamp timesheet recording --from type=string
FLAG basecamp timesheet recording --hints type=bool
FLAG basecamp timesheet recording --ids-only type=bool
FLAG basecamp timesheet recording --in type=string
FLAG basecamp timesheet recording --json type=bool
FLAG basecamp timesheet recording --markdown type=bool
FLAG basecamp timesheet recording --md type=bool
FLAG basecamp timesheet recording --no-hints type=bool
FLAG basecamp timesheet recording --no-stats type=bool
FLAG basecamp timesheet recording --person type=string
FLAG basecamp timesheet recording --profile type=string
FLAG basecamp timesheet recording --project type=string
FLAG basecamp timesheet recording --quiet type=bool
FLAG basecamp timesheet recording --start type=string
FLAG basecamp timesheet recording --stats type=bool
FLAG basecamp timesheet recording --styled type=bool
FLAG basecamp timesheet recording --to type=string
FLAG basecamp timesheet recording --todolist type=string
FLAG basecamp timesheet recording --verbose type=count
FLAG basecamp timesheet item --account type=string
FLAG basecamp timesheet item --agent type=bool
FLAG basecamp timesheet item --cache-dir type=string
FLAG basecamp timesheet item --count type=bool
FLAG basecamp timesheet item --end type=string
FLAG basecamp timesheet item --from type=string
FLAG basecamp timesheet item --hints type=bool
FLAG basecamp timesheet item --ids-only type=bool
FLAG basecamp timesheet item --in type=string
FLAG basecamp timesheet item --json type=bool
FLAG basecamp timesheet item --markdown type=bool
FLAG basecamp timesheet item --md type=bool
FLAG basecamp timesheet item --no-hints type=bool
FLAG basecamp timesheet item --no-stats type=bool
FLAG basecamp timesheet item --person type=string
FLAG basecamp timesheet item --profile type=string
FLAG basecamp timesheet item --project type=string
FLAG basecamp timesheet item --quiet type=bool
FLAG basecamp timesheet item --start type=string
FLAG basecamp timesheet item --stats type=bool
FLAG basecamp timesheet item --styled type=bool
FLAG basecamp timesheet item --to type=string
FLAG basecamp timesheet item --todolist type=string
FLAG basecamp timesheet item --verbose type=count
FLAG basecamp timesheet report --account type=string
FLAG basecamp timesheet report --agent type=bool
FLAG basecamp timesheet report --cache-dir type=string
Expand Down Expand Up @@ -6362,7 +6362,7 @@ SUB basecamp templates update
SUB basecamp timeline
SUB basecamp timesheet
SUB basecamp timesheet project
SUB basecamp timesheet recording
SUB basecamp timesheet item
SUB basecamp timesheet report
SUB basecamp todo
SUB basecamp todolistgroups
Expand Down
2 changes: 1 addition & 1 deletion e2e/errors.bats
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ load test_helper

run basecamp comment "test" --on
assert_failure
assert_output_contains "--on requires a recording ID"
assert_output_contains "--on requires an ID"
}

@test "cards --column without value shows error" {
Expand Down
2 changes: 1 addition & 1 deletion e2e/events.bats
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ load test_helper
run basecamp events --help
assert_success
assert_output_contains "basecamp events"
assert_output_contains "recording_id"
assert_output_contains "id|url"
assert_output_contains "audit"
}
2 changes: 1 addition & 1 deletion e2e/timesheet.bats
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ load test_helper
assert_output_contains "basecamp timesheet"
assert_output_contains "report"
assert_output_contains "project"
assert_output_contains "recording"
assert_output_contains "item"
}


Expand Down
13 changes: 10 additions & 3 deletions internal/cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ func transformCobraError(err error) error {
flag := after
// Special cases for flags with custom error messages
if flag == "--on" {
return output.ErrUsage("--on requires a recording ID")
return output.ErrUsage("--on requires an ID")
}
return output.ErrUsage(flag + " requires a value")
}
Expand Down Expand Up @@ -501,7 +501,7 @@ func transformCobraError(err error) error {
case "to":
return output.ErrUsage("Position required")
case "on":
return output.ErrUsage("Recording ID required")
return output.ErrUsage("ID required")
default:
return output.ErrUsage(flag + " required")
}
Expand Down Expand Up @@ -587,14 +587,21 @@ func emitAgentHelp(cmd *cobra.Command) {
}
}

// Subcommands
// Subcommands (include aliases so the CLI surface snapshot tracks them)
for _, sub := range cmd.Commands() {
if sub.IsAvailableCommand() || sub.Name() == "help" {
info.Subcommands = append(info.Subcommands, agentSubcommand{
Name: sub.Name(),
Short: sub.Short,
Path: sub.CommandPath(),
})
for _, alias := range sub.Aliases {
info.Subcommands = append(info.Subcommands, agentSubcommand{
Name: alias,
Short: sub.Short,
Path: strings.TrimSuffix(sub.CommandPath(), sub.Name()) + alias,
})
}
}
}

Expand Down
46 changes: 23 additions & 23 deletions internal/commands/boost.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ func NewBoostsCmd() *cobra.Command {
Use: "boost [action]",
Aliases: []string{"boosts"},
Short: "Manage boosts (reactions)",
Long: `Manage boosts (emoji reactions) on recordings.
Long: `Manage boosts (emoji reactions) on items.

Use 'basecamp boost list <recording-id>' to see boosts on a recording.
Use 'basecamp boost list <id>' to see boosts on an item.
Use 'basecamp boost show <boost-id>' to view a specific boost.
Use 'basecamp boost create <recording-id> "emoji"' to boost a recording.
Use 'basecamp boost create <id> "emoji"' to boost an item.
Use 'basecamp boost delete <boost-id>' to remove a boost.`,
Annotations: map[string]string{"agent_notes": "Boost content is typically an emoji but can be text\nbasecamp react is a shortcut for boost create"},
Args: cobra.MinimumNArgs(0),
Expand All @@ -48,15 +48,15 @@ func newBoostListCmd(project *string) *cobra.Command {
var eventID string

cmd := &cobra.Command{
Use: "list <recording-id|url>",
Short: "List boosts on a recording",
Long: `List boosts on a recording.
Use: "list <id|url>",
Short: "List boosts on an item",
Long: `List boosts on an item.

You can pass either a recording ID or a Basecamp URL:
You can pass either an ID or a Basecamp URL:
basecamp boost list 789 --project my-project
basecamp boost list https://3.basecamp.com/123/buckets/456/todos/789

Use --event to list boosts on a specific event within the recording.`,
Use --event to list boosts on a specific event within the item.`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
app := appctx.FromContext(cmd.Context())
Expand Down Expand Up @@ -99,7 +99,7 @@ func runBoostList(cmd *cobra.Command, app *appctx.App, recording, project, event

recordingIDInt, err := strconv.ParseInt(recordingID, 10, 64)
if err != nil {
return output.ErrUsage("Invalid recording ID")
return output.ErrUsage("Invalid ID")
}

if eventID != "" {
Expand Down Expand Up @@ -140,7 +140,7 @@ func runBoostList(cmd *cobra.Command, app *appctx.App, recording, project, event
output.Breadcrumb{
Action: "create",
Cmd: fmt.Sprintf("basecamp boost create %s \"emoji\" --project %s", recordingID, resolvedProjectID),
Description: "Boost this recording",
Description: "Boost this item",
},
),
)
Expand Down Expand Up @@ -224,15 +224,15 @@ func newBoostCreateCmd(project *string) *cobra.Command {
var eventID string

cmd := &cobra.Command{
Use: "create <recording-id|url> <content>",
Short: "Boost a recording",
Long: `Boost a recording with an emoji reaction.
Use: "create <id|url> <content>",
Short: "Boost an item",
Long: `Boost an item with an emoji reaction.

You can pass either a recording ID or a Basecamp URL:
You can pass either an ID or a Basecamp URL:
basecamp boost create 789 "🎉" --project my-project
basecamp boost create https://3.basecamp.com/123/buckets/456/todos/789 "👍"

Use --event to boost a specific event within the recording.`,
Use --event to boost a specific event within the item.`,
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
app := appctx.FromContext(cmd.Context())
Expand Down Expand Up @@ -275,7 +275,7 @@ func runBoostCreate(cmd *cobra.Command, app *appctx.App, recording, project, con

recordingIDInt, err := strconv.ParseInt(recordingID, 10, 64)
if err != nil {
return output.ErrUsage("Invalid recording ID")
return output.ErrUsage("Invalid ID")
}

if eventID != "" {
Expand Down Expand Up @@ -331,7 +331,7 @@ func newBoostDeleteCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "delete <boost-id|url>",
Short: "Delete a boost",
Long: `Delete a boost from a recording.
Long: `Delete a boost.

You can pass either a boost ID or a Basecamp URL:
basecamp boost delete 789
Expand Down Expand Up @@ -365,7 +365,7 @@ You can pass either a boost ID or a Basecamp URL:
output.WithBreadcrumbs(
output.Breadcrumb{
Action: "list",
Cmd: "basecamp boost list <recording-id> --project <project>",
Cmd: "basecamp boost list <id> --project <project>",
Description: "View boosts",
},
),
Expand All @@ -383,10 +383,10 @@ func NewBoostShortcutCmd() *cobra.Command {

cmd := &cobra.Command{
Use: "react <content>",
Short: "Boost a recording",
Long: `Boost a recording with an emoji reaction (shortcut for boost create).
Short: "React with an emoji",
Long: `React to an item with an emoji (shortcut for boost create).

Content as positional argument, --on for the recording:
Content as positional argument, --on for the item:
basecamp react "🎉" --on 789 --project my-project
basecamp react "👍" --on https://3.basecamp.com/123/buckets/456/todos/789`,
Args: cobra.ExactArgs(1),
Expand All @@ -406,8 +406,8 @@ Content as positional argument, --on for the recording:
},
}

cmd.Flags().StringVarP(&recording, "on", "r", "", "Recording ID or URL to boost")
cmd.Flags().StringVar(&recording, "recording", "", "Recording ID or URL (alias for --on)")
cmd.Flags().StringVarP(&recording, "on", "r", "", "ID or URL to react to")
cmd.Flags().StringVar(&recording, "recording", "", "ID or URL (alias for --on)")
cmd.Flags().StringVar(&eventID, "event", "", "Event ID (for event-specific boosts)")
cmd.Flags().StringVarP(&project, "project", "p", "", "Project ID or name")
cmd.Flags().StringVar(&project, "in", "", "Project ID (alias for --project)")
Expand Down
12 changes: 6 additions & 6 deletions internal/commands/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ func CommandCategories() []CommandCategory {
{Name: "message", Category: "shortcut", Description: "Post a message"},
{Name: "card", Category: "shortcut", Description: "Create a card"},
{Name: "comment", Category: "shortcut", Description: "Add a comment"},
{Name: "assign", Category: "shortcut", Description: "Assign a recording"},
{Name: "assign", Category: "shortcut", Description: "Assign someone to an item"},
{Name: "unassign", Category: "shortcut", Description: "Remove assignment"},
{Name: "react", Category: "shortcut", Description: "Boost a recording"},
{Name: "react", Category: "shortcut", Description: "React with an emoji"},
},
},
{
Expand All @@ -70,7 +70,7 @@ func CommandCategories() []CommandCategory {
Name: "Scheduling & Time",
Commands: []CommandInfo{
{Name: "schedule", Category: "scheduling", Description: "Manage schedule entries", Actions: []string{"show", "entries", "create", "update"}},
{Name: "timesheet", Category: "scheduling", Description: "Manage time tracking", Actions: []string{"report", "project", "recording"}},
{Name: "timesheet", Category: "scheduling", Description: "Manage time tracking", Actions: []string{"report", "project", "item"}},
{Name: "checkins", Category: "scheduling", Description: "View automatic check-ins", Actions: []string{"questions", "question", "answers", "answer"}},
{Name: "timeline", Category: "scheduling", Description: "View activity timelines", Actions: []string{}},
{Name: "reports", Category: "scheduling", Description: "View reports", Actions: []string{"assignable", "assigned", "overdue", "schedule"}},
Expand Down Expand Up @@ -100,9 +100,9 @@ func CommandCategories() []CommandCategory {
Name: "Search & Browse",
Commands: []CommandInfo{
{Name: "search", Category: "search", Description: "Search across projects"},
{Name: "recordings", Category: "search", Description: "Browse recordings by type/status", Actions: []string{"list", "trash", "archive", "restore", "visibility"}},
{Name: "show", Category: "search", Description: "Show any recording by ID"},
{Name: "events", Category: "search", Description: "View recording change history"},
{Name: "recordings", Category: "search", Description: "Browse content by type across projects", Actions: []string{"list", "trash", "archive", "restore", "visibility"}},
{Name: "show", Category: "search", Description: "Show any item by ID"},
{Name: "events", Category: "search", Description: "View change history"},
{Name: "url", Category: "search", Description: "Parse Basecamp URLs"},
},
},
Expand Down
Loading
Loading