Language: English | 简体中文
This article describes the configuration that the current source actually consumes. All chunks are non-evaluating because examples may require local credentials, providers, or files.
Configuration locations
Create a user or project file with:
use_codeagent_settings(scope = "user")
use_codeagent_settings(scope = "project")User scope is <config-dir>/settings.json, where
<config-dir> is:
-
CODEAGENT_HOME, when set; -
rappdirs::user_config_dir("codeagent"), whenrappdirsis installed; or - legacy
~/.codeagentas a fallback.
On first use, codeagent attempts a one-time copy from legacy
~/.codeagent to the OS-standard directory. If migration
cannot be completed, the existing legacy directory remains usable.
Project scope is always .codeagent/settings.json under the
current working directory.
Resolution order
The effective sequence is:
- start with package defaults;
- deep-merge user
settings.json; - deep-merge project
.codeagent/settings.json; - export the merged JSON
envblock withSys.setenv(); - read recognized environment-variable overrides;
- derive permission rules and load project instruction files.
The project JSON therefore wins over user JSON. An env
entry is exported before the environment layer is read and overwrites an
already-set variable of the same name in the current process. A process
environment variable wins over top-level JSON only when the merged
env block does not replace it.
Under --vanilla, load_settings() also
imports previously unset CODEAGENT_* values from
~/.Renviron. That fallback occurs after model and endpoint
fields have already been resolved for the current load, so put
CODEAGENT_BASE_URL and CODEAGENT_MODEL in the
JSON env block when relying on automatic CLI construction.
Credentials are read lazily and can remain in ~/.Renviron
or another secret-injection mechanism.
A functional settings example
{
"provider": "openai_compatible",
"model": "main",
"env": {
"CODEAGENT_BASE_URL": "https://YOUR-WORKSPACE/serving-endpoints",
"CODEAGENT_MODEL": "your-main-endpoint-name",
"CODEAGENT_HEAVY_MODEL": "your-heavy-endpoint-name",
"CODEAGENT_FAST_MODEL": "your-fast-endpoint-name"
},
"permissions": {
"allow": ["Read", "Bash(R CMD check *)"],
"deny": ["Bash(rm -rf *)"],
"ask": ["Write"]
},
"sandbox": {
"enabled": false,
"allow_network": true
},
"effort_level": "high",
"file_tools": "core",
"midloop_compact": true,
"midloop_full_compact": false,
"explore_data": true,
"auto_continue": false,
"web_citations": "off",
"max_budget_usd": null
}Use snake_case for fields consumed directly by the R implementation.
In particular, effort_level is passed to
ellmer::params(reasoning_effort = ...); camelCase
effortLevel may be retained in the loaded list but is not
used by the automatic Chat factory.
Important defaults include:
| Setting | Default | Meaning |
|---|---|---|
provider |
NULL |
Use openai_compatible when base_url
exists; otherwise use anthropic. |
model |
NULL |
Provider-dependent: native ellmer providers may choose their own
default; OpenAI-compatible endpoints normally need JSON,
CODEAGENT_MODEL, or an explicit Chat. |
max_turns |
100L |
Loop limit; normally choose it with a constructor/config argument. |
model_limit |
dynamic, fallback 200,000 | Context window derived from model/provider unless overridden. |
max_output_tokens |
8192L |
Stored output-token setting. |
max_budget_usd |
NULL |
No dollar cap. |
permission_mode |
"default" |
Base loader value; see constructor precedence below. |
sandbox |
disabled, network allowed | Best-effort Bash/RunR defense in depth. |
file_tools |
"core" |
Core tools; alternatives are "btw" and
"both". |
midloop_compact |
TRUE |
Cheap near-limit tool-result snipping between rounds. |
midloop_full_compact |
FALSE |
Do not make a blocking full compaction call mid-stream. |
explore_data |
TRUE |
Register the exec-gated ExploreData arbitrary-R
tool. |
rag |
FALSE |
Do not build/use codebase RAG. |
inject_r_env |
FALSE |
Do not inject .GlobalEnv object summaries. |
auto_continue |
FALSE |
Start a fresh Shiny conversation. |
web_citations |
"off" |
Deterministic Shiny citation presentation is opt-in. |
Constructor arguments override loaded values
codeagent_client() always writes its
permission_mode, max_turns,
btw_groups, worktree_isolation,
verify_fn, and mcp_config arguments into the
live settings. Because those arguments have defaults, use the
constructor to choose these values rather than relying on similarly
named JSON or environment entries:
client <- codeagent_client(
permission_mode = "accept_edits",
max_turns = 50L,
btw_groups = c("docs", "git", "pkg"),
worktree_isolation = TRUE,
max_budget_usd = 2.50
)max_budget_usd = NULL is the exception: it preserves a
positive value loaded from max_budget_usd or
CODEAGENT_MAX_BUDGET_USD. The cap is checked through
chat$get_cost() and can trigger only when ellmer has
pricing for the active provider/model.
permissions.defaultMode is not mapped to the
constructor’s mode. The permissions.allow,
deny, and ask arrays are functional: they are
converted to ordered PermissionRule objects, and
caller-supplied rules are prepended.
Environment variables
The current implementation uses these variables directly:
| Variable | Current use |
|---|---|
CODEAGENT_HOME |
Override the user configuration directory. |
CODEAGENT_BASE_URL |
OpenAI-compatible endpoint and compact-model backend selection. |
CODEAGENT_MODEL |
Active/default model and the main tier. |
CODEAGENT_HEAVY_MODEL |
heavy model alias; not selected automatically. |
CODEAGENT_FAST_MODEL |
fast alias and preferred
compaction/classification/reviewer model. |
CODEAGENT_API_KEY |
Default credential read by OpenAI-compatible and several hosted-provider factories. |
CODEAGENT_MAX_BUDGET_USD |
Positive dollar-cost cap. |
CODEAGENT_MODEL_LIMIT |
Value loaded into settings$model_limit; dynamic context
logic may use its own resolution. |
CODEAGENT_MAX_CONTEXT_TOKENS |
Highest-priority raw context-window override. |
CODEAGENT_AUTO_COMPACT_WINDOW |
Cap the window used to calculate compaction thresholds. |
CODEAGENT_DISABLE_COMPACT |
Any non-empty value disables automatic threshold compaction. |
CODEAGENT_EMBED_MODEL |
Embedding model for opt-in RAG. |
CODEAGENT_PERMISSION_MODE and
CODEAGENT_MAX_TURNS are read by
load_settings(), but the default arguments of
codeagent_client() overwrite them. Pass
permission_mode and max_turns explicitly for a
client. Provider-native ellmer constructors may also use
their own variables, such as ANTHROPIC_API_KEY, AWS
credentials, or OAuth state.
API keys and setup
Do not put API keys in settings.json or a tracked
project file. Prefer a deployment secret or ~/.Renviron. A
keyring entry is not read automatically by the current Chat factory; use
an apiKeyHelper or host integration that retrieves it and
supplies the environment variable:
apiKeyHelper or api_key_helper may name a
command whose first output line is used as
CODEAGENT_API_KEY when that variable is absent:
use_codeagent_setup() is interactive, but its current
implementation includes a detected or newly supplied provider key in the
generated JSON env block before it offers
keyring/~/.Renviron persistence choices. Storing a value in
the keyring does not by itself wire retrieval into the automatic Chat
factory; configure an apiKeyHelper/host integration for
that path. For keyed providers, prefer
use_codeagent_settings() and add the credential separately.
If you use the wizard, inspect and remove any credential from the
generated JSON immediately.
Permission rules
Patterns without parentheses match a whole tool. Parenthesized
content matches the tool’s primary argument with *
wildcards:
{
"permissions": {
"allow": [
"Read",
"Bash(R CMD check *)"
],
"deny": [
"Bash(rm -rf *)"
],
"ask": [
"Write(/shared/*)"
]
}
}Content matching is implemented for Bash,
Read, Write, Edit,
MultiEdit, Glob, and Grep. Rules
are case-sensitive and first match wins. In plan mode,
non-read tools are denied before rules are considered.
Sandbox settings
{
"sandbox": {
"enabled": true,
"allow_network": false,
"keep_env": ["PATH", "HOME", "LANG", "TMPDIR"]
}
}When enabled, Bash receives only keep_env. Network
denial uses an OS network namespace where available and otherwise
degrades, with a warning, to command pattern blocking. RunR
uses a scrubbed callr child and timeout when
callr is installed; without it, execution remains
in-process after pattern checks. This is not a complete filesystem
sandbox.
Project codeagent.md
codeagent_client_config() searches, in order,
.codeagent/config.md and codeagent.md in
cwd, then the literal user fallback
~/.codeagent/config.md. (This fallback does not follow
CODEAGENT_HOME or the OS-standard settings directory.) The
YAML front matter supports client, btw_groups,
permission_mode, and max_turns. The Markdown
body is appended to the system prompt.
---
client:
gpt41: openai/gpt-4.1
local: ollama/llama3.2
sonnet: anthropic/claude-sonnet-4-6
btw_groups: [docs, git, pkg]
permission_mode: default
max_turns: 50
---
Follow tidyverse style and run focused tests before the full suite.
client <- codeagent_client_config(alias = "gpt41")Recognized prefixed client specs are
openai/<model>, anthropic/<model>,
and ollama/<model>. openai/<model>
uses chat_openai_compatible() when
CODEAGENT_BASE_URL is set; without a base URL it falls
through to the normal automatic provider path. A plain model name uses
load_settings() and .make_chat(). In a
non-interactive session, omitting alias selects the first
alias; in an interactive session it opens a menu.
Create a template with:
Project instructions
In addition to settings, codeagent loads instruction files from the
user and up to five directory levels from cwd:
CLAUDE.md, btw.md, AGENTS.md, and
llms.txt. Outer files are included before more specific
inner files. A line consisting only of @path/to/file
imports that file, with cycle detection and a maximum import depth of
five.