diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 4cbf818..3c92356 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -30,6 +30,7 @@ This is the **Claude on Foundry Starter Kit** ([`Azure-Samples/claude`](https:// | `CLAUDE_MODEL_NAME` | no | `claude-sonnet-4-6` | **Legacy** single-deployment fallback (only used when all three `CLAUDE_*_MODEL` are empty) | | `ASSIGN_RBAC` | no | `false` | `true` grants Foundry User + Foundry Project Manager to `AZURE_PRINCIPAL_ID` | | `CLAUDE_CODE_AUTO_INSTALL` | no | `false` | `true` installs the Claude Code CLI in the postprovision hook | +| `CLAUDE_SKIP_VSCODE_SETTINGS` | no | `false` | `true` skips the `.vscode/settings.json` write in the postprovision hook (use when you don't have the Claude Code VS Code extension) | Always set vars with `azd env set ` from inside the chosen variant folder. diff --git a/README.md b/README.md index eddfda3..6e976e7 100644 --- a/README.md +++ b/README.md @@ -236,7 +236,7 @@ After `azd up` succeeds, the **postprovision** hook ([`scripts/configure-claude- - `ANTHROPIC_FOUNDRY_RESOURCE=` - One `ANTHROPIC_DEFAULT__MODEL=` per deployed family (`HAIKU` / `SONNET` / `OPUS`). Only the families you actually deployed get a line. - **`AZURE_CONFIG_DIR=/.azure-cli`** — scopes `az login` (and `azd`) to this workspace only. See [Workspace-scoped `az login`](#workspace-scoped-az-login) below. -2. Writes (or merges into) `.vscode/settings.json` with `claudeCode.environmentVariables` (the array-of-`{name,value}` schema the extension actually reads — the display name in the Settings UI is *"Claude Code: Environment Variables"*) and `claudeCode.disableLoginPrompt: true` so the [Claude Code VS Code extension](https://marketplace.visualstudio.com/items?itemName=anthropic.claude-code) skips the Anthropic-account login and uses your Foundry deployment via Entra ID. It also sets `terminal.integrated.env.{windows,linux,osx}.AZURE_CONFIG_DIR` so every terminal VS Code spawns in this workspace inherits the scoped Azure config automatically — you don't even have to source the activator first. +2. Writes (or merges into) `.vscode/settings.json` with `claudeCode.environmentVariables` (the array-of-`{name,value}` schema the extension actually reads — the display name in the Settings UI is *"Claude Code: Environment Variables"*) and `claudeCode.disableLoginPrompt: true` so the [Claude Code VS Code extension](https://marketplace.visualstudio.com/items?itemName=anthropic.claude-code) skips the Anthropic-account login and uses your Foundry deployment via Entra ID. It also sets `terminal.integrated.env.{windows,linux,osx}.AZURE_CONFIG_DIR` so every terminal VS Code spawns in this workspace inherits the scoped Azure config automatically — you don't even have to source the activator first. **Not using the Claude Code extension?** Opt out before `azd up` with `azd env set CLAUDE_SKIP_VSCODE_SETTINGS 1` (or pass `-SkipVsCodeSettings` / `--skip-vscode-settings` when running the script standalone) and the hook leaves `.vscode/settings.json` alone. The activator at step 1 still works for sourced shells. 3. Writes (or merges into) `.claude/settings.json` at the repo root with `{ "model": "" }` pinned to a deployed family (sonnet > opus > haiku priority). This is the **workspace-level** Claude Code config and overrides whatever is in your user-global `~/.claude/settings.json` — so bare `claude` / `claude -p` resolves to a family you actually deployed, even if your global default points elsewhere. 4. Checks whether `claude` is on PATH. If not, prints the platform-appropriate one-liner install command. Set `CLAUDE_CODE_AUTO_INSTALL=true` *before* `azd up` to run [the official installer](https://claude.ai/install.ps1) automatically. diff --git a/scripts/configure-claude-code.ps1 b/scripts/configure-claude-code.ps1 index 02c7604..80de74d 100644 --- a/scripts/configure-claude-code.ps1 +++ b/scripts/configure-claude-code.ps1 @@ -38,6 +38,16 @@ param( $ErrorActionPreference = 'Stop' +# Env-var opt-out so the postprovision hook can honor it without having to +# pass -SkipVsCodeSettings on the command line: +# azd env set CLAUDE_SKIP_VSCODE_SETTINGS 1 +if (-not $SkipVsCodeSettings) { + $skipEnv = $env:CLAUDE_SKIP_VSCODE_SETTINGS + if ($skipEnv -and $skipEnv -match '^(1|true|yes|on)$') { + $SkipVsCodeSettings = $true + } +} + function Fail([int]$code, [string]$message) { Write-Host "" Write-Host "ERROR: $message" -ForegroundColor Red @@ -177,7 +187,9 @@ Write-Host "Wrote activator: $shPath" # --------------------------------------------------------------------------- # 2. Write / merge `.vscode/settings.json` for the Claude Code VS Code extension. # --------------------------------------------------------------------------- -if (-not $SkipVsCodeSettings) { +if ($SkipVsCodeSettings) { + Write-Host "Skipping .vscode/settings.json (CLAUDE_SKIP_VSCODE_SETTINGS / -SkipVsCodeSettings set). The activator above still wires up sourced shells." +} else { $vscodeDir = Join-Path $RepoRoot '.vscode' $settingsPath = Join-Path $vscodeDir 'settings.json' if (-not (Test-Path $vscodeDir)) { diff --git a/scripts/configure-claude-code.sh b/scripts/configure-claude-code.sh index ab58c11..ab697d3 100644 --- a/scripts/configure-claude-code.sh +++ b/scripts/configure-claude-code.sh @@ -26,7 +26,15 @@ fail() { SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="${REPO_ROOT:-$(cd "$SCRIPT_DIR/.." && pwd)}" -SKIP_VSCODE_SETTINGS="${SKIP_VSCODE_SETTINGS:-0}" + +# Skip flag from env. Prefer the CLAUDE_-namespaced name (matches the rest of +# the env-var contract); keep the un-prefixed name as a deprecated alias. +# Set via: azd env set CLAUDE_SKIP_VSCODE_SETTINGS 1 +SKIP_VSCODE_SETTINGS="${CLAUDE_SKIP_VSCODE_SETTINGS:-${SKIP_VSCODE_SETTINGS:-0}}" +case "$SKIP_VSCODE_SETTINGS" in + 1|true|TRUE|yes|YES|on|ON) SKIP_VSCODE_SETTINGS=1 ;; + *) SKIP_VSCODE_SETTINGS=0 ;; +esac while [[ $# -gt 0 ]]; do case "$1" in @@ -153,7 +161,9 @@ for cand in python python3; do if command -v "$cand" >/dev/null 2>&1; then PYTHON_BIN="$cand"; break; fi done -if [ "${SKIP_VSCODE_SETTINGS:-}" != "1" ] && [ -n "$PYTHON_BIN" ]; then +if [ "${SKIP_VSCODE_SETTINGS:-}" = "1" ]; then + echo "Skipping .vscode/settings.json (CLAUDE_SKIP_VSCODE_SETTINGS / --skip-vscode-settings set). The activator above still wires up sourced shells." +elif [ -n "$PYTHON_BIN" ]; then VSCODE_DIR="$REPO_ROOT/.vscode" mkdir -p "$VSCODE_DIR" SETTINGS_PATH="$VSCODE_DIR/settings.json" diff --git a/skills/claude-on-foundry/SKILL.md b/skills/claude-on-foundry/SKILL.md index a5b09ca..9b32a17 100644 --- a/skills/claude-on-foundry/SKILL.md +++ b/skills/claude-on-foundry/SKILL.md @@ -170,6 +170,7 @@ claude # interactive REPL; try /status and /mode | **Switch region** | `azd env new ` in the same variant folder, then redo the [DEPLOY](#deploy--running-azd-up) flow. **Don't** try to mutate `AZURE_LOCATION` on an existing env — the account is region-stamped. | | **Switch variants (Bicep ↔ Terraform)** | They produce equivalent infra but with different `azd` env state. Create a new env in the other folder: `cd infra-terraform && azd env new && ...`. | | **Refresh Claude Code wiring** | `pwsh -File scripts/configure-claude-code.ps1` (or the `.sh` variant). Idempotent — runs without re-deploying. | +| **Skip the `.vscode/settings.json` write** | `azd env set CLAUDE_SKIP_VSCODE_SETTINGS 1` (then re-run `azd provision` or the configure script). For customers who don't use the Claude Code VS Code extension and don't want workspace settings touched. The activator at the repo root still wires up sourced shells. | | **Convert to long-running auth** | Replace `Anthropic(auth_token=...)` with `AnthropicIdentity(azure_ad_token_provider=...)` from [`src/hello_claude_token_refresh.py`](../../src/hello_claude_token_refresh.py). | ---