From 91f8338f49774b95bba6bfe05d151880f07b1103 Mon Sep 17 00:00:00 2001 From: Lucas Alvares Gomes Date: Tue, 21 Jul 2026 19:51:02 +0100 Subject: [PATCH] Embed config defaults at build time Replaces the hardcoded defaultConfig() with a checked-in defaults.json that is embedded into the binary via //go:embed. Updating defaults now requires editing one file instead of keeping config.go and README.md in sync. Signed-off-by: Lucas Alvares Gomes --- AGENTS.md | 7 ++-- README.md | 69 ++------------------------------------ cmd/bwai/config.go | 76 +++++------------------------------------- cmd/bwai/defaults.json | 62 ++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 138 deletions(-) create mode 100644 cmd/bwai/defaults.json diff --git a/AGENTS.md b/AGENTS.md index 911fb26..3b88948 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,7 +9,8 @@ ``` cmd/bwai/ main.go # Entry point, flag parsing, bwrap command construction - config.go # Config struct, defaults, JSON loading (~/.bwai.json) + config.go # Config struct and JSON loading (~/.bwai.json) + defaults.json # Built-in default configuration (embedded into the binary at build time) mounts.go # Filesystem mount logic (home, DNS, GPU, shm) bwrap.go # Low-level bwrap argument helpers (roBind, rwBind, devBind, tmpfs) update.go # Self-update from GitHub releases with SHA-256 verification @@ -74,8 +75,8 @@ bwai --dump-config # Print default config as JSON - **New mount type**: Add a helper function in `mounts.go` following the existing pattern (`[]string` return, appended in `main.go`). - **New CLI flag**: Add to `main.go` using the `flag` package; wire into the bwrap args slice. -- **New config field**: Add to the `Config` struct in `config.go` and update `defaultConfig()`. -- **New agent support**: Add its dotfiles to `home_allow` defaults and its API key to `env_allow` defaults in `config.go`. +- **New config field**: Add to the `Config` struct in `config.go` and add the default value to `defaults.json`. +- **New agent support**: Add its dotfiles to `home_allow` and its API key to `env_allow` in `defaults.json`. ## Testing diff --git a/README.md b/README.md index 64a0012..61f0d8a 100644 --- a/README.md +++ b/README.md @@ -98,78 +98,13 @@ Everything after `--` is passed as extra arguments to the resolved command. bwai --config /path/to/my-config.json ``` -To see the full default configuration as a starting point, run: +To use the full defaults as a starting point, run: ```sh bwai --dump-config > ~/.bwai.json ``` -Example `~/.bwai.json`: - -```json -{ - "bwrap_path": "bwrap", - "bwrap_extra_args": ["--unshare-pid", "--unshare-ipc"], - "command": ["bash"], - "home_allow": [ - ".claude", - ".gemini", - ".claude.json", - ".config/goose", - ".config/gcloud", - ".local/state", - ".local/share/goose", - ".cache", - ".cargo" - ], - "home_block": [ - ".gnupg", - ".ssh", - ".pki", - ".aws", - ".kube", - ".azure", - ".bashrc", - ".bashrc.d", - ".password-store", - ".bash_history*", - ".config/Bitwarden", - ".cache/nvidia" - ], - "env_allow": [ - "TERM", - "COLORTERM", - "LANG", - "LC_ALL", - "LC_MESSAGES", - "LC_CTYPE", - "HOME", - "USER", - "LOGNAME", - "PATH", - "EDITOR", - "ANTHROPIC_API_KEY", - "ANTHROPIC_MODEL", - "ANTHROPIC_DEFAULT_OPUS_MODEL", - "ANTHROPIC_DEFAULT_SONNET_MODEL", - "ANTHROPIC_DEFAULT_HAIKU_MODEL", - "CLAUDE_CODE_USE_VERTEX", - "CLOUD_ML_REGION", - "ANTHROPIC_VERTEX_PROJECT_ID", - "GEMINI_API_KEY", - "GOOGLE_API_KEY", - "GCLOUD_PROJECT", - "GOOGLE_CLOUD_PROJECT", - "GOOSE_PROVIDER", - "GOOSE_MODEL", - "GOOSE_PLANNER_PROVIDER", - "GOOSE_PLANNER_MODEL", - "OPENAI_API_KEY", - "OPENAI_API_BASE", - "OPENROUTER_API_KEY", - ] -} -``` +The built-in defaults are also available at [`cmd/bwai/defaults.json`](cmd/bwai/defaults.json). | Field | Description | Default | |---|---|---| diff --git a/cmd/bwai/config.go b/cmd/bwai/config.go index 38ca9f6..ea5168b 100644 --- a/cmd/bwai/config.go +++ b/cmd/bwai/config.go @@ -1,10 +1,14 @@ package main import ( + _ "embed" "encoding/json" "os" ) +//go:embed defaults.json +var defaultConfigJSON []byte + type Config struct { // Path to the bwrap binary. Defaults to "bwrap" BwrapPath string `json:"bwrap_path"` @@ -26,75 +30,11 @@ type Config struct { } func defaultConfig() Config { - return Config{ - BwrapPath: "bwrap", - BwrapExtraArgs: []string{"--unshare-pid", "--unshare-ipc"}, - Command: []string{"bash"}, - EnvAllow: []string{ - "TERM", - "COLORTERM", - "LANG", - "LC_ALL", - "LC_MESSAGES", - "LC_CTYPE", - "HOME", - "USER", - "LOGNAME", - "PATH", - "EDITOR", - // Claude - "ANTHROPIC_API_KEY", - // Claude model selection / pinning - "ANTHROPIC_MODEL", - "ANTHROPIC_DEFAULT_OPUS_MODEL", - "ANTHROPIC_DEFAULT_SONNET_MODEL", - "ANTHROPIC_DEFAULT_HAIKU_MODEL", - // Claude Code on Google Vertex AI - "CLAUDE_CODE_USE_VERTEX", - "CLOUD_ML_REGION", - "ANTHROPIC_VERTEX_PROJECT_ID", - // Gemini / Google - "GEMINI_API_KEY", - "GOOGLE_API_KEY", - "GCLOUD_PROJECT", - "GOOGLE_CLOUD_PROJECT", - // Goose (uses provider keys above + its own config) - "GOOSE_PROVIDER", - "GOOSE_MODEL", - "GOOSE_PLANNER_PROVIDER", - "GOOSE_PLANNER_MODEL", - // OpenAI-compatible providers (used by Goose and others) - "OPENAI_API_KEY", - "OPENAI_API_BASE", - // OpenRouter - "OPENROUTER_API_KEY", - }, - HomeAllow: []string{ - ".claude", - ".gemini", - ".claude.json", - ".config/goose", - ".config/gcloud", - ".local/state", - ".local/share/goose", - ".cache", - ".cargo", - }, - HomeBlock: []string{ - ".gnupg", - ".ssh", - ".pki", - ".aws", - ".kube", - ".azure", - ".bashrc", - ".bashrc.d", - ".password-store", - ".bash_history*", - ".config/Bitwarden", - ".cache/nvidia", - }, + var cfg Config + if err := json.Unmarshal(defaultConfigJSON, &cfg); err != nil { + panic("bwai: invalid defaults.json: " + err.Error()) } + return cfg } // loadConfig reads the config file at the given path if it exists and returns the resulting Config. diff --git a/cmd/bwai/defaults.json b/cmd/bwai/defaults.json new file mode 100644 index 0000000..553bf63 --- /dev/null +++ b/cmd/bwai/defaults.json @@ -0,0 +1,62 @@ +{ + "bwrap_path": "bwrap", + "bwrap_extra_args": ["--unshare-pid", "--unshare-ipc"], + "command": ["bash"], + "home_allow": [ + ".claude", + ".gemini", + ".claude.json", + ".config/goose", + ".config/gcloud", + ".local/state", + ".local/share/goose", + ".cache", + ".cargo" + ], + "home_block": [ + ".gnupg", + ".ssh", + ".pki", + ".aws", + ".kube", + ".azure", + ".bashrc", + ".bashrc.d", + ".password-store", + ".bash_history*", + ".config/Bitwarden", + ".cache/nvidia" + ], + "env_allow": [ + "TERM", + "COLORTERM", + "LANG", + "LC_ALL", + "LC_MESSAGES", + "LC_CTYPE", + "HOME", + "USER", + "LOGNAME", + "PATH", + "EDITOR", + "ANTHROPIC_API_KEY", + "ANTHROPIC_MODEL", + "ANTHROPIC_DEFAULT_OPUS_MODEL", + "ANTHROPIC_DEFAULT_SONNET_MODEL", + "ANTHROPIC_DEFAULT_HAIKU_MODEL", + "CLAUDE_CODE_USE_VERTEX", + "CLOUD_ML_REGION", + "ANTHROPIC_VERTEX_PROJECT_ID", + "GEMINI_API_KEY", + "GOOGLE_API_KEY", + "GCLOUD_PROJECT", + "GOOGLE_CLOUD_PROJECT", + "GOOSE_PROVIDER", + "GOOSE_MODEL", + "GOOSE_PLANNER_PROVIDER", + "GOOSE_PLANNER_MODEL", + "OPENAI_API_KEY", + "OPENAI_API_BASE", + "OPENROUTER_API_KEY" + ] +}