Skip to content
Open
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
22 changes: 19 additions & 3 deletions internal/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ func newConfigShowCmd() *cobra.Command {
io.Printf("%s %s\n", ui.Label("gitHubToken:", w), ui.Dim("(not set)"))
}

io.Printf("%s %v\n", ui.Label("useSSHIdentityFile:", w), rc.UseSSHIdentityFile)

return nil
},
}
Expand All @@ -95,7 +97,7 @@ func newConfigSetCmd() *cobra.Command {
return &cobra.Command{
Use: "set <key> <value>",
Short: "Set a config value",
Long: "Set a config value. Use 'chunk auth set <provider>' to store credentials with validation.\n\nUser keys: model\nProject keys: orgID, validation.sidecarImage",
Long: "Set a config value. Use 'chunk auth set <provider>' to store credentials with validation.\n\nUser keys: model, useSSHIdentityFile\nProject keys: orgID, validation.sidecarImage",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
io := iostream.FromCmd(cmd)
Expand Down Expand Up @@ -131,7 +133,7 @@ func newConfigSetCmd() *cobra.Command {
if !config.ValidConfigKeys[key] {
return &userError{
msg: fmt.Sprintf("Unknown config key: %q.", key),
detail: "Supported keys: model, orgID, validation.sidecarImage.",
detail: "Supported keys: model, useSSHIdentityFile, orgID, validation.sidecarImage.",
errMsg: fmt.Sprintf("unknown config key %q", key),
}
}
Expand All @@ -141,8 +143,22 @@ func newConfigSetCmd() *cobra.Command {
return &userError{msg: msgCouldNotLoadConfig, suggestion: configFilePermHint, err: err}
}

if key == "model" {
switch key {
case "model":
cfg.Model = value
case "useSSHIdentityFile":
switch value {
case "true", "1":
cfg.UseSSHIdentityFile = true
case "false", "0":
cfg.UseSSHIdentityFile = false
default:
return &userError{
msg: fmt.Sprintf("Invalid value %q for useSSHIdentityFile.", value),
detail: "Accepted values: true, false.",
errMsg: fmt.Sprintf("invalid boolean value %q", value),
}
}
}

if err := config.Save(cfg); err != nil {
Expand Down
14 changes: 13 additions & 1 deletion internal/cmd/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,19 @@ func openSSHSession(ctx context.Context, sidecarID, identityFile, workdir string
if err != nil {
return nil, "", err
}
authSock := os.Getenv(config.EnvSSHAuthSock)
if identityFile == "" {
if userCfg, err := config.Load(); err == nil && userCfg.UseSSHIdentityFile {
var keyErr error
identityFile, keyErr = sidecar.DefaultKeyPath()
if keyErr != nil {
streams.ErrPrintf("warning: could not resolve SSH identity file: %v\n", keyErr)
}
}
}
var authSock string
if identityFile == "" {
authSock = os.Getenv(config.EnvSSHAuthSock)
}
session, err := sidecar.OpenSession(ctx, client, sidecarID, identityFile, authSock)
if err != nil {
return nil, "", &userError{msg: "Could not open SSH session to sidecar.", err: err}
Expand Down
14 changes: 9 additions & 5 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,11 @@ func LoadEnv(ctx context.Context) (EnvVars, error) {

// UserConfig is the on-disk JSON config.
type UserConfig struct {
AnthropicAPIKey string `json:"anthropicAPIKey,omitempty"`
CircleCIToken string `json:"circleCIToken,omitempty"`
GitHubToken string `json:"gitHubToken,omitempty"`
Model string `json:"model,omitempty"`
AnthropicAPIKey string `json:"anthropicAPIKey,omitempty"`
CircleCIToken string `json:"circleCIToken,omitempty"`
GitHubToken string `json:"gitHubToken,omitempty"`
Model string `json:"model,omitempty"`
UseSSHIdentityFile bool `json:"useSSHIdentityFile,omitempty"`

// LegacyAPIKey reads the pre-rename "apiKey" field so existing users don't
// silently lose their stored Anthropic key on upgrade. Migrated into
Expand All @@ -125,6 +126,7 @@ type ResolvedConfig struct {
ModelSource string
AnalyzeModel string
PromptModel string
UseSSHIdentityFile bool
}

// Load reads the config file. Returns empty config if not found.
Expand Down Expand Up @@ -257,6 +259,7 @@ func Resolve(flagAPIKey, flagModel string) (ResolvedConfig, error) {
rc.CircleCIBaseURL = env.CircleCIBaseURL
rc.AnthropicBaseURL = env.AnthropicBaseURL
rc.GitHubAPIURL = env.GitHubAPIURL
rc.UseSSHIdentityFile = cfg.UseSSHIdentityFile

return rc, err
}
Expand All @@ -273,7 +276,8 @@ func MaskKey(key string) string {
// Credentials (anthropicAPIKey, circleCIToken) are intentionally excluded —
// users should use "auth set" which validates before storing.
var ValidConfigKeys = map[string]bool{
"model": true,
"model": true,
"useSSHIdentityFile": true,
}

// ValidProjectConfigKeys are the keys accepted by "config set" that write to
Expand Down