feat(claude-code): add managed_settings input for policy delivery via /etc/claude-code (#863)
## Problem
The module configures Claude Code's permission posture by reaching
around the permission system rather than through it:
- `scripts/install.sh` writes `bypassPermissionsModeAccepted`,
`autoModeAccepted`, and `primaryApiKey` directly into the user-writable
`~/.claude.json`. Any process in the workspace can read the API key or
flip the acceptance flags back.
- `scripts/start.sh` adds `--dangerously-skip-permissions` to every task
launch, even when the template author set an explicit `permission_mode`.
The README has to carry a security warning telling people the module
bypasses permission checks.
- `permission_mode`, `allowed_tools`, and `disallowed_tools` each plumb
through a different ad-hoc path (CLI flag, `coder` subcommand) instead
of a single policy surface.
## Change
Add a `managed_settings` input that renders to
`/etc/claude-code/managed-settings.d/10-coder.json`. Claude Code reads
that drop-in directory at startup with the highest configuration
precedence (above `~/.claude/settings.json` and project settings), so
template authors get an admin-controlled policy file that users inside
the workspace cannot override. The mechanism is a local file read with
no API call, so it works identically for the Anthropic API, AWS Bedrock,
Google Vertex AI, and AI Bridge / AI Gateway.
```hcl
managed_settings = {
permissions = {
defaultMode = "acceptEdits"
disableBypassPermissionsMode = "disable"
deny = ["Bash(curl:*)", "WebFetch"]
}
}
```
Supporting changes:
- `install.sh` writes the policy file (root-owned, 0644) and stops
writing `bypassPermissionsModeAccepted`, `autoModeAccepted`, and
`primaryApiKey` into `~/.claude.json`. The API key is already exported
via `coder_env` as `CLAUDE_API_KEY`; duplicating it on disk is
unnecessary. `hasCompletedOnboarding` stays because there is no env-var
alternative for it.
- `start.sh` only adds `--dangerously-skip-permissions` for tasks when
no explicit `permission_mode` is set (same fix as #846; included here so
this PR is self-contained, happy to drop if #846 lands first).
- `permission_mode`, `allowed_tools`, and `disallowed_tools` are marked
deprecated and shimmed into `managed_settings.permissions` for one
release when `managed_settings` is not provided.
- README security warning rewritten to point at the policy mechanism
instead of telling people the module is unsafe by design.
## Relationship to #861
#861 strips this module to install-and-configure and removes
`permission_mode` / `allowed_tools` / `disallowed_tools` outright.
`managed_settings` is the natural replacement for those: it is
install-time (survives the `start.sh` removal), it covers everything the
dropped variables did plus `hooks`, `env`, `model`, `apiKeyHelper`, and
the rest of the settings schema, and it does not require the module to
know anything about how Claude is launched. If #861 lands first I will
rebase this on top and drop the deprecation shim and the `start.sh`
hunk.
## Validation
- `terraform fmt` / `terraform validate` clean
- New tests: `claude-managed-settings-written`,
`claude-managed-settings-legacy-shim`,
`claude-no-policy-keys-in-claudejson`, plus an assertion in
`claude-auto-permission-mode` that `--dangerously-skip-permissions` is
absent when a mode is set
- Manually verified `/etc/claude-code/managed-settings.d/*.json`
precedence in the Claude Code CLI source
Closes #818. Relates to #284, #846, #861.
Disclosure: I work at Anthropic on the Claude Code team. Happy to adjust
scope or split this further if that is easier to review.
---------
Co-authored-by: DevCats <chris@dualriver.com>
Co-authored-by: DevCats <christofer@coder.com>
This commit is contained in:
parent
99510a1f75
commit
ac6329e77c
@ -13,7 +13,7 @@ Install and configure the [Claude Code](https://docs.anthropic.com/en/docs/agent
|
|||||||
```tf
|
```tf
|
||||||
module "claude-code" {
|
module "claude-code" {
|
||||||
source = "registry.coder.com/coder/claude-code/coder"
|
source = "registry.coder.com/coder/claude-code/coder"
|
||||||
version = "5.1.0"
|
version = "5.2.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
anthropic_api_key = "xxxx-xxxxx-xxxx"
|
anthropic_api_key = "xxxx-xxxxx-xxxx"
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ locals {
|
|||||||
|
|
||||||
module "claude-code" {
|
module "claude-code" {
|
||||||
source = "registry.coder.com/coder/claude-code/coder"
|
source = "registry.coder.com/coder/claude-code/coder"
|
||||||
version = "5.1.0"
|
version = "5.2.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
workdir = local.claude_workdir
|
workdir = local.claude_workdir
|
||||||
anthropic_api_key = "xxxx-xxxxx-xxxx"
|
anthropic_api_key = "xxxx-xxxxx-xxxx"
|
||||||
@ -78,7 +78,7 @@ resource "coder_app" "claude" {
|
|||||||
```tf
|
```tf
|
||||||
module "claude-code" {
|
module "claude-code" {
|
||||||
source = "registry.coder.com/coder/claude-code/coder"
|
source = "registry.coder.com/coder/claude-code/coder"
|
||||||
version = "5.1.0"
|
version = "5.2.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
workdir = "/home/coder/project"
|
workdir = "/home/coder/project"
|
||||||
enable_ai_gateway = true
|
enable_ai_gateway = true
|
||||||
@ -95,6 +95,33 @@ Claude Code then routes API requests through Coder's AI Gateway instead of direc
|
|||||||
> [!CAUTION]
|
> [!CAUTION]
|
||||||
> `enable_ai_gateway = true` is mutually exclusive with `anthropic_api_key` and `claude_code_oauth_token`. Setting any of them together fails at plan time.
|
> `enable_ai_gateway = true` is mutually exclusive with `anthropic_api_key` and `claude_code_oauth_token`. Setting any of them together fails at plan time.
|
||||||
|
|
||||||
|
### Enterprise policy via managed settings
|
||||||
|
|
||||||
|
The `managed_settings` input writes a policy file to `/etc/claude-code/managed-settings.d/10-coder.json` inside the workspace. Claude Code reads this directory at startup with the highest configuration precedence, so users cannot override these values in their own `~/.claude/settings.json`. This is a local file mechanism and works with any inference backend (Anthropic API, AWS Bedrock, Google Vertex AI, or AI Gateway).
|
||||||
|
|
||||||
|
```tf
|
||||||
|
module "claude-code" {
|
||||||
|
source = "registry.coder.com/coder/claude-code/coder"
|
||||||
|
version = "5.2.0"
|
||||||
|
agent_id = coder_agent.main.id
|
||||||
|
workdir = "/home/coder/project"
|
||||||
|
anthropic_api_key = "xxxx-xxxxx-xxxx"
|
||||||
|
|
||||||
|
managed_settings = {
|
||||||
|
permissions = {
|
||||||
|
defaultMode = "acceptEdits"
|
||||||
|
disableBypassPermissionsMode = "disable"
|
||||||
|
deny = ["Bash(curl:*)", "Bash(wget:*)", "WebFetch"]
|
||||||
|
}
|
||||||
|
env = {
|
||||||
|
DISABLE_TELEMETRY = "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [Claude Code settings reference](https://docs.anthropic.com/en/docs/claude-code/settings) for the full schema. Common keys: `permissions` (`defaultMode`, `allow`, `deny`, `disableBypassPermissionsMode`, `additionalDirectories`), `env`, `model`, `apiKeyHelper`, `hooks`, `cleanupPeriodDays`.
|
||||||
|
|
||||||
### Advanced Configuration
|
### Advanced Configuration
|
||||||
|
|
||||||
This example shows version pinning, a pre-installed binary path, a custom model, and MCP servers.
|
This example shows version pinning, a pre-installed binary path, a custom model, and MCP servers.
|
||||||
@ -102,7 +129,7 @@ This example shows version pinning, a pre-installed binary path, a custom model,
|
|||||||
```tf
|
```tf
|
||||||
module "claude-code" {
|
module "claude-code" {
|
||||||
source = "registry.coder.com/coder/claude-code/coder"
|
source = "registry.coder.com/coder/claude-code/coder"
|
||||||
version = "5.1.0"
|
version = "5.2.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
workdir = "/home/coder/project"
|
workdir = "/home/coder/project"
|
||||||
|
|
||||||
@ -166,7 +193,7 @@ Downstream `coder_script` resources can wait for this module's install pipeline
|
|||||||
```tf
|
```tf
|
||||||
module "claude-code" {
|
module "claude-code" {
|
||||||
source = "registry.coder.com/coder/claude-code/coder"
|
source = "registry.coder.com/coder/claude-code/coder"
|
||||||
version = "5.1.0"
|
version = "5.2.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
workdir = "/home/coder/project"
|
workdir = "/home/coder/project"
|
||||||
anthropic_api_key = "xxxx-xxxxx-xxxx"
|
anthropic_api_key = "xxxx-xxxxx-xxxx"
|
||||||
@ -252,7 +279,7 @@ resource "coder_env" "bedrock_api_key" {
|
|||||||
|
|
||||||
module "claude-code" {
|
module "claude-code" {
|
||||||
source = "registry.coder.com/coder/claude-code/coder"
|
source = "registry.coder.com/coder/claude-code/coder"
|
||||||
version = "5.1.0"
|
version = "5.2.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
workdir = "/home/coder/project"
|
workdir = "/home/coder/project"
|
||||||
model = "global.anthropic.claude-sonnet-4-5-20250929-v1:0"
|
model = "global.anthropic.claude-sonnet-4-5-20250929-v1:0"
|
||||||
@ -309,7 +336,7 @@ resource "coder_env" "google_application_credentials" {
|
|||||||
|
|
||||||
module "claude-code" {
|
module "claude-code" {
|
||||||
source = "registry.coder.com/coder/claude-code/coder"
|
source = "registry.coder.com/coder/claude-code/coder"
|
||||||
version = "5.1.0"
|
version = "5.2.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
workdir = "/home/coder/project"
|
workdir = "/home/coder/project"
|
||||||
model = "claude-sonnet-4@20250514"
|
model = "claude-sonnet-4@20250514"
|
||||||
@ -350,7 +377,7 @@ The module automatically tags every span and metric with `coder.workspace_id`, `
|
|||||||
```tf
|
```tf
|
||||||
module "claude-code" {
|
module "claude-code" {
|
||||||
source = "registry.coder.com/coder/claude-code/coder"
|
source = "registry.coder.com/coder/claude-code/coder"
|
||||||
version = "5.1.0"
|
version = "5.2.0"
|
||||||
agent_id = coder_agent.main.id
|
agent_id = coder_agent.main.id
|
||||||
workdir = "/home/coder/project"
|
workdir = "/home/coder/project"
|
||||||
anthropic_api_key = "xxxx-xxxxx-xxxx"
|
anthropic_api_key = "xxxx-xxxxx-xxxx"
|
||||||
|
|||||||
@ -382,10 +382,13 @@ describe("claude-code", async () => {
|
|||||||
const parsed = JSON.parse(claudeConfig);
|
const parsed = JSON.parse(claudeConfig);
|
||||||
expect(parsed.autoUpdaterStatus).toBe("disabled");
|
expect(parsed.autoUpdaterStatus).toBe("disabled");
|
||||||
expect(parsed.hasCompletedOnboarding).toBe(true);
|
expect(parsed.hasCompletedOnboarding).toBe(true);
|
||||||
expect(parsed.bypassPermissionsModeAccepted).toBe(true);
|
|
||||||
expect(parsed.hasAcknowledgedCostThreshold).toBe(true);
|
expect(parsed.hasAcknowledgedCostThreshold).toBe(true);
|
||||||
expect(parsed.projects[workdir].hasCompletedProjectOnboarding).toBe(true);
|
expect(parsed.projects[workdir].hasCompletedProjectOnboarding).toBe(true);
|
||||||
expect(parsed.projects[workdir].hasTrustDialogAccepted).toBe(true);
|
expect(parsed.projects[workdir].hasTrustDialogAccepted).toBe(true);
|
||||||
|
// Permission posture is delivered via /etc/claude-code/managed-settings.d/,
|
||||||
|
// not user-writable ~/.claude.json acceptance flags.
|
||||||
|
expect(parsed.bypassPermissionsModeAccepted).toBeUndefined();
|
||||||
|
expect(parsed.autoModeAccepted).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("standalone-mode-with-oauth-token", async () => {
|
test("standalone-mode-with-oauth-token", async () => {
|
||||||
@ -413,7 +416,7 @@ describe("claude-code", async () => {
|
|||||||
);
|
);
|
||||||
const parsed = JSON.parse(claudeConfig);
|
const parsed = JSON.parse(claudeConfig);
|
||||||
expect(parsed.hasCompletedOnboarding).toBe(true);
|
expect(parsed.hasCompletedOnboarding).toBe(true);
|
||||||
expect(parsed.bypassPermissionsModeAccepted).toBe(true);
|
expect(parsed.bypassPermissionsModeAccepted).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("standalone-mode-no-auth", async () => {
|
test("standalone-mode-no-auth", async () => {
|
||||||
@ -436,6 +439,49 @@ describe("claude-code", async () => {
|
|||||||
expect(resp.stdout.trim()).toBe("ABSENT");
|
expect(resp.stdout.trim()).toBe("ABSENT");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("claude-managed-settings-written", async () => {
|
||||||
|
const { id, scripts } = await setup({
|
||||||
|
moduleVariables: {
|
||||||
|
managed_settings: JSON.stringify({
|
||||||
|
permissions: {
|
||||||
|
defaultMode: "acceptEdits",
|
||||||
|
disableBypassPermissionsMode: "disable",
|
||||||
|
deny: ["Bash(rm -rf*)"],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await runScripts(id, scripts);
|
||||||
|
|
||||||
|
const policy = await execContainer(id, [
|
||||||
|
"bash",
|
||||||
|
"-c",
|
||||||
|
"cat /etc/claude-code/managed-settings.d/10-coder.json",
|
||||||
|
]);
|
||||||
|
expect(policy.exitCode).toBe(0);
|
||||||
|
expect(policy.stdout).toContain('"defaultMode":"acceptEdits"');
|
||||||
|
expect(policy.stdout).toContain('"disableBypassPermissionsMode":"disable"');
|
||||||
|
expect(policy.stdout).toContain('"deny":["Bash(rm -rf*)"]');
|
||||||
|
|
||||||
|
const installLog = await readFileContainer(
|
||||||
|
id,
|
||||||
|
"/home/coder/.coder-modules/coder/claude-code/logs/install.log",
|
||||||
|
);
|
||||||
|
expect(installLog).toContain("Wrote Claude Code managed settings");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("claude-managed-settings-not-set", async () => {
|
||||||
|
const { id, scripts } = await setup();
|
||||||
|
await runScripts(id, scripts);
|
||||||
|
|
||||||
|
const resp = await execContainer(id, [
|
||||||
|
"bash",
|
||||||
|
"-c",
|
||||||
|
"test -e /etc/claude-code/managed-settings.d/10-coder.json && echo EXISTS || echo ABSENT",
|
||||||
|
]);
|
||||||
|
expect(resp.stdout.trim()).toBe("ABSENT");
|
||||||
|
});
|
||||||
|
|
||||||
test("telemetry-otel", async () => {
|
test("telemetry-otel", async () => {
|
||||||
const { coderEnvVars } = await setup({
|
const { coderEnvVars } = await setup({
|
||||||
moduleVariables: {
|
moduleVariables: {
|
||||||
|
|||||||
@ -102,6 +102,12 @@ variable "claude_binary_path" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "managed_settings" {
|
||||||
|
type = any
|
||||||
|
description = "Policy settings written to /etc/claude-code/managed-settings.d/10-coder.json. Highest-precedence client config; works with any inference backend (Anthropic API, Bedrock, Vertex, AI Gateway). See https://docs.anthropic.com/en/docs/claude-code/settings for the schema."
|
||||||
|
default = null
|
||||||
|
}
|
||||||
|
|
||||||
variable "enable_ai_gateway" {
|
variable "enable_ai_gateway" {
|
||||||
type = bool
|
type = bool
|
||||||
description = "Use AI Gateway for Claude Code. https://coder.com/docs/ai-coder/ai-gateway"
|
description = "Use AI Gateway for Claude Code. https://coder.com/docs/ai-coder/ai-gateway"
|
||||||
@ -237,6 +243,7 @@ locals {
|
|||||||
ARG_MCP = var.mcp != "" ? base64encode(var.mcp) : ""
|
ARG_MCP = var.mcp != "" ? base64encode(var.mcp) : ""
|
||||||
ARG_MCP_CONFIG_REMOTE_PATH = base64encode(jsonencode(var.mcp_config_remote_path))
|
ARG_MCP_CONFIG_REMOTE_PATH = base64encode(jsonencode(var.mcp_config_remote_path))
|
||||||
ARG_ENABLE_AI_GATEWAY = tostring(var.enable_ai_gateway)
|
ARG_ENABLE_AI_GATEWAY = tostring(var.enable_ai_gateway)
|
||||||
|
ARG_MANAGED_SETTINGS_JSON = var.managed_settings != null ? base64encode(jsonencode(var.managed_settings)) : ""
|
||||||
})
|
})
|
||||||
module_dir_name = ".coder-modules/coder/claude-code"
|
module_dir_name = ".coder-modules/coder/claude-code"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -283,3 +283,47 @@ run "test_workdir_optional" {
|
|||||||
error_message = "workdir should default to null when omitted"
|
error_message = "workdir should default to null when omitted"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
run "test_managed_settings" {
|
||||||
|
command = plan
|
||||||
|
|
||||||
|
variables {
|
||||||
|
agent_id = "test-agent-managed-settings"
|
||||||
|
workdir = "/home/coder/project"
|
||||||
|
managed_settings = {
|
||||||
|
permissions = {
|
||||||
|
defaultMode = "acceptEdits"
|
||||||
|
disableBypassPermissionsMode = "disable"
|
||||||
|
deny = ["Bash(rm -rf*)"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {
|
||||||
|
condition = var.managed_settings.permissions.defaultMode == "acceptEdits"
|
||||||
|
error_message = "managed_settings should accept the permissions object"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {
|
||||||
|
condition = strcontains(local.install_script, "/etc/claude-code/managed-settings.d")
|
||||||
|
error_message = "install script should reference the managed-settings.d drop-in directory"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {
|
||||||
|
condition = strcontains(local.install_script, base64encode(jsonencode(var.managed_settings)))
|
||||||
|
error_message = "install script should embed the base64-encoded managed_settings JSON"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run "test_managed_settings_default_null" {
|
||||||
|
command = plan
|
||||||
|
|
||||||
|
variables {
|
||||||
|
agent_id = "test-agent-managed-settings-default"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {
|
||||||
|
condition = var.managed_settings == null
|
||||||
|
error_message = "managed_settings should default to null when omitted"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ ARG_CLAUDE_BINARY_PATH="$${ARG_CLAUDE_BINARY_PATH//\$HOME/$HOME}"
|
|||||||
ARG_MCP=$(echo -n '${ARG_MCP}' | base64 -d)
|
ARG_MCP=$(echo -n '${ARG_MCP}' | base64 -d)
|
||||||
ARG_MCP_CONFIG_REMOTE_PATH=$(echo -n '${ARG_MCP_CONFIG_REMOTE_PATH}' | base64 -d)
|
ARG_MCP_CONFIG_REMOTE_PATH=$(echo -n '${ARG_MCP_CONFIG_REMOTE_PATH}' | base64 -d)
|
||||||
ARG_ENABLE_AI_GATEWAY='${ARG_ENABLE_AI_GATEWAY}'
|
ARG_ENABLE_AI_GATEWAY='${ARG_ENABLE_AI_GATEWAY}'
|
||||||
|
ARG_MANAGED_SETTINGS_JSON=$(echo -n '${ARG_MANAGED_SETTINGS_JSON}' | base64 -d)
|
||||||
|
|
||||||
export PATH="$${ARG_CLAUDE_BINARY_PATH}:$PATH"
|
export PATH="$${ARG_CLAUDE_BINARY_PATH}:$PATH"
|
||||||
|
|
||||||
@ -29,6 +30,7 @@ printf "ARG_CLAUDE_BINARY_PATH: %s\n" "$${ARG_CLAUDE_BINARY_PATH}"
|
|||||||
printf "ARG_MCP: %s\n" "$${ARG_MCP}"
|
printf "ARG_MCP: %s\n" "$${ARG_MCP}"
|
||||||
printf "ARG_MCP_CONFIG_REMOTE_PATH: %s\n" "$${ARG_MCP_CONFIG_REMOTE_PATH}"
|
printf "ARG_MCP_CONFIG_REMOTE_PATH: %s\n" "$${ARG_MCP_CONFIG_REMOTE_PATH}"
|
||||||
printf "ARG_ENABLE_AI_GATEWAY: %s\n" "$${ARG_ENABLE_AI_GATEWAY}"
|
printf "ARG_ENABLE_AI_GATEWAY: %s\n" "$${ARG_ENABLE_AI_GATEWAY}"
|
||||||
|
printf "ARG_MANAGED_SETTINGS_JSON: %s\n" "$${ARG_MANAGED_SETTINGS_JSON}"
|
||||||
|
|
||||||
echo "--------------------------------"
|
echo "--------------------------------"
|
||||||
|
|
||||||
@ -144,6 +146,32 @@ function setup_claude_configurations() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function write_managed_settings() {
|
||||||
|
if [ -z "$${ARG_MANAGED_SETTINGS_JSON}" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local dropin_dir="/etc/claude-code/managed-settings.d"
|
||||||
|
local target="$${dropin_dir}/10-coder.json"
|
||||||
|
|
||||||
|
if ! echo "$${ARG_MANAGED_SETTINGS_JSON}" | jq empty 2> /dev/null; then
|
||||||
|
echo "Warning: managed_settings is not valid JSON, skipping policy write"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command_exists sudo; then
|
||||||
|
sudo mkdir -p "$${dropin_dir}"
|
||||||
|
echo "$${ARG_MANAGED_SETTINGS_JSON}" | sudo tee "$${target}" > /dev/null
|
||||||
|
sudo chmod 0644 "$${target}"
|
||||||
|
else
|
||||||
|
mkdir -p "$${dropin_dir}"
|
||||||
|
echo "$${ARG_MANAGED_SETTINGS_JSON}" > "$${target}"
|
||||||
|
chmod 0644 "$${target}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Wrote Claude Code managed settings to $${target}"
|
||||||
|
}
|
||||||
|
|
||||||
function configure_standalone_mode() {
|
function configure_standalone_mode() {
|
||||||
echo "Configuring Claude Code for standalone mode..."
|
echo "Configuring Claude Code for standalone mode..."
|
||||||
|
|
||||||
@ -158,8 +186,6 @@ function configure_standalone_mode() {
|
|||||||
echo "Updating existing Claude configuration at $${claude_config}"
|
echo "Updating existing Claude configuration at $${claude_config}"
|
||||||
|
|
||||||
jq '.autoUpdaterStatus = "disabled" |
|
jq '.autoUpdaterStatus = "disabled" |
|
||||||
.autoModeAccepted = true |
|
|
||||||
.bypassPermissionsModeAccepted = true |
|
|
||||||
.hasAcknowledgedCostThreshold = true |
|
.hasAcknowledgedCostThreshold = true |
|
||||||
.hasCompletedOnboarding = true' \
|
.hasCompletedOnboarding = true' \
|
||||||
"$${claude_config}" > "$${claude_config}.tmp" && mv "$${claude_config}.tmp" "$${claude_config}"
|
"$${claude_config}" > "$${claude_config}.tmp" && mv "$${claude_config}.tmp" "$${claude_config}"
|
||||||
@ -168,8 +194,6 @@ function configure_standalone_mode() {
|
|||||||
cat > "$${claude_config}" << EOF
|
cat > "$${claude_config}" << EOF
|
||||||
{
|
{
|
||||||
"autoUpdaterStatus": "disabled",
|
"autoUpdaterStatus": "disabled",
|
||||||
"autoModeAccepted": true,
|
|
||||||
"bypassPermissionsModeAccepted": true,
|
|
||||||
"hasAcknowledgedCostThreshold": true,
|
"hasAcknowledgedCostThreshold": true,
|
||||||
"hasCompletedOnboarding": true
|
"hasCompletedOnboarding": true
|
||||||
}
|
}
|
||||||
@ -189,4 +213,5 @@ EOF
|
|||||||
|
|
||||||
install_claude_code_cli
|
install_claude_code_cli
|
||||||
setup_claude_configurations
|
setup_claude_configurations
|
||||||
|
write_managed_settings
|
||||||
configure_standalone_mode
|
configure_standalone_mode
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user