# Configuration and bootstrap

## Configuration search order

Manual Invoice loads the first available configuration in this order:

1. `MANUAL_INVOICE_CONFIG`, when set to an explicit file path.
2. The nearest `.manual-invoice.env`, searching from the task working directory upward.
3. `${XDG_CONFIG_HOME:-~/.config}/manual-invoice/config.env`.

Project configuration is appropriate when different workspaces use different credentials or billing projects. User configuration is appropriate when one identity applies across projects.

## Configure command

Before configuration, detect system tools:

```bash
python "$SKILL_DIR/scripts/bootstrap_system_tools.py" --check
```

The detector covers `curl`, `jq`, GitHub CLI, AWS CLI, Google Cloud CLI (`gcloud` + `bq`), and `lark-cli`. It marks `curl` and `jq` as required for nutshell O11Y helpers. GitHub CLI and AWS CLI are optional. Google Cloud CLI is optional because Manual Invoice uses `google-cloud-bigquery` directly. `lark-cli` is detected, but requires manual installation until a portable approved installer is configured.

After the user selects tools, generate an installation plan without making changes:

```bash
python "$SKILL_DIR/scripts/bootstrap_system_tools.py" \
  --plan --tools aws,google-cloud-cli
```

Show every exact command in the returned plan and ask for a second confirmation. Selection is not approval. Only after that confirmation, install the same immutable list:

```bash
python "$SKILL_DIR/scripts/bootstrap_system_tools.py" \
  --yes --tools gh,jq,aws
```

On macOS, the installer uses Homebrew. On supported Linux systems it uses `apt-get`, `dnf`, or `yum` where a package mapping is available. With no package manager or package mapping, it reports manual installation instead of executing an arbitrary download script.

Project scope:

```bash
python "$SKILL_DIR/scripts/configure.py" \
  --scope project \
  --project-root "$PWD" \
  --credentials /absolute/path/to/credentials.json \
  --job-project "" \
  --location "" \
  --non-interactive
```

For interactive configuration, omit `--non-interactive`; the GitHub PAT prompt is hidden. Manual Invoice does not ask for a separate Clinic API key. If `CLINIC_API_KEY` already exists in the process environment or a legacy private config, the installed Clinic Skill reuses it automatically. Do not paste secrets into prompts, logs, or committed files.

Interactive `configure.py` also displays missing installable system tools, accepts one aggregate numbered selection, previews all selected commands, and asks once for final approval. Non-interactive configuration only detects tools by default. To install a reviewed list non-interactively, pass for example `--install-system-tools aws,gh`; use `--skip-system-tools` to omit even the check.

When Codex has already completed the separate check/selection/plan/approval flow, it must invoke `configure.py --skip-system-tools` to avoid asking about the remaining optional tools again.

User scope:

```bash
python "$SKILL_DIR/scripts/configure.py" \
  --scope user \
  --credentials /absolute/path/to/credentials.json \
  --non-interactive
```

Configuration files are written with mode `0600`. Project configuration is added to the local Git exclude file when possible, without modifying the repository's committed `.gitignore`.

The configuration includes `GITHUB_PAT` for O11Y metrics/log authentication. The PAT needs `read:user` and `read:org`. Because `tidbcloud/nutshell-skills` is private, first-time Skill installation also needs repository read access or an existing authorized `gh`/SSH login.

Configure installs nutshell `clinic-api` for Clinic-backed cluster metadata. Clinic itself still requires an internal Access Key and does not accept the GitHub PAT or O11Y tokens. Manual Invoice does not prompt for or require that key: it reuses an already available `CLINIC_API_KEY` when present, otherwise uses the bounded common-region GS scan and asks for provider/region only when the scan cannot find the cluster.

By default, configure installs the five approved observability Skills and performs a redacted AWS-provider authentication check. Use `--skip-o11y-skills` only when configuring BigQuery without O11Y, or `--skip-o11y-auth-check` when installation should proceed while temporarily outside Office/VPN.

## Dependency bootstrap

Dependencies live outside the plugin installation cache:

```text
${MANUAL_INVOICE_CACHE_DIR:-${XDG_CACHE_HOME:-~/.cache}/manual-invoice}/venv
```

Run:

```bash
python "$SKILL_DIR/scripts/bootstrap.py"
```

The bootstrap prefers `uv`, installs Python 3.11 when necessary, installs `requirements.txt`, and uses a requirements hash to avoid unnecessary reinstalls. Its JSON output contains the persistent Python path to use for other scripts.

Check without installing:

```bash
python "$SKILL_DIR/scripts/bootstrap.py" --check
```

## Connection validation

After bootstrap, run:

```bash
"<python-from-bootstrap>" "$SKILL_DIR/scripts/test_bigquery.py"
```

To validate Dataset access and discover Location:

```bash
"<python-from-bootstrap>" "$SKILL_DIR/scripts/test_bigquery.py" \
  --dataset gcp-digital-bi.metadb_new
```

Never store credential JSON contents in configuration. Store only a path, or use ambient ADC.

Validate O11Y installation and authentication:

```bash
"<python-from-bootstrap>" "$SKILL_DIR/scripts/test_o11y.py" --auth --provider aws
```

The command reports only readiness booleans and never prints returned tokens or cloud credentials.
