diff --git a/README.md b/README.md index 327d5d7..dbda8ed 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,13 @@ brew upgrade --cask codex just switch ``` +Sync Bitwarden-backed shell secrets: + +```bash +export BW_SESSION="$(bw unlock --raw)" +just secrets-sync +``` + ## What Still Needs Manual Handling - Secrets and tokens under `~/.secrets`, `~/.npmrc`, `~/.config/gcloud`, `~/.config/gh`, and similar paths diff --git a/docs/architecture.md b/docs/architecture.md deleted file mode 100644 index 9ed1e60..0000000 --- a/docs/architecture.md +++ /dev/null @@ -1,65 +0,0 @@ -# Architecture - -## Goal - -This repo should read like a steady-state machine configuration, not a diary of -whatever was necessary to survive the first migration. - -The structure is intentionally split into three layers: - -- `modules/`: host-wide `nix-darwin` policy -- `home/`: user-facing Home Manager config -- `config/`: raw config payloads consumed by Home Manager - -## Host Layer - -- [modules/base.nix](/Users/rathi/Documents/GitHub/nix/modules/base.nix) owns - baseline Nix settings, shells, and common packages -- [modules/packages.nix](/Users/rathi/Documents/GitHub/nix/modules/packages.nix) - owns the heavier developer tooling and fonts -- [modules/homebrew.nix](/Users/rathi/Documents/GitHub/nix/modules/homebrew.nix) - is the explicitly narrow Brew escape hatch for GUI casks, including Codex - because the Homebrew-distributed app is a better fit here than a source build -- [modules/macos.nix](/Users/rathi/Documents/GitHub/nix/modules/macos.nix) - owns system defaults and macOS-specific integration - -## Home Layer - -- each app/tool gets its own module under `home/` -- raw config trees live under `config/` and are linked by Home Manager -- [home/migration.nix](/Users/rathi/Documents/GitHub/nix/home/migration.nix) - is the only place where takeover logic for old `~/dots` symlinks lives - -That separation matters. Steady-state modules should describe how the machine -works today. Migration-only ownership cleanup belongs in one place and should be -easy to delete later. - -## Package Sources - -Default rule: - -- use `nixpkgs` for stable everyday tooling - -Exceptions: - -- use dedicated flake inputs for fast-moving product CLIs whose release cadence - matters to the machine owner - -Current dedicated inputs: - -- `googleworkspace-cli` -- `claudeCode` - -## Intentional Pragmatism - -Some pieces are still pragmatic compatibility shims rather than ideal upstream -state: - -- [modules/macos.nix](/Users/rathi/Documents/GitHub/nix/modules/macos.nix) - carries a Karabiner launch-agent override because current nix-darwin still - points at the older Karabiner bundle layout -- [home/claude.nix](/Users/rathi/Documents/GitHub/nix/home/claude.nix) manages - `~/.local/bin/claude` so the Nix package cleanly replaces the old manual path - that was already first in shell PATH - -Those are acceptable as long as they are explicit and documented. diff --git a/justfile b/justfile index 72c987a..8f5b2b6 100644 --- a/justfile +++ b/justfile @@ -12,3 +12,6 @@ switch: fmt: nix --extra-experimental-features 'nix-command flakes' fmt + +secrets-sync: + ./scripts/render-bw-shell-secrets.sh diff --git a/scripts/render-bw-shell-secrets.sh b/scripts/render-bw-shell-secrets.sh new file mode 100755 index 0000000..230bdd1 --- /dev/null +++ b/scripts/render-bw-shell-secrets.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +set -euo pipefail + +if ! command -v bw >/dev/null 2>&1; then + echo "bw is not installed" >&2 + exit 1 +fi + +if ! command -v jq >/dev/null 2>&1; then + echo "jq is not installed" >&2 + exit 1 +fi + +if [[ "${BW_SESSION:-}" == "" ]]; then + echo 'BW_SESSION is not set. Run: export BW_SESSION="$(bw unlock --raw)"' >&2 + exit 1 +fi + +out_dir="${HOME}/.config/secrets" +out_file="${out_dir}/shell.zsh" +tmp_file="$(mktemp)" + +mkdir -p "${out_dir}" + +read_note() { + local item_name="$1" + bw get item "${item_name}" --session "${BW_SESSION}" | jq -r '.notes' +} + +extract_env_value() { + local item_name="$1" + local var_name="$2" + read_note "${item_name}" | sed -n "s/^${var_name}=//p" | head -1 +} + +cat > "${tmp_file}" <<'EOF' +# Generated from Bitwarden. Do not edit by hand. +EOF + +append_export_from_note() { + local var_name="$1" + local item_name="$2" + local value + value="$(read_note "${item_name}")" + printf 'export %s=%q\n' "${var_name}" "${value}" >> "${tmp_file}" +} + +append_export_from_env_note() { + local var_name="$1" + local item_name="$2" + local value + value="$(extract_env_value "${item_name}" "${var_name}")" + printf 'export %s=%q\n' "${var_name}" "${value}" >> "${tmp_file}" +} + +append_export_from_note "OPENAI_API_KEY" "Machine: OpenAI API Key" +append_export_from_note "GREPTILE_API_KEY" "Machine: Greptile API Key" +append_export_from_note "CONTEXT7_API_KEY" "Machine: Context7 API Key" +append_export_from_env_note "MISTRAL_API_KEY" "Machine: Vibe Env" + +chmod 600 "${tmp_file}" +mv "${tmp_file}" "${out_file}" + +printf 'Wrote %s\n' "${out_file}"