diff --git a/ansible/playbooks/provision-agent-host.yml b/ansible/playbooks/provision-agent-host.yml index dd2342a..8206d91 100644 --- a/ansible/playbooks/provision-agent-host.yml +++ b/ansible/playbooks/provision-agent-host.yml @@ -20,6 +20,17 @@ # multica_workspaces_root_mount: "/mnt/utilidor" multica_agent_clis: - claude + # Merged into the daemon user's ~/.claude/settings.json. Mirrors the model + # mix already live on haunted-mansion (unpinned runs on sonnet, subagents + # on haiku), and stops the npm install self-updating past the pin. + multica_claude_settings: + model: sonnet + alwaysThinkingEnabled: false + env: + DISABLE_AUTOUPDATER: "1" + CLAUDE_CODE_SUBAGENT_MODEL: haiku + MAX_THINKING_TOKENS: "4000" + BASH_MAX_OUTPUT_LENGTH: "20000" # --- Secret source ---------------------------------------------------- # This homelab keeps Ansible secrets in ansible-vault encrypted files, so diff --git a/ansible/roles/multica_agent_host/defaults/main.yml b/ansible/roles/multica_agent_host/defaults/main.yml index 5eafec5..bf3f0b3 100644 --- a/ansible/roles/multica_agent_host/defaults/main.yml +++ b/ansible/roles/multica_agent_host/defaults/main.yml @@ -129,6 +129,15 @@ multica_agent_cli_catalog: manual_login: true manual_login_hint: "configure Hermes credentials as {{ multica_user }} (Hermes reads 1Password natively; confirm against its docs)" +# Keys MERGED (recursively) into the daemon user's ~/.claude/settings.json. +# Merged, not templated: Claude Code writes that file itself. Keys not named +# here are left alone. Empty = don't touch the file. +# +# An npm-installed Claude Code updates itself in place, which silently breaks +# the package_version pin above (and the next play downgrades it again). +# Setting env.DISABLE_AUTOUPDATER: "1" here is what makes the pin hold. +multica_claude_settings: {} + # ----------------------------------------------------------------------------- # Node.js (installed only when a selected agent CLI needs npm) # ----------------------------------------------------------------------------- diff --git a/ansible/roles/multica_agent_host/tasks/claude_settings.yml b/ansible/roles/multica_agent_host/tasks/claude_settings.yml new file mode 100644 index 0000000..348ef2b --- /dev/null +++ b/ansible/roles/multica_agent_host/tasks/claude_settings.yml @@ -0,0 +1,34 @@ +--- +- name: Claude settings | Ensure ~/.claude exists + ansible.builtin.file: + path: "{{ multica_user_home }}/.claude" + state: directory + owner: "{{ multica_user }}" + group: "{{ multica_group }}" + mode: "0700" + become: true + +- name: Claude settings | Read the current settings + ansible.builtin.slurp: + src: "{{ multica_user_home }}/.claude/settings.json" + register: _multica_claude_settings_raw + failed_when: false + become: true + +- name: Claude settings | Merge the declared keys over them + ansible.builtin.set_fact: + _multica_claude_settings_current: >- + {{ (_multica_claude_settings_raw.content | b64decode | from_json) + if _multica_claude_settings_raw.content is defined else {} }} + +- name: Claude settings | Write them back if anything differs + ansible.builtin.copy: + dest: "{{ multica_user_home }}/.claude/settings.json" + content: "{{ _multica_claude_settings_current | combine(multica_claude_settings, recursive=true) | to_nice_json }}\n" + owner: "{{ multica_user }}" + group: "{{ multica_group }}" + mode: "0600" + become: true + when: >- + _multica_claude_settings_current | combine(multica_claude_settings, recursive=true) + != _multica_claude_settings_current diff --git a/ansible/roles/multica_agent_host/tasks/main.yml b/ansible/roles/multica_agent_host/tasks/main.yml index 55e4db6..d53edff 100644 --- a/ansible/roles/multica_agent_host/tasks/main.yml +++ b/ansible/roles/multica_agent_host/tasks/main.yml @@ -27,6 +27,13 @@ ansible.builtin.import_tasks: agent_clis.yml tags: [multica, multica_agents] +- name: Claude Code settings + ansible.builtin.import_tasks: claude_settings.yml + when: + - "'claude' in multica_agent_clis" + - multica_claude_settings | length > 0 + tags: [multica, multica_agents, multica_claude_settings] + - name: CLI configuration ansible.builtin.import_tasks: config.yml tags: [multica, multica_config]