@markusylisiurunen/tau 0.3.49 → 0.3.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +22 -908
  2. package/dist/core/commands/registry.js +4 -4
  3. package/dist/core/commands/registry.js.map +1 -1
  4. package/dist/core/personas.js +19 -10
  5. package/dist/core/personas.js.map +1 -1
  6. package/dist/core/runtime/runtime_bootstrap.js +14 -9
  7. package/dist/core/runtime/runtime_bootstrap.js.map +1 -1
  8. package/dist/core/static/tau_docs/client-tools.md +228 -0
  9. package/dist/core/static/tau_docs/config-reference.md +422 -0
  10. package/dist/core/static/tau_docs/configuration.md +210 -0
  11. package/dist/core/static/tau_docs/credentials.md +200 -0
  12. package/dist/core/static/tau_docs/getting-started.md +140 -0
  13. package/dist/core/static/tau_docs/history.md +163 -0
  14. package/dist/core/static/tau_docs/index.md +40 -0
  15. package/dist/core/static/tau_docs/manifest.json +28 -0
  16. package/dist/core/static/tau_docs/models.md +198 -0
  17. package/dist/core/static/tau_docs/node-sdk.md +399 -0
  18. package/dist/core/static/tau_docs/nook.md +264 -0
  19. package/dist/core/static/tau_docs/ownership-and-scope.md +104 -0
  20. package/dist/core/static/tau_docs/personas.md +199 -0
  21. package/dist/core/static/tau_docs/prompts-and-project-context.md +181 -0
  22. package/dist/core/static/tau_docs/remote-sessions.md +274 -0
  23. package/dist/core/static/tau_docs/security.md +188 -0
  24. package/dist/core/static/tau_docs/session-protocol-methods.md +577 -0
  25. package/dist/core/static/tau_docs/session-protocol.md +265 -0
  26. package/dist/core/static/tau_docs/sessions.md +223 -0
  27. package/dist/core/static/tau_docs/skills.md +176 -0
  28. package/dist/core/static/tau_docs/subagents.md +203 -0
  29. package/dist/core/static/tau_docs/telegram.md +342 -0
  30. package/dist/core/static/tau_docs/tools.md +203 -0
  31. package/dist/core/static/tau_docs/troubleshooting.md +292 -0
  32. package/dist/core/static/tau_docs/tui.md +224 -0
  33. package/dist/core/telegram/session_manager.js +4 -3
  34. package/dist/core/telegram/session_manager.js.map +1 -1
  35. package/dist/core/tools/catalog.js +3 -1
  36. package/dist/core/tools/catalog.js.map +1 -1
  37. package/dist/core/tools/presentation.js +12 -1
  38. package/dist/core/tools/presentation.js.map +1 -1
  39. package/dist/core/tools/tau_docs.js +115 -0
  40. package/dist/core/tools/tau_docs.js.map +1 -0
  41. package/dist/core/tools/tool_names.js +8 -0
  42. package/dist/core/tools/tool_names.js.map +1 -1
  43. package/dist/core/utils/repository.js +19 -0
  44. package/dist/core/utils/repository.js.map +1 -1
  45. package/dist/core/version.js +1 -1
  46. package/dist/host/client_tool_broker.js +3 -18
  47. package/dist/host/client_tool_broker.js.map +1 -1
  48. package/dist/protocol/session_protocol.d.ts +1 -0
  49. package/dist/protocol/session_protocol.js +2 -1
  50. package/dist/protocol/session_protocol.js.map +1 -1
  51. package/dist/tui/session_chat_app.js +1 -0
  52. package/dist/tui/session_chat_app.js.map +1 -1
  53. package/dist/tui/session_chat_controller.js +13 -13
  54. package/dist/tui/session_chat_controller.js.map +1 -1
  55. package/dist/tui/session_creation_attributes.js +3 -3
  56. package/dist/tui/session_creation_attributes.js.map +1 -1
  57. package/package.json +2 -2
@@ -0,0 +1,422 @@
1
+ # Configuration reference
2
+
3
+ `config.json` controls Tau defaults and integrations. The same schema is available at global and project levels, but a few fields are restricted to one scope and different components consume different results. This reference lists the current fields only.
4
+
5
+ Read [configuration](configuration.md) first for discovery and precedence. In the tables below, **global** means `~/.config/tau/config.json` when that level is eligible, and **project** means an ancestor `.tau/config.json` discovered from the relevant `cwd`.
6
+
7
+ ## Shipped defaults
8
+
9
+ These are defaults built into this Tau version, not a dump of the effective configuration:
10
+
11
+ | Behavior | Shipped default |
12
+ | --- | --- |
13
+ | Default persona | `opus-5-chat` |
14
+ | Default TUI theme | `gold` |
15
+ | Built-in personas | Enabled |
16
+ | Built-in themes | Enabled |
17
+ | Automatic compaction | `{ "enabled": true, "reserveTokens": 16384, "keepRecentTokens": 20000 }` |
18
+ | Speech-to-text provider when unset | `mistral` |
19
+ | Built-in diff tool code theme | `github-dark-dimmed` |
20
+ | Command client tool timeout when unset | `60000` ms |
21
+
22
+ Project and global content can change which ids are actually available. A configured default that is not loaded produces a warning rather than creating that persona or theme.
23
+
24
+ ## Field summary
25
+
26
+ | Field | Type | Scope | Combination | Primary owner and apply boundary |
27
+ | --- | --- | --- | --- | --- |
28
+ | `apiKeys` | Object of string values | Global, project | Merge by provider id | Host or feature consumer; `/reload` for session runtime keys, process restart for environment changes |
29
+ | `defaultPersona` | Non-empty string | Global, project | Most-specific wins | Session host; new session |
30
+ | `disableBuiltinPersonas` | Boolean | Global, project | Most-specific wins | Session runtime; `/reload` or new session |
31
+ | `disableBuiltinThemes` | Boolean | Global, project | Most-specific wins | TUI client; client restart |
32
+ | `defaultTheme` | Non-empty string | Global, project | Most-specific wins | TUI client; client restart |
33
+ | `diffTool` | Object | Global, project | Most-specific complete object | TUI client; client restart |
34
+ | `builtInDiffTool` | Object | Global, project | Most-specific complete object | TUI client; client restart |
35
+ | `clientTools` | Array of objects | Global only | One global definition list | Owning client; TUI restart or new Telegram session client |
36
+ | `enabledClientTools` | String array | Project only | Most-specific project list | Owning client; TUI restart or new Telegram session client |
37
+ | `agentContextFiles` | String array | Global, project | Additive, resolved and deduplicated | Execution environment and session host; `/reload` or new session |
38
+ | `subagents` | Object | Global, project | Field-wise, currently one selectable list | Session runtime; `/reload` or new session |
39
+ | `autoCompact` | Object | Global, project | Merge by field over shipped defaults | Session runtime; `/reload` or new session |
40
+ | `modelSystemNotices` | String map | Global, project | Merge by model target | Session runtime; `/reload`, affects later inputs |
41
+ | `speechToText` | Object | Global, project | Most-specific wins | TUI client or Telegram runner; process restart |
42
+ | `cloudflareSandbox` | Object | Global, project | Merge bridges by id | Host startup; host restart |
43
+ | `flySprites` | Object | Global, project | Merge APIs by id | Host startup; host restart |
44
+ | `nook` | Object | Global, project | Most-specific complete object | Host tool runtime; `/reload` or new session |
45
+ | `history` | Object | Global only | One global object | Host startup; host restart |
46
+
47
+ Unknown fields are stripped without warnings. Wrong types and invalid known values produce warnings, and Tau continues with valid fields. A field at a forbidden scope is rejected.
48
+
49
+ ## Persona, model behavior, and context
50
+
51
+ ### `defaultPersona`
52
+
53
+ A persona id, optionally followed by `:` and a reasoning level:
54
+
55
+ ```json
56
+ {
57
+ "defaultPersona": "gpt-5.6-sol-coder:high"
58
+ }
59
+ ```
60
+
61
+ Allowed reasoning suffixes are `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`. The persona id is matched exactly and case-sensitively during startup selection. The id must exist after built-in, global, and project personas are loaded.
62
+
63
+ `defaultPersona` selects a new session when no CLI or session-creation override is supplied. Reloading an existing session retains its current persona id when possible. See [personas](personas.md).
64
+
65
+ ### `disableBuiltinPersonas`
66
+
67
+ A boolean that removes shipped personas from the loaded persona catalog:
68
+
69
+ ```json
70
+ {
71
+ "disableBuiltinPersonas": true
72
+ }
73
+ ```
74
+
75
+ The default is `false`. When enabled, at least one valid custom persona must be available or session startup fails. This field does not disable user or project personas.
76
+
77
+ ### `agentContextFiles`
78
+
79
+ An array of non-empty paths to additional text files included as project context:
80
+
81
+ ```json
82
+ {
83
+ "agentContextFiles": ["docs/AI_GUIDE.md", "services/payments/AGENTS.md"]
84
+ }
85
+ ```
86
+
87
+ Entries are additive across levels. Global paths resolve from home; project paths resolve from the directory containing `.tau`. Tau deduplicates identical resolved paths. Eligibility and ordinary `AGENTS.md` discovery are described in [prompts and project context](prompts-and-project-context.md).
88
+
89
+ The startup flag `--no-agent-context-files` disables context injection independently of this list.
90
+
91
+ ### `subagents`
92
+
93
+ The top-level subagent configuration currently accepts one optional field:
94
+
95
+ | Nested field | Type | Contract |
96
+ | --- | --- | --- |
97
+ | `defaultLaunchModels` | String array | Allowlist for launch overrides of the built-in `default` subagent |
98
+
99
+ Each entry must use `<provider>/<model>:<effort>` and resolve against the merged model catalog:
100
+
101
+ ```json
102
+ {
103
+ "subagents": {
104
+ "defaultLaunchModels": [
105
+ "openai-codex/gpt-5.6-sol:high",
106
+ "anthropic/claude-haiku-4-5:low"
107
+ ]
108
+ }
109
+ }
110
+ ```
111
+
112
+ A more-specific list replaces the broader list. Custom subagent definitions belong in persona frontmatter, not this object. See [subagents](subagents.md).
113
+
114
+ ### `autoCompact`
115
+
116
+ Automatic compaction settings:
117
+
118
+ | Nested field | Type | Default | Meaning |
119
+ | --- | --- | --- | --- |
120
+ | `enabled` | Boolean | `true` | Whether Tau checks and compacts before model subturns |
121
+ | `reserveTokens` | Positive integer | `16384` | Context reserved below the model's context-window limit |
122
+ | `keepRecentTokens` | Positive integer | `20000` | Target budget for the recent retained tail |
123
+
124
+ Fields merge independently across levels:
125
+
126
+ ```json
127
+ {
128
+ "autoCompact": {
129
+ "reserveTokens": 24000
130
+ }
131
+ }
132
+ ```
133
+
134
+ The omitted fields retain their broader or shipped values. This setting changes Tau's automatic policy; manual `/compact-all` and `/compact-keep-last` remain available. See [sessions](sessions.md).
135
+
136
+ ### `modelSystemNotices`
137
+
138
+ A map from exact `<provider>/<model>` targets to non-empty notice text:
139
+
140
+ ```json
141
+ {
142
+ "modelSystemNotices": {
143
+ "openai/gpt-5.6-sol": "Use the repository's checked-in formatter for source changes."
144
+ }
145
+ }
146
+ ```
147
+
148
+ Provider ids must be known, and model ids must resolve against the merged built-in and `models.json` catalog. Entries merge by normalized target, with the more-specific value winning. Tau prepends the matching notice to later committed main-session and subagent user input. Ephemeral agents and maintenance model calls do not receive a newly resolved notice.
149
+
150
+ Use this for model-specific operational guidance, not for persona behavior that belongs in a persona file. See [models](models.md) and [personas](personas.md).
151
+
152
+ ## Credentials and service selection
153
+
154
+ ### `apiKeys`
155
+
156
+ A map from provider or feature id to a string credential:
157
+
158
+ ```json
159
+ {
160
+ "apiKeys": {
161
+ "anthropic": "sk-ant-...",
162
+ "openai": "sk-...",
163
+ "google": "...",
164
+ "exa": "...",
165
+ "mistral": "..."
166
+ }
167
+ }
168
+ ```
169
+
170
+ The map accepts arbitrary non-empty provider names and string values. Values are trimmed when consumed; an empty string is not a usable credential. Maps merge by key, so a project can replace one provider without removing others.
171
+
172
+ For model requests, credential precedence is an explicit request override, configured `apiKeys.<provider>`, then the provider runtime's ambient authentication. This means `apiKeys.openai` wins over `OPENAI_API_KEY` for model calls. The `openai-codex` provider uses managed OAuth separately and does not use `apiKeys.openai`.
173
+
174
+ Feature-specific helpers use different precedence: `EXA_API_KEY`, `GEMINI_API_KEY`, and `MISTRAL_API_KEY` take precedence over `apiKeys.exa`, `apiKeys.google`, and `apiKeys.mistral` for the features that consume those helpers. See [credentials](credentials.md) for the exact feature matrix.
175
+
176
+ Credentials are consumed where the model or feature runs. In an attached session that is usually the host, not the TUI client. Avoid committing project API keys. See [credentials](credentials.md).
177
+
178
+ ### `speechToText`
179
+
180
+ An object with one required field when present:
181
+
182
+ | Nested field | Type | Values |
183
+ | ------------ | ------ | --------------------- |
184
+ | `provider` | String | `mistral` or `gemini` |
185
+
186
+ ```json
187
+ {
188
+ "speechToText": {
189
+ "provider": "gemini"
190
+ }
191
+ }
192
+ ```
193
+
194
+ When the object is absent, `/listen` and Telegram transcription use `mistral`. The TUI consumes this setting for client-local recording; the Telegram runner consumes it for Telegram audio. Restart the owning process after changing it.
195
+
196
+ ### `nook`
197
+
198
+ Connection details for one existing Nook deployment:
199
+
200
+ | Nested field | Type | Required | Contract |
201
+ | --- | --- | --- | --- |
202
+ | `domain` | Non-empty string | Yes | DNS hostname, optionally supplied as a plain `http://` or `https://` origin with no port, path, query, credentials, or fragment |
203
+ | `accessClientId` | Non-empty string | No | Cloudflare Access service-token client id |
204
+ | `accessClientSecret` | Non-empty string | No | Inline service-token secret |
205
+ | `accessClientSecretEnv` | Non-empty string | No | Host environment variable containing the secret |
206
+
207
+ ```json
208
+ {
209
+ "nook": {
210
+ "domain": "apps.example.com",
211
+ "accessClientId": "8f0c...access",
212
+ "accessClientSecretEnv": "NOOK_ACCESS_CLIENT_SECRET"
213
+ }
214
+ }
215
+ ```
216
+
217
+ Tau normalizes the domain to a lowercase hostname. A non-empty value from `accessClientSecretEnv` takes precedence over `accessClientSecret`. The `nook` tool is available only when both the active persona allows it and effective configuration contains this object. See [Nook](nook.md).
218
+
219
+ ### `history`
220
+
221
+ A global-only remote history target:
222
+
223
+ | Nested field | Type | Required | Contract |
224
+ | --- | --- | --- | --- |
225
+ | `endpoint` | Non-empty string | Yes | HTTP(S) URL with no query or fragment |
226
+ | `apiKey` | Non-empty string | No | Inline service API key |
227
+ | `apiKeyEnv` | Non-empty string | No | Host environment variable containing the key |
228
+
229
+ ```json
230
+ {
231
+ "history": {
232
+ "endpoint": "https://history.example.com",
233
+ "apiKeyEnv": "TEAM_TAU_HISTORY_KEY"
234
+ }
235
+ }
236
+ ```
237
+
238
+ Credential precedence is `TAU_HISTORY_API_KEY`, then the variable named by `apiKeyEnv`, then `apiKey`. Configuring an endpoint without an available key prevents the host service from starting. Without `history`, transcript storage and queries remain machine-local. See [history](history.md).
239
+
240
+ ## TUI presentation and diff review
241
+
242
+ ### `disableBuiltinThemes`
243
+
244
+ A boolean that removes shipped themes from the TUI client's loaded theme list. The default is `false`.
245
+
246
+ ```json
247
+ {
248
+ "disableBuiltinThemes": true
249
+ }
250
+ ```
251
+
252
+ If built-ins are disabled, provide a valid custom theme. This setting does not affect personas or model behavior.
253
+
254
+ ### `defaultTheme`
255
+
256
+ The exact, case-sensitive id of a loaded theme. The shipped default is `gold`:
257
+
258
+ ```json
259
+ {
260
+ "defaultTheme": "azure"
261
+ }
262
+ ```
263
+
264
+ The attached TUI uses its client-local configuration and theme files. `/theme:<id>` changes the current client only and is not persisted into the session. See [TUI](tui.md).
265
+
266
+ ### `diffTool`
267
+
268
+ A custom client-local diff-review launcher:
269
+
270
+ | Nested field | Type | Required | Contract |
271
+ | --- | --- | --- | --- |
272
+ | `command` | Non-empty string | Yes | Executable name or path |
273
+ | `args` | String array | No | Arguments passed to the executable |
274
+ | `env` | Object of string values | No | Extra environment entries for the tool process |
275
+
276
+ ```json
277
+ {
278
+ "diffTool": {
279
+ "command": "./tools/review-ui",
280
+ "args": ["--browser", "firefox"],
281
+ "env": {
282
+ "REVIEW_LOG_LEVEL": "warn"
283
+ }
284
+ }
285
+ }
286
+ ```
287
+
288
+ The most-specific complete object wins. A relative command containing `/` resolves from the declaring level root; a bare command resolves through client `PATH`. The TUI launches this process on the client machine. If this field is absent, the TUI uses Tau's built-in diff tool. See [TUI](tui.md) and [client tools](client-tools.md) for the broader client-local distinction.
289
+
290
+ ### `builtInDiffTool`
291
+
292
+ Settings for the built-in fallback diff tool:
293
+
294
+ ```json
295
+ {
296
+ "builtInDiffTool": {
297
+ "codeTheme": "nord"
298
+ }
299
+ }
300
+ ```
301
+
302
+ `codeTheme` defaults to `github-dark-dimmed`. Supported values are:
303
+
304
+ `andromeeda`, `aurora-x`, `ayu-dark`, `ayu-mirage`, `catppuccin-frappe`, `catppuccin-macchiato`, `catppuccin-mocha`, `dark-plus`, `dracula`, `dracula-soft`, `everforest-dark`, `github-dark`, `github-dark-default`, `github-dark-dimmed`, `github-dark-high-contrast`, `gruvbox-dark-hard`, `gruvbox-dark-medium`, `gruvbox-dark-soft`, `horizon`, `horizon-bright`, `houston`, `kanagawa-dragon`, `kanagawa-wave`, `laserwave`, `material-theme`, `material-theme-darker`, `material-theme-ocean`, `material-theme-palenight`, `min-dark`, `monokai`, `night-owl`, `nord`, `one-dark-pro`, `plastic`, `poimandres`, `red`, `rose-pine`, `rose-pine-moon`, `slack-dark`, `solarized-dark`, `synthwave-84`, `tokyo-night`, `vesper`, `vitesse-black`, and `vitesse-dark`.
305
+
306
+ This object does not configure a custom `diffTool` process.
307
+
308
+ ## Command client tools
309
+
310
+ ### `clientTools`
311
+
312
+ A global-only array of commands exposed as client-provided tools:
313
+
314
+ | Nested field | Type | Required | Contract |
315
+ | --- | --- | --- | --- |
316
+ | `name` | Non-empty string | Yes | Unique within the array |
317
+ | `defaultEnabled` | Boolean | Yes | Advertise when no project selection exists |
318
+ | `description` | Non-empty string | Yes | Model-facing tool description |
319
+ | `parameters` | JSON Schema object | Yes | Root `type` must be `"object"` |
320
+ | `command` | Non-empty string | Yes | Executable name or path |
321
+ | `args` | String array | No | Command arguments |
322
+ | `executionTimeoutMs` | Positive integer | No | Invocation timeout, default `60000` |
323
+
324
+ ```json
325
+ {
326
+ "clientTools": [
327
+ {
328
+ "name": "open-ticket",
329
+ "defaultEnabled": false,
330
+ "description": "Open a ticket in the client team's tracker.",
331
+ "parameters": {
332
+ "type": "object",
333
+ "properties": {
334
+ "title": { "type": "string" }
335
+ },
336
+ "required": ["title"],
337
+ "additionalProperties": false
338
+ },
339
+ "command": "./bin/open-ticket"
340
+ }
341
+ ]
342
+ }
343
+ ```
344
+
345
+ Unknown properties inside `parameters` are preserved as part of the configured schema; unknown fields elsewhere in each tool object are stripped. A command containing `/` resolves from home because definitions are global. The command executes directly on the owning client without a shell and participates in Tau's bounded client-tool protocol.
346
+
347
+ TUI startup flag `--no-client-tools` disables both configured command tools and built-in TUI client tools. See [client tools](client-tools.md).
348
+
349
+ ### `enabledClientTools`
350
+
351
+ A project-only exact allowlist of names from global `clientTools`:
352
+
353
+ ```json
354
+ {
355
+ "enabledClientTools": ["open-ticket"]
356
+ }
357
+ ```
358
+
359
+ Names are trimmed and duplicates removed. Unknown names are silently ignored. An empty list selects none. If the field is absent at every project level, Tau selects tools with `defaultEnabled: true`.
360
+
361
+ The most-specific project list replaces broader project lists. Project configuration cannot define executable client tool commands.
362
+
363
+ ## Hosted execution environments
364
+
365
+ These fields configure resolvers owned by a host process. They do not provision sandboxes or Sprites. A client creating a session supplies an existing environment identity and `cwd` that references one of these host-known entries. See [remote sessions](remote-sessions.md).
366
+
367
+ ### `cloudflareSandbox`
368
+
369
+ An optional `bridges` map keyed by bridge id:
370
+
371
+ ```json
372
+ {
373
+ "cloudflareSandbox": {
374
+ "bridges": {
375
+ "team": {
376
+ "url": "https://tau-sandbox.example.workers.dev",
377
+ "apiKeyEnv": "TAU_SANDBOX_BRIDGE_KEY",
378
+ "home": "/home/sandbox"
379
+ }
380
+ }
381
+ }
382
+ }
383
+ ```
384
+
385
+ Each bridge accepts:
386
+
387
+ | Nested field | Type | Required | Default or behavior |
388
+ | --- | --- | --- | --- |
389
+ | `url` | Non-empty string | Yes | Bridge base URL; schema requires a string but does not perform general URL validation |
390
+ | `apiKey` | Non-empty string | No | Inline bridge key; takes precedence when present |
391
+ | `apiKeyEnv` | Non-empty string | No | Host environment variable used when `apiKey` is absent |
392
+ | `home` | Non-empty string | No | Execution-environment home, default `/home/sandbox` |
393
+
394
+ Bridge maps merge by id. A more-specific bridge replaces the complete entry with that id, so it must repeat the required `url`.
395
+
396
+ ### `flySprites`
397
+
398
+ An optional `apis` map keyed by API id:
399
+
400
+ ```json
401
+ {
402
+ "flySprites": {
403
+ "apis": {
404
+ "personal": {
405
+ "tokenEnv": "FLY_SPRITES_TOKEN",
406
+ "home": "/home/sprite"
407
+ }
408
+ }
409
+ }
410
+ }
411
+ ```
412
+
413
+ Each API accepts:
414
+
415
+ | Nested field | Type | Required | Default or behavior |
416
+ | --- | --- | --- | --- |
417
+ | `baseURL` | Non-empty string | No | Defaults to `https://api.sprites.dev` |
418
+ | `token` | Non-empty string | No | Inline token; takes precedence when present |
419
+ | `tokenEnv` | Non-empty string | No | Host environment variable used when `token` is absent |
420
+ | `home` | Non-empty string | No | Execution-environment home, default `/home/sprite` |
421
+
422
+ A usable token is required when the host resolves a Sprite. API maps merge by id, with the more-specific complete entry replacing the broader entry.
@@ -0,0 +1,210 @@
1
+ # Configuration
2
+
3
+ Tau builds configuration from a working directory, not from one universal file. It combines shipped defaults, an eligible global level, and every project level on the path to that working directory. Knowing whose working directory is in use is as important as knowing the field name.
4
+
5
+ This page explains how the layers behave. Use [configuration reference](config-reference.md) for the fields themselves and [ownership and scope](ownership-and-scope.md) when more than one machine is involved.
6
+
7
+ ## Where configuration is loaded
8
+
9
+ Tau recognizes these `config.json` locations:
10
+
11
+ | Level | Path | Included when |
12
+ | --- | --- | --- |
13
+ | Shipped defaults | Built into the installed Tau version | Always |
14
+ | Global | `~/.config/tau/config.json` | The relevant `cwd` is the home directory or lies below it |
15
+ | Project | `<ancestor>/.tau/config.json` | The ancestor is on the path from the relevant `cwd` to the discovery stop |
16
+
17
+ When `cwd` is inside home, discovery stops at home. When it is outside home, the global level is omitted and project discovery continues to the filesystem root.
18
+
19
+ Tau recognizes a project level when that ancestor contains either `.tau/` or `.agents/skills/`. A `config.json` file is optional at a recognized level. This allows skill-only levels to participate in content discovery without requiring an empty config file.
20
+
21
+ For this layout:
22
+
23
+ ```text
24
+ /home/ada/
25
+ .config/tau/config.json
26
+ work/ledger/
27
+ .tau/config.json
28
+ packages/api/
29
+ .tau/config.json
30
+ ```
31
+
32
+ starting from `/home/ada/work/ledger/packages/api` loads, from least to most specific:
33
+
34
+ ```text
35
+ /home/ada/.config/tau/config.json
36
+ /home/ada/work/ledger/.tau/config.json
37
+ /home/ada/work/ledger/packages/api/.tau/config.json
38
+ ```
39
+
40
+ In a remote session, the session runtime uses the execution environment's `cwd` and home. An attached TUI separately loads client-local settings from the attach process's `cwd` and home.
41
+
42
+ ## How levels combine
43
+
44
+ Most scalar or whole-object settings use **most-specific wins**. A value in the nearest project level replaces the corresponding value from broader levels.
45
+
46
+ In `~/.config/tau/config.json`:
47
+
48
+ ```json
49
+ {
50
+ "defaultPersona": "opus-5-chat",
51
+ "speechToText": { "provider": "mistral" }
52
+ }
53
+ ```
54
+
55
+ In `~/work/ledger/.tau/config.json`:
56
+
57
+ ```json
58
+ {
59
+ "defaultPersona": "gpt-5.6-sol-coder:high",
60
+ "speechToText": { "provider": "gemini" }
61
+ }
62
+ ```
63
+
64
+ Within the project, the effective values are the coder persona and the Gemini speech provider. Tau does not recursively combine `speechToText`; the project object replaces the global object.
65
+
66
+ A few fields intentionally use other rules:
67
+
68
+ - `apiKeys` merges by provider id. A more-specific key replaces only the same provider's value.
69
+ - `autoCompact` merges by field on top of shipped defaults.
70
+ - `modelSystemNotices` merges by normalized `<provider>/<model>` key.
71
+ - `cloudflareSandbox.bridges` merges by bridge id. A more-specific bridge replaces the complete bridge with that id.
72
+ - `flySprites.apis` merges by API id. A more-specific API replaces the complete API entry with that id.
73
+ - `agentContextFiles` is additive across levels, resolves each entry at its owning level, and removes duplicate resolved paths while preserving order.
74
+ - `diffTool` and `builtInDiffTool` select the complete object from the most-specific level that defines them.
75
+ - `subagents.defaultLaunchModels` selects the most-specific list.
76
+ - `clientTools` is defined only at global scope. `enabledClientTools` at the most-specific project level is an exact selection from those definitions.
77
+ - `history` is accepted only at global scope.
78
+
79
+ An empty project `enabledClientTools` list deliberately disables all configured command client tools for that project:
80
+
81
+ ```json
82
+ {
83
+ "enabledClientTools": []
84
+ }
85
+ ```
86
+
87
+ Without `enabledClientTools`, Tau selects global client tools whose `defaultEnabled` value is `true`. Unknown selected names are ignored.
88
+
89
+ ## How relative paths resolve
90
+
91
+ Relative path bases belong to the level that declares the value:
92
+
93
+ - Global `agentContextFiles` entries resolve from home.
94
+ - Project `agentContextFiles` entries resolve from the directory containing `.tau`.
95
+ - A relative `diffTool.command` containing a slash resolves from the same level root.
96
+ - A global `clientTools[].command` containing a slash resolves from home.
97
+ - A bare command such as `review-ui` is left bare and resolves through the owning process's `PATH`.
98
+
99
+ For example, in `/home/ada/work/ledger/.tau/config.json`:
100
+
101
+ ```json
102
+ {
103
+ "agentContextFiles": ["docs/AI_GUIDE.md"],
104
+ "diffTool": {
105
+ "command": "./tools/review-ui"
106
+ }
107
+ }
108
+ ```
109
+
110
+ Tau resolves the paths as `/home/ada/work/ledger/docs/AI_GUIDE.md` and `/home/ada/work/ledger/tools/review-ui`. In an attached session, `diffTool` used by the TUI comes from the client-local load, so this resolved command is a client path.
111
+
112
+ Other strings that happen to contain paths are not automatically rebased unless their field contract says so. In particular, hosted execution-environment `home` values are passed as configured.
113
+
114
+ ## Invalid and unknown fields
115
+
116
+ Each `config.json` must contain a JSON object. Malformed JSON, wrong types, invalid enum values, unknown model targets, and fields used at a forbidden scope produce configuration warnings. Tau keeps valid fields from the same file and continues merging other levels. Run `/reload` in an idle session to see the current warnings.
117
+
118
+ If a more-specific field is invalid, it is skipped rather than replacing a valid broader value. This can make the broader value remain effective, so do not treat a warning as if the requested override took effect.
119
+
120
+ Unknown object fields are accepted and stripped without a warning. This applies at the top level and in validated nested objects. It makes newer configuration tolerable to an older binary, but it also means misspelled fields have no effect:
121
+
122
+ ```json
123
+ {
124
+ "defaultPersnoa": "gpt-5.6-sol-coder"
125
+ }
126
+ ```
127
+
128
+ The example is valid JSON and produces no setting because `defaultPersnoa` is unknown. Compare edited keys against [configuration reference](config-reference.md), especially when no warning appears.
129
+
130
+ ## Make a safe edit
131
+
132
+ First identify the consumer and its `cwd`, home, and machine. Then choose the narrowest valid scope:
133
+
134
+ - Personal defaults and secrets usually belong in eligible global configuration.
135
+ - Repository behavior shared by collaborators belongs in a project `.tau/config.json` when it contains no secrets or machine-local commands.
136
+ - Nested project levels are appropriate only when that subtree genuinely needs a different value.
137
+ - Client-only commands should not be placed in a remote execution environment and expected to appear on an attached laptop.
138
+
139
+ Keep examples small and edit only the intended field. Validate JSON before asking Tau to load it:
140
+
141
+ ```sh
142
+ node -e 'JSON.parse(require("node:fs").readFileSync(process.argv[1], "utf8"))' \
143
+ ~/.config/tau/config.json
144
+ ```
145
+
146
+ That check proves syntax only. Start Tau from the relevant `cwd` to validate field contracts and content references:
147
+
148
+ ```sh
149
+ cd ~/work/ledger
150
+ tau --debug
151
+ ```
152
+
153
+ `--debug` is appropriate for a local startup and can reveal project instructions in its output. It does not query an already running host, remote execution environment, or attached client's state. For a live session runtime, use `/reload` and read its configuration warnings. There is no command that serializes the complete effective configuration.
154
+
155
+ Never verify a secret by printing the full config or environment into a shared transcript. Test the operation that needs the credential, and use the auth commands for Codex OAuth accounts.
156
+
157
+ ## When changes take effect
158
+
159
+ ### New local or client process
160
+
161
+ Tau loads startup configuration and content before opening the TUI. Restart the local TUI or `tau attach` to apply client-owned changes such as:
162
+
163
+ - `defaultTheme`, `disableBuiltinThemes`, and theme files
164
+ - `diffTool` and `builtInDiffTool`
165
+ - `clientTools` and `enabledClientTools`
166
+ - `speechToText` for `/listen`
167
+ - client environment variables
168
+
169
+ Changing `/theme:<id>` updates only the current client presentation. Themes are not persisted in session snapshots.
170
+
171
+ ### Current session runtime
172
+
173
+ Run `/reload` when no session turn is active to recollect runtime configuration and content from the execution environment. Reload updates the current session's runtime config, model catalog, personas, prompts, skills, selected persona definition, and project context. It reports warnings and refreshes the session catalog.
174
+
175
+ The current persona id is retained if it still exists; otherwise Tau chooses the first available persona. Changing `defaultPersona` does not by itself switch an existing session during reload. It selects new sessions unless a CLI or creation request overrides it.
176
+
177
+ A logical turn captures its persona, model settings, and tools when it starts. Reload is blocked while a turn is active, and reloaded behavior applies to later turns.
178
+
179
+ ### Host startup
180
+
181
+ Restart the host process to apply settings used to construct host-wide services, including:
182
+
183
+ - `cloudflareSandbox.bridges`
184
+ - `flySprites.apis`
185
+ - `history`
186
+ - host environment variables and Codex account forcing
187
+
188
+ For `tau serve` or `tau rpc`, make the changes on the host machine and restart that server. Restarting only an attached TUI does not rebuild the host.
189
+
190
+ ### New session or runner
191
+
192
+ Some settings are choices rather than live mutations. `defaultPersona` and startup persona flags select a new session. Execution-environment kind, identity, `cwd`, and home are fixed when the session is created or recovered.
193
+
194
+ The Telegram runner loads its speech provider and separate runner config at startup. Restart it for speech, project, routing, or workspace-preparation changes. Command client tools are selected when a Telegram session client is created, so configuration changes apply to new sessions; restarting the runner also rebuilds clients while recovering its sessions. Existing sessions retain their recorded execution environment unless the documented recovery behavior reconstructs a managed workspace.
195
+
196
+ ## Common precedence mistakes
197
+
198
+ **Editing global config for a project outside home.** The global level is omitted when the relevant `cwd` is outside home. Add an appropriate project level or change the environment's configured home rather than assuming `~/.config/tau` is always included.
199
+
200
+ **Editing the laptop for host behavior.** An attached TUI cannot provide credentials, session storage, hosted-environment definitions, or runtime project config to a remote host merely by having them locally.
201
+
202
+ **Editing the host filesystem for target content.** A hosted execution environment owns its project files and home. Put project `.tau` content on that target, not in a similarly named path on the host.
203
+
204
+ **Expecting nested objects to deep-merge.** A project bridge or Sprite API entry replaces the complete entry with the same id. Repeat required fields such as a Cloudflare bridge `url`.
205
+
206
+ **Expecting `/reload` to rebuild the client or server.** Reload is a current-session runtime operation. Restart the component that owns startup-only behavior.
207
+
208
+ **Using a project file for global-only fields.** `clientTools` and `history` are rejected outside global config. `enabledClientTools` is rejected outside project config.
209
+
210
+ **Trusting a silent typo.** Unknown fields are stripped. Check exact names and observe the resulting operation rather than assuming valid JSON means valid Tau configuration.