@@ -17,22 +17,24 @@ import (
1717// wizardSeed lets the caller pre-fill some answers so already-supplied
1818// flags aren't asked for again.
1919type wizardSeed struct {
20- name string
21- rootfs string
22- ingress bool
23- netIDs []string
24- sshKeys []string // canonicalised key strings (NOT paths)
20+ name string
21+ rootfs string
22+ ingress bool
23+ netIDs []string
24+ sshKeys []string // canonicalised key strings (NOT paths)
25+ autoPauseSecs * int // nil = not supplied via flag
2526}
2627
2728// wizardResult is what runCreateWizard returns when the user finished.
2829// nil result = user cancelled (caller exits quietly).
2930type wizardResult struct {
30- shape string
31- name string
32- rootfs string
33- ingress bool
34- netIDs []string
35- sshKeys []string // canonicalised key strings (NOT paths)
31+ shape string
32+ name string
33+ rootfs string
34+ ingress bool
35+ netIDs []string
36+ sshKeys []string // canonicalised key strings (NOT paths)
37+ autoPauseSecs * int // nil = disabled
3638}
3739
3840// runCreateWizard walks the user through shape → name → rootfs → ingress
@@ -50,11 +52,12 @@ func runCreateWizard(c *cli.Context, client *api.SandboxClient, seed wizardSeed)
5052 return nil , fmt .Errorf ("please choose a size with --shape\n \n To see the options, run:\n createos sandbox shapes" )
5153 }
5254 out := & wizardResult {
53- name : seed .name ,
54- rootfs : seed .rootfs ,
55- ingress : seed .ingress ,
56- netIDs : append ([]string {}, seed .netIDs ... ),
57- sshKeys : append ([]string {}, seed .sshKeys ... ),
55+ name : seed .name ,
56+ rootfs : seed .rootfs ,
57+ ingress : seed .ingress ,
58+ netIDs : append ([]string {}, seed .netIDs ... ),
59+ sshKeys : append ([]string {}, seed .sshKeys ... ),
60+ autoPauseSecs : seed .autoPauseSecs ,
5861 }
5962
6063 // ── 1. Shape (required) ─────────────────────────────────────────
@@ -125,6 +128,16 @@ func runCreateWizard(c *cli.Context, client *api.SandboxClient, seed wizardSeed)
125128 }
126129 }
127130
131+ // ── 7. Auto-pause (optional; skip if already supplied via --auto-pause) ──
132+ if out .autoPauseSecs == nil {
133+ secs , err := wizardPickAutoPause ()
134+ if err != nil {
135+ pterm .Println (pterm .Gray (fmt .Sprintf (" Auto-pause step skipped (%v)." , err )))
136+ } else {
137+ out .autoPauseSecs = secs
138+ }
139+ }
140+
128141 return out , nil
129142}
130143
@@ -339,6 +352,33 @@ func relToHome(path, home string) string {
339352 return path
340353}
341354
355+ // wizardPickAutoPause asks whether the sandbox should pause itself when idle.
356+ // Returns nil (no auto-pause) if the user skips or types nothing.
357+ func wizardPickAutoPause () (* int , error ) {
358+ pterm .Println ()
359+ pterm .NewStyle (pterm .FgCyan ).Println (" Auto-pause" )
360+ pterm .Println (pterm .Gray (" Your sandbox can pause itself automatically when you're not using it," ))
361+ pterm .Println (pterm .Gray (" saving resources. It resumes instantly the next time you need it." ))
362+ pterm .Println (pterm .Gray (" Leave blank to keep it running until you stop it manually." ))
363+
364+ input , err := pterm .DefaultInteractiveTextInput .
365+ WithDefaultText ("Pause after how long with no activity? (e.g. 10m, 1h — leave blank to skip)" ).
366+ Show ()
367+ if err != nil {
368+ return nil , err
369+ }
370+ input = strings .TrimSpace (input )
371+ if input == "" {
372+ return nil , nil
373+ }
374+ secs , err := parseDurationToSeconds (input )
375+ if err != nil {
376+ pterm .Println (pterm .Gray (fmt .Sprintf (" Didn't recognise %q — skipping auto-pause." , input )))
377+ return nil , nil
378+ }
379+ return & secs , nil
380+ }
381+
342382// stringSliceCleanup trims and drops empty entries — pulled out of
343383// runCreate so the wizard plumbing can reuse it.
344384func stringSliceCleanup (raw []string ) []string {
0 commit comments