onboard: make encryption opt-in via --enc flag

Encryption (passphrase prompt + SSH key generation) is now only
triggered when the user passes --enc to 'picoclaw onboard'.
Without the flag, onboard skips the credential-encryption setup and
writes a plain config + workspace templates directly.

- Add --enc BoolFlag in NewOnboardCommand()
- Pass encrypt bool into onboard()
- Guard passphrase prompt, SSH key generation, and related env-var
  setup behind the encrypt branch
- Adjust 'Next steps' output so the passphrase reminder only appears
  when --enc was used
This commit is contained in:
sky5454 2026-03-16 12:15:56 +08:00
parent 71fbf6db9d
commit e29ee04a18
3 changed files with 54 additions and 37 deletions

View file

@ -11,14 +11,19 @@ import (
var embeddedFiles embed.FS
func NewOnboardCommand() *cobra.Command {
var encrypt bool
cmd := &cobra.Command{
Use: "onboard",
Aliases: []string{"o"},
Short: "Initialize picoclaw configuration and workspace",
Run: func(cmd *cobra.Command, args []string) {
onboard()
onboard(encrypt)
},
}
cmd.Flags().BoolVar(&encrypt, "enc", false,
"Enable credential encryption (generates SSH key and prompts for passphrase)")
return cmd
}

View file

@ -24,6 +24,9 @@ func TestNewOnboardCommand(t *testing.T) {
assert.Nil(t, cmd.PersistentPreRun)
assert.Nil(t, cmd.PersistentPostRun)
assert.False(t, cmd.HasFlags())
assert.True(t, cmd.HasFlags())
encFlag := cmd.Flags().Lookup("enc")
require.NotNil(t, encFlag, "expected --enc flag to be registered")
assert.Equal(t, "false", encFlag.DefValue, "--enc should default to false")
assert.False(t, cmd.HasSubCommands())
}

View file

@ -13,12 +13,13 @@ import (
"github.com/sipeed/picoclaw/pkg/credential"
)
func onboard() {
func onboard(encrypt bool) {
configPath := internal.GetConfigPath()
configExists := false
if _, err := os.Stat(configPath); err == nil {
configExists = true
if encrypt {
// Only ask for confirmation when *both* config and SSH key already exist,
// indicating a full re-onboard that would reset the config to defaults.
sshKeyPath, _ := credential.DefaultSSHKeyPath()
@ -36,12 +37,15 @@ func onboard() {
}
// Config exists but SSH key is missing — keep existing config, only add SSH key.
}
}
var err error
if encrypt {
fmt.Println("\nSet up credential encryption")
fmt.Println("-----------------------------")
passphrase, err := promptPassphrase()
if err != nil {
fmt.Printf("Error: %v\n", err)
passphrase, pErr := promptPassphrase()
if pErr != nil {
fmt.Printf("Error: %v\n", pErr)
os.Exit(1)
}
// Expose the passphrase to credential.PassphraseProvider (which calls
@ -54,6 +58,7 @@ func onboard() {
fmt.Printf("Error generating SSH key: %v\n", err)
os.Exit(1)
}
}
var cfg *config.Config
if configExists {
@ -76,11 +81,15 @@ func onboard() {
fmt.Printf("\n%s picoclaw is ready!\n", internal.Logo)
fmt.Println("\nNext steps:")
if encrypt {
fmt.Println(" 1. Set your encryption passphrase before starting picoclaw:")
fmt.Println(" export PICOCLAW_KEY_PASSPHRASE=<your-passphrase> # Linux/macOS")
fmt.Println(" set PICOCLAW_KEY_PASSPHRASE=<your-passphrase> # Windows cmd")
fmt.Println("")
fmt.Println(" 2. Add your API key to", configPath)
} else {
fmt.Println(" 1. Add your API key to", configPath)
}
fmt.Println("")
fmt.Println(" Recommended:")
fmt.Println(" - OpenRouter: https://openrouter.ai/keys (access 100+ models)")