BroV: single Mac target, chat brain = local claude CLI (stream-json, resume)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -598,6 +598,46 @@ struct SettingsView: View {
|
||||
// MARK: - Chat section
|
||||
|
||||
@ViewBuilder private var chatSection: some View {
|
||||
GroupBox("Claude Code (your subscription, no API key)") {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
HStack {
|
||||
TextField("Folder the chat runs in", text: $state.chatWorkingDirectory)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
Button("Choose…") {
|
||||
let panel = NSOpenPanel()
|
||||
panel.canChooseDirectories = true
|
||||
panel.canChooseFiles = false
|
||||
panel.allowsMultipleSelection = false
|
||||
if panel.runModal() == .OK, let url = panel.url {
|
||||
state.chatWorkingDirectory = url.path
|
||||
ClaudeCodeCLI.shared.newConversation()
|
||||
}
|
||||
}
|
||||
}
|
||||
Picker("Model", selection: $state.claudeCodeModel) {
|
||||
ForEach(ClaudeCodeCLI.models, id: \.id) { m in
|
||||
Text(m.label).tag(m.id)
|
||||
}
|
||||
}
|
||||
Picker("Permissions", selection: $state.claudePermissionMode) {
|
||||
Text("Ask in the notch").tag("default")
|
||||
Text("Accept edits").tag("acceptEdits")
|
||||
Text("Plan only").tag("plan")
|
||||
Text("Bypass (dangerous)").tag("bypassPermissions")
|
||||
}
|
||||
TextField("Path to claude (empty = auto)", text: $state.claudeBinaryPath)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
let found = ClaudeCodeCLI.resolveBinary(custom: state.claudeBinaryPath)
|
||||
Text(found.map { "✓ Using \($0)" } ?? "✗ claude not found — install Claude Code or set the path.")
|
||||
.font(.system(size: 11))
|
||||
.foregroundColor(found == nil ? .red : .secondary)
|
||||
Text("The chat runs `claude -p` in this folder and keeps one conversation until you start a new one. Your MCP servers, skills and CLAUDE.md come along.")
|
||||
.font(.system(size: 11))
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.padding(6)
|
||||
}
|
||||
|
||||
GroupBox("Anthropic API") {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
SecureField("API key (sk-ant-…)", text: $apiKey)
|
||||
@@ -705,7 +745,7 @@ struct SettingsView: View {
|
||||
ollamaURL = ""
|
||||
state.fetchedProviderModels[.ollama] = nil
|
||||
state.providerModelFetchError[.ollama] = nil
|
||||
if state.chatProvider == .ollama { state.chatProvider = .anthropic }
|
||||
if state.chatProvider == .ollama { state.chatProvider = .claudeCode }
|
||||
statusMessage = "Ollama disconnected."
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
@@ -740,7 +780,7 @@ struct SettingsView: View {
|
||||
lmstudioURL = ""
|
||||
state.fetchedProviderModels[.lmstudio] = nil
|
||||
state.providerModelFetchError[.lmstudio] = nil
|
||||
if state.chatProvider == .lmstudio { state.chatProvider = .anthropic }
|
||||
if state.chatProvider == .lmstudio { state.chatProvider = .claudeCode }
|
||||
statusMessage = "LM Studio disconnected."
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
|
||||
Reference in New Issue
Block a user