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
85 changes: 76 additions & 9 deletions docs/commands/scheduler.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,94 @@ nylas scheduler configurations list --json
nylas scheduler configurations show <config-id>
nylas scheduler configs show <config-id>

# Create a new configuration
nylas scheduler configurations create \\
--name "30 Min Meeting" \\
--duration 30 \\
--interval 15
# Create a simple configuration
nylas scheduler configurations create \
--name "30 Min Meeting" \
--title "30 Min Meeting" \
--participants alice@co.com \
--duration 30

# Create with availability settings
nylas scheduler configurations create \
--name "Product Demo" \
--title "Product Demo" \
--participants alice@co.com \
--duration 30 \
--interval 15 \
--buffer-before 5 \
--buffer-after 10 \
--conferencing-provider "Google Meet" \
--min-booking-notice 120 \
--available-days-in-future 30

# Create from a JSON file
nylas scheduler configurations create --file config.json

# Create from file with flag overrides
nylas scheduler configurations create --file config.json --duration 60

# Update a configuration
nylas scheduler configurations update <config-id> \\
--name "Updated Name" \\
--duration 60
nylas scheduler configurations update <config-id> \
--name "Updated Name" \
--duration 60 \
--buffer-before 10

# Update from a JSON file
nylas scheduler configurations update <config-id> --file update.json

# Delete a configuration
nylas scheduler configurations delete <config-id>
nylas scheduler configs delete <config-id> -f # Skip confirmation
nylas scheduler configs delete <config-id> -y # Skip confirmation
```

**Configuration Flags:**

| Flag | Type | Description |
|------|------|-------------|
| `--name` | string | Configuration name |
| `--participants` | strings | Participant emails (comma-separated, first is organizer) |
| `--duration` | int | Meeting duration in minutes (default: 30) |
| `--title` | string | Event title |
| `--description` | string | Event description |
| `--location` | string | Event location |
| `--interval` | int | Slot interval in minutes |
| `--round-to` | int | Round start times to nearest N minutes |
| `--availability-method` | string | `max-fairness` or `max-availability` |
| `--buffer-before` | int | Buffer minutes before meetings |
| `--buffer-after` | int | Buffer minutes after meetings |
| `--timezone` | string | Event timezone (e.g., `America/New_York`) |
| `--booking-type` | string | `booking` or `organizer-confirmation` |
| `--conferencing-provider` | string | `Google Meet`, `Zoom`, or `Microsoft Teams` |
| `--disable-emails` | bool | Disable email notifications |
| `--reminder-minutes` | ints | Reminder minutes (e.g., `10,60`) |
| `--min-booking-notice` | int | Minimum minutes before booking |
| `--min-cancellation-notice` | int | Minimum minutes before cancellation |
| `--confirmation-method` | string | `automatic` or `manual` |
| `--available-days-in-future` | int | Days in advance bookings are available |
| `--cancellation-policy` | string | Cancellation policy text |
| `--file` | string | JSON config file (flags override file values) |
| `--json` | bool | Output as JSON |

**File Input:**

The `--file` flag accepts a JSON file matching the API request structure. You can export an existing configuration with `--json`, edit it, and re-import:

```bash
# Export → edit → recreate
nylas scheduler configs show abc123 --json > meeting.json
# Edit meeting.json...
nylas scheduler configs create --file meeting.json
```

When both `--file` and flags are provided, flags take precedence over file values.

**Configuration Features:**
- Duration and interval settings
- Availability rules and windows
- Buffer times before/after meetings
- Conferencing auto-creation (Google Meet, Zoom, Teams)
- Booking limits and restrictions
- Reminder notifications
- Custom event settings

### Scheduler Sessions
Expand Down
162 changes: 75 additions & 87 deletions internal/cli/scheduler/configurations.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"strings"

"github.com/nylas/cli/internal/cli/common"
"github.com/nylas/cli/internal/domain"
"github.com/nylas/cli/internal/ports"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -93,30 +92,7 @@ func newConfigShowCmd() *cobra.Command {
return struct{}{}, json.NewEncoder(cmd.OutOrStdout()).Encode(config)
}

_, _ = common.Bold.Printf("Configuration: %s\n", config.Name)
fmt.Printf(" ID: %s\n", common.Cyan.Sprint(config.ID))
fmt.Printf(" Slug: %s\n", common.Green.Sprint(config.Slug))
fmt.Printf(" Duration: %d minutes\n", config.Availability.DurationMinutes)

if len(config.Participants) > 0 {
fmt.Printf("\nParticipants (%d):\n", len(config.Participants))
for i, p := range config.Participants {
fmt.Printf(" %d. %s <%s>", i+1, p.Name, p.Email)
if p.IsOrganizer {
fmt.Printf(" %s", common.Green.Sprint("(Organizer)"))
}
fmt.Println()
}
}

fmt.Printf("\nEvent Booking:\n")
fmt.Printf(" Title: %s\n", config.EventBooking.Title)
if config.EventBooking.Description != "" {
fmt.Printf(" Description: %s\n", config.EventBooking.Description)
}
if config.EventBooking.Location != "" {
fmt.Printf(" Location: %s\n", config.EventBooking.Location)
}
formatConfigDetails(cmd.OutOrStdout(), config)

return struct{}{}, nil
})
Expand All @@ -139,47 +115,56 @@ func newConfigCreateCmd() *cobra.Command {
location string
jsonOutput bool
)
flags := &configFlags{}

cmd := &cobra.Command{
Use: "create",
Short: "Create a scheduler configuration",
Long: "Create a new scheduler configuration (meeting type).",
Long: `Create a new scheduler configuration (meeting type).

Use flags for common settings, or --file for full JSON config input.
When both are provided, flags override file values.`,
Example: ` # Simple inline creation
nylas scheduler configs create --name "Quick Chat" --title "Quick Chat" \
--participants alice@co.com --duration 15

# With availability settings
nylas scheduler configs create --name "Product Demo" --title "Demo" \
--participants alice@co.com --duration 30 --interval 15 \
--buffer-before 5 --buffer-after 10 --conferencing-provider "Google Meet"

# From a JSON file
nylas scheduler configs create --file config.json

# File as base, override specific values
nylas scheduler configs create --file config.json --duration 60`,
RunE: func(cmd *cobra.Command, args []string) error {
// Validate participants
if len(participants) == 0 {
return common.NewUserError("at least one participant email is required", "Use --participant to specify email addresses")
}
for i, p := range participants {
p = strings.TrimSpace(p)
if p == "" {
return fmt.Errorf("participant email at position %d cannot be empty", i+1)
}
participants[i] = p
if err := validateConfigFlags(flags); err != nil {
return err
}

_, err := common.WithClient(args, func(ctx context.Context, client ports.NylasClient, grantID string) (struct{}, error) {
// Build participants list
var participantsList []domain.ConfigurationParticipant
for i, email := range participants {
participantsList = append(participantsList, domain.ConfigurationParticipant{
Email: email,
IsOrganizer: i == 0, // First participant is organizer
})
if flags.file == "" {
if len(participants) == 0 {
return common.NewUserError("at least one participant email is required", "Use --participants to specify email addresses")
}

req := &domain.CreateSchedulerConfigurationRequest{
Name: name,
Participants: participantsList,
Availability: domain.AvailabilityRules{
DurationMinutes: duration,
},
EventBooking: domain.EventBooking{
Title: title,
Description: description,
Location: location,
},
for i, p := range participants {
p = strings.TrimSpace(p)
if p == "" {
return fmt.Errorf("participant email at position %d cannot be empty", i+1)
}
participants[i] = p
}
}

req, err := buildCreateRequest(cmd, flags, name, participants, duration, title, description, location)
if err != nil {
return err
}
if err := validateCreateRequest(req); err != nil {
return err
}

_, err = common.WithClient(args, func(ctx context.Context, client ports.NylasClient, grantID string) (struct{}, error) {
config, err := client.CreateSchedulerConfiguration(ctx, req)
if err != nil {
return struct{}{}, common.WrapCreateError("configuration", err)
Expand All @@ -201,19 +186,16 @@ func newConfigCreateCmd() *cobra.Command {
},
}

cmd.Flags().StringVar(&name, "name", "", "Configuration name (required)")
cmd.Flags().StringVar(&name, "name", "", "Configuration name")
cmd.Flags().StringSliceVar(&participants, "participants", []string{}, "Participant emails (comma-separated, first is organizer)")
cmd.Flags().IntVar(&duration, "duration", 30, "Meeting duration in minutes")
cmd.Flags().StringVar(&title, "title", "", "Event title (required)")
cmd.Flags().StringVar(&title, "title", "", "Event title")
cmd.Flags().StringVar(&description, "description", "", "Event description")
cmd.Flags().StringVar(&location, "location", "", "Event location")

_ = cmd.MarkFlagRequired("name")
_ = cmd.MarkFlagRequired("participants")
_ = cmd.MarkFlagRequired("title")

cmd.Flags().BoolVar(&jsonOutput, "json", false, "Output as JSON")

registerConfigFlags(cmd, flags)

return cmd
}

Expand All @@ -225,38 +207,42 @@ func newConfigUpdateCmd() *cobra.Command {
description string
jsonOutput bool
)
flags := &configFlags{}

cmd := &cobra.Command{
Use: "update <config-id>",
Short: "Update a scheduler configuration",
Long: "Update an existing scheduler configuration.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
configID := args[0]
_, err := common.WithClient(args, func(ctx context.Context, client ports.NylasClient, grantID string) (struct{}, error) {
req := &domain.UpdateSchedulerConfigurationRequest{}
Long: `Update an existing scheduler configuration.

if name != "" {
req.Name = &name
}
Use flags to set specific fields, or --file for full JSON update.
When both are provided, flags override file values.`,
Example: ` # Update specific fields
nylas scheduler configs update abc123 --name "Updated Name" --duration 60

if cmd.Flags().Changed("duration") {
req.Availability = &domain.AvailabilityRules{
DurationMinutes: duration,
}
}
# Add buffer times
nylas scheduler configs update abc123 --buffer-before 5 --buffer-after 10

if cmd.Flags().Changed("title") || cmd.Flags().Changed("description") {
eventBooking := &domain.EventBooking{}
if cmd.Flags().Changed("title") {
eventBooking.Title = title
}
if cmd.Flags().Changed("description") {
eventBooking.Description = description
}
req.EventBooking = eventBooking
}
# From a JSON file
nylas scheduler configs update abc123 --file update.json

# File as base, override specific values
nylas scheduler configs update abc123 --file update.json --duration 45`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
if err := validateConfigFlags(flags); err != nil {
return err
}

configID := args[0]
req, err := buildUpdateRequest(cmd, flags, name, duration, title, description)
if err != nil {
return err
}
if err := validateUpdateRequest(req); err != nil {
return err
}

_, err = common.WithClient(args, func(ctx context.Context, client ports.NylasClient, grantID string) (struct{}, error) {
config, err := client.UpdateSchedulerConfiguration(ctx, configID, req)
if err != nil {
return struct{}{}, common.WrapUpdateError("configuration", err)
Expand All @@ -280,6 +266,8 @@ func newConfigUpdateCmd() *cobra.Command {
cmd.Flags().StringVar(&description, "description", "", "Event description")
cmd.Flags().BoolVar(&jsonOutput, "json", false, "Output as JSON")

registerConfigFlags(cmd, flags)

return cmd
}

Expand Down
Loading
Loading