noah-code 0.1.1__tar.gz → 0.2.0__tar.gz

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 (88) hide show
  1. {noah_code-0.1.1 → noah_code-0.2.0}/.github/workflows/ci.yml +3 -3
  2. {noah_code-0.1.1 → noah_code-0.2.0}/.github/workflows/release.yml +2 -2
  3. {noah_code-0.1.1 → noah_code-0.2.0}/PKG-INFO +59 -14
  4. {noah_code-0.1.1 → noah_code-0.2.0}/README.md +51 -8
  5. noah_code-0.2.0/docs/configuration.md +279 -0
  6. {noah_code-0.1.1 → noah_code-0.2.0}/docs/development.md +12 -1
  7. noah_code-0.2.0/docs/extensions.md +94 -0
  8. {noah_code-0.1.1 → noah_code-0.2.0}/docs/interactive-reference.md +48 -12
  9. noah_code-0.2.0/docs/releases/v0.2.0.md +52 -0
  10. {noah_code-0.1.1 → noah_code-0.2.0}/pyproject.toml +7 -5
  11. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/__init__.py +1 -1
  12. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/agent.py +230 -28
  13. noah_code-0.2.0/src/noah_code/benchmark.py +140 -0
  14. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/cli.py +194 -4
  15. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/commands.py +32 -3
  16. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/config.py +115 -7
  17. noah_code-0.2.0/src/noah_code/credentials.py +103 -0
  18. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/event_bridge.py +45 -8
  19. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/events.py +1 -0
  20. noah_code-0.2.0/src/noah_code/host.py +1249 -0
  21. noah_code-0.2.0/src/noah_code/llm.py +61 -0
  22. noah_code-0.2.0/src/noah_code/mcp_setup.py +252 -0
  23. noah_code-0.2.0/src/noah_code/providers.py +320 -0
  24. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/sessions.py +19 -4
  25. noah_code-0.2.0/src/noah_code/skills_setup.py +215 -0
  26. noah_code-0.2.0/src/noah_code/summarization.py +34 -0
  27. noah_code-0.2.0/src/noah_code/tool_output.py +97 -0
  28. noah_code-0.2.0/src/noah_code/tools/git_tools.py +210 -0
  29. noah_code-0.2.0/src/noah_code/tools/lsp_tools.py +835 -0
  30. noah_code-0.2.0/src/noah_code/tools/process_tools.py +336 -0
  31. noah_code-0.2.0/src/noah_code/tools/workspace_tools.py +627 -0
  32. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/ui/console.py +4 -2
  33. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/ui/textual.css +153 -29
  34. noah_code-0.2.0/src/noah_code/ui/textual_app.py +2137 -0
  35. noah_code-0.2.0/src/noah_code/usage.py +107 -0
  36. {noah_code-0.1.1 → noah_code-0.2.0}/tests/test_agent_security.py +6 -0
  37. {noah_code-0.1.1 → noah_code-0.2.0}/tests/test_cli.py +49 -0
  38. {noah_code-0.1.1 → noah_code-0.2.0}/tests/test_config.py +31 -0
  39. noah_code-0.2.0/tests/test_credentials.py +60 -0
  40. noah_code-0.2.0/tests/test_efficiency.py +105 -0
  41. {noah_code-0.1.1 → noah_code-0.2.0}/tests/test_event_bridge.py +14 -1
  42. noah_code-0.2.0/tests/test_git_tools.py +56 -0
  43. noah_code-0.2.0/tests/test_host.py +464 -0
  44. noah_code-0.2.0/tests/test_llm.py +75 -0
  45. noah_code-0.2.0/tests/test_lsp_tools.py +90 -0
  46. noah_code-0.2.0/tests/test_mcp_setup.py +69 -0
  47. noah_code-0.2.0/tests/test_process_tools.py +83 -0
  48. noah_code-0.2.0/tests/test_providers.py +104 -0
  49. {noah_code-0.1.1 → noah_code-0.2.0}/tests/test_sessions.py +2 -0
  50. noah_code-0.2.0/tests/test_skills_setup.py +62 -0
  51. {noah_code-0.1.1 → noah_code-0.2.0}/tests/test_summarization.py +2 -0
  52. noah_code-0.2.0/tests/test_textual_tui.py +882 -0
  53. noah_code-0.2.0/tests/test_workspace_tools.py +292 -0
  54. {noah_code-0.1.1 → noah_code-0.2.0}/uv.lock +105 -11
  55. noah_code-0.1.1/docs/configuration.md +0 -157
  56. noah_code-0.1.1/docs/extensions.md +0 -58
  57. noah_code-0.1.1/src/noah_code/host.py +0 -715
  58. noah_code-0.1.1/src/noah_code/mcp_setup.py +0 -91
  59. noah_code-0.1.1/src/noah_code/skills_setup.py +0 -51
  60. noah_code-0.1.1/src/noah_code/tools/git_tools.py +0 -44
  61. noah_code-0.1.1/src/noah_code/tools/workspace_tools.py +0 -269
  62. noah_code-0.1.1/src/noah_code/ui/textual_app.py +0 -1153
  63. noah_code-0.1.1/tests/test_host.py +0 -230
  64. noah_code-0.1.1/tests/test_textual_tui.py +0 -312
  65. noah_code-0.1.1/tests/test_workspace_tools.py +0 -145
  66. {noah_code-0.1.1 → noah_code-0.2.0}/.gitignore +0 -0
  67. {noah_code-0.1.1 → noah_code-0.2.0}/docs/releases/v0.1.0.md +0 -0
  68. {noah_code-0.1.1 → noah_code-0.2.0}/docs/releases/v0.1.1.md +0 -0
  69. {noah_code-0.1.1 → noah_code-0.2.0}/docs/security.md +0 -0
  70. {noah_code-0.1.1 → noah_code-0.2.0}/install.sh +0 -0
  71. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/__main__.py +0 -0
  72. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/approvals.py +0 -0
  73. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/custom_commands.py +0 -0
  74. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/macos_sandbox.py +0 -0
  75. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/permissions.py +0 -0
  76. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/snapshots.py +0 -0
  77. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/tools/__init__.py +0 -0
  78. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/ui/__init__.py +0 -0
  79. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/ui/protocol.py +0 -0
  80. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/updates.py +0 -0
  81. {noah_code-0.1.1 → noah_code-0.2.0}/src/noah_code/workspace.py +0 -0
  82. {noah_code-0.1.1 → noah_code-0.2.0}/tests/test_custom_commands.py +0 -0
  83. {noah_code-0.1.1 → noah_code-0.2.0}/tests/test_event_bridge_and_shell.py +0 -0
  84. {noah_code-0.1.1 → noah_code-0.2.0}/tests/test_installer.py +0 -0
  85. {noah_code-0.1.1 → noah_code-0.2.0}/tests/test_permissions.py +0 -0
  86. {noah_code-0.1.1 → noah_code-0.2.0}/tests/test_run_exit.py +0 -0
  87. {noah_code-0.1.1 → noah_code-0.2.0}/tests/test_snapshots.py +0 -0
  88. {noah_code-0.1.1 → noah_code-0.2.0}/tests/test_updates.py +0 -0
@@ -41,7 +41,7 @@ jobs:
41
41
  run: uv run ruff check src tests
42
42
 
43
43
  - name: Test
44
- run: uv run pytest tests
44
+ run: uv run pytest tests -W error::pytest.PytestUnraisableExceptionWarning
45
45
 
46
46
  - name: Build distributions
47
47
  run: uv build --out-dir build-dist
@@ -77,7 +77,7 @@ jobs:
77
77
  run: uv sync --locked --all-extras --dev
78
78
 
79
79
  - name: Run tests
80
- run: uv run pytest tests
80
+ run: uv run pytest tests -W error::pytest.PytestUnraisableExceptionWarning
81
81
 
82
82
  - name: Verify command entry point
83
83
  run: uv run noah --version
@@ -88,5 +88,5 @@ jobs:
88
88
  UV_TOOL_BIN_DIR: ${{ runner.temp }}/noah-bin
89
89
  run: |
90
90
  uv build --out-dir smoke-dist
91
- uv tool install --managed-python --python 3.12 --no-build --with 'nooa[mcp,tracing]==0.0.8' smoke-dist/*.whl
91
+ uv tool install --managed-python --python 3.12 --no-build --with 'nooa[mcp,tracing]' smoke-dist/*.whl
92
92
  "${UV_TOOL_BIN_DIR}/noah" --version
@@ -50,7 +50,7 @@ jobs:
50
50
  - name: Run release checks
51
51
  run: |
52
52
  uv run ruff check src tests
53
- uv run pytest tests
53
+ uv run pytest tests -W error::pytest.PytestUnraisableExceptionWarning
54
54
  uv lock --check
55
55
 
56
56
  - name: Build wheel and source distribution
@@ -64,7 +64,7 @@ jobs:
64
64
  UV_TOOL_DIR: ${{ runner.temp }}/noah-tools
65
65
  UV_TOOL_BIN_DIR: ${{ runner.temp }}/noah-bin
66
66
  run: |
67
- uv tool install --managed-python --python 3.12 --no-build --with 'nooa[mcp,tracing]==0.0.8' dist/*.whl
67
+ uv tool install --managed-python --python 3.12 --no-build --with 'nooa[mcp,tracing]' dist/*.whl
68
68
  "${UV_TOOL_BIN_DIR}/noah" --version
69
69
 
70
70
  - name: Upload release distributions
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: noah-code
3
- Version: 0.1.1
3
+ Version: 0.2.0
4
4
  Summary: Noah Code terminal coding agent, built on NVIDIA OO Agents (NOOA)
5
5
  Project-URL: Homepage, https://github.com/skundu42/noah-code
6
6
  Project-URL: Documentation, https://github.com/skundu42/noah-code#readme
@@ -20,11 +20,13 @@ Classifier: Programming Language :: Python :: 3.13
20
20
  Classifier: Topic :: Software Development
21
21
  Requires-Python: <3.14,>=3.12
22
22
  Requires-Dist: click>=8.1.0
23
+ Requires-Dist: keyring>=25.0.0
23
24
  Requires-Dist: litellm<1.92.0,>=1.84.0
24
- Requires-Dist: nooa-cli==0.0.8
25
- Requires-Dist: nooa==0.0.8
25
+ Requires-Dist: nooa-cli==0.0.9
26
+ Requires-Dist: nooa==0.0.9
26
27
  Requires-Dist: packaging>=24.0
27
28
  Requires-Dist: pydantic>=2.5.0
29
+ Requires-Dist: pyyaml>=6.0.0
28
30
  Requires-Dist: rich>=13.0.0
29
31
  Requires-Dist: textual>=1.0.0
30
32
  Requires-Dist: tomli>=2.0.0; python_version < '3.11'
@@ -33,9 +35,9 @@ Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
33
35
  Requires-Dist: pytest>=8.0.0; extra == 'dev'
34
36
  Requires-Dist: ruff>=0.8.0; extra == 'dev'
35
37
  Provides-Extra: mcp
36
- Requires-Dist: nooa[mcp]==0.0.8; extra == 'mcp'
38
+ Requires-Dist: nooa[mcp]==0.0.9; extra == 'mcp'
37
39
  Provides-Extra: tracing
38
- Requires-Dist: nooa[tracing]==0.0.8; extra == 'tracing'
40
+ Requires-Dist: nooa[tracing]==0.0.9; extra == 'tracing'
39
41
  Provides-Extra: tui
40
42
  Requires-Dist: textual>=1.0.0; extra == 'tui'
41
43
  Description-Content-Type: text/markdown
@@ -70,8 +72,12 @@ and seccomp support. You also need an LLM provider account such as OpenAI, Anthr
70
72
  ## Features
71
73
 
72
74
  - Read files, search with ripgrep, and inspect Git status, diffs, and history.
73
- - Edit files with anchored replacements, full rewrites, and concurrent-change detection.
74
- - Run permission-gated shell commands with timeouts and streamed output.
75
+ - Navigate definitions, implementations, references, symbols, hover types, and diagnostics through
76
+ lazily launched language servers plus an mtime-cached repository map.
77
+ - Edit files with anchored replacements or atomic multi-file patches with exact preimages,
78
+ rollback, immediate diagnostics, and concurrent-change detection.
79
+ - Run permission-gated shell commands with timeouts and streamed output, or own long-running
80
+ servers and watchers as bounded background jobs with cursor-based logs.
75
81
  - Follow repository instructions from `AGENTS.md`, `CLAUDE.md`, and `.noah-code/instructions.md`.
76
82
  - Switch between implementation-focused **build** mode and read-only **plan** mode.
77
83
  - Approve actions once or for a session with ordered `allow`, `ask`, and `deny` rules.
@@ -79,7 +85,12 @@ and seccomp support. You also need an LLM provider account such as OpenAI, Anthr
79
85
  - Work in an adaptive Atom One Dark cockpit, a classic console, or one-shot non-interactive mode.
80
86
  - Type `/` for a live-filtering command and configuration reference; press Enter to send.
81
87
  - Follow batched live tool output, then inspect compact execution records with `F2`.
88
+ - Review `/diff` in a keyboard-driven staged/worktree ledger with per-file patches, line deltas,
89
+ validation state, changed symbols, explicit revert, and checkpoint undo.
82
90
  - Resume workspace-scoped sessions with todos and automatic context compaction.
91
+ - Keep full oversized tool results privately while sending the model a focused, reopenable preview.
92
+ - Inspect token, prompt-cache, model-wait, and tool-output usage with `/tokens`; switch live
93
+ `fast`, `balanced`, and `deep` budgets with `/efficiency`.
83
94
  - Switch AI models between turns, with optional cross-repository defaults.
84
95
  - Extend workflows with slash commands, opt-in skills, MCP servers, model selection, and tracing.
85
96
 
@@ -126,21 +137,55 @@ noah --version
126
137
  noah doctor .
127
138
  noah config show .
128
139
  noah update --check
140
+ noah benchmark .
129
141
  ```
130
142
 
143
+ Bring your own API key from inside the TUI by entering `/model`: choose the provider, paste the
144
+ key into the masked field, choose the model, then select its reasoning effort. Noah saves the key to the operating system's
145
+ credential store when one is available; otherwise it remains available only to that Noah process.
146
+ API-key values are never written to Noah config, repository, or session files.
147
+
148
+ Environment variables and the CLI remain available for scripts and headless use:
149
+
150
+ ```bash
151
+ export OPENAI_API_KEY="..." # or ANTHROPIC_API_KEY / OPENROUTER_API_KEY
152
+ noah providers list
153
+ noah providers add openai --model MODEL_NAME
154
+ noah .
155
+ ```
156
+
157
+ For reasoning models, choose `default`, `none`, `minimal`, `low`, `medium`, `high`, or `xhigh`.
158
+ Provider and model support varies; `default` omits the parameter. You can set it in the guided
159
+ `/model` flow, switch it live with `/reasoning high`, or launch with:
160
+
161
+ ```bash
162
+ uv run noah --model openai/MODEL --reasoning-effort high .
163
+ ```
164
+
165
+ Custom OpenAI-compatible gateways, vLLM, LM Studio, Ollama, Azure OpenAI, Bedrock, Gemini, Groq,
166
+ Mistral, xAI, DeepSeek, Together AI, and Perplexity are also supported. See the
167
+ [provider configuration guide](docs/configuration.md#bring-your-own-api-provider).
168
+
131
169
  The package also installs `noah-code` and `nc` as equivalent entry points. Because `nc` commonly
132
- refers to netcat, `noah` or `noah-code` is recommended. Keep provider API keys in the environment
133
- or trusted NOOA user configuration, never in a repository or Noah Code session metadata.
170
+ refers to netcat, `noah` or `noah-code` is recommended. Keep provider API keys in the OS
171
+ credential store or environment, never in a repository or Noah Code session metadata.
134
172
 
135
- Inside a session, `/model MODEL` switches the active model immediately and remembers it when that
136
- session is resumed. It does not change other sessions. Use `/model --global MODEL` when the new
137
- model should also become the default for future sessions in every repository.
173
+ Inside a session, bare `/model` opens guided provider, API-key, model, and reasoning setup. `/model MODEL`
174
+ switches the active model immediately and remembers it when that session is resumed. It does not
175
+ change other sessions. Use `/model --global MODEL` when the new model should also become the
176
+ default for future sessions in every repository.
138
177
 
139
178
  The TUI keeps the conversation central and adds a session-and-plan rail on terminals at least
140
179
  110 columns wide. Tool output streams in a bounded activity panel and compacts after completion,
141
180
  keeping long runs responsive without deleting persisted session data. Press `F2` for activity
142
181
  details or `F3` for paginated conversation history.
143
182
 
183
+ The default `fast` profile uses compact NOOA trajectory rendering, bounded tool results, batched
184
+ repository inspection, cache-friendly turn-boundary context refresh, and lazy MCP connections. A
185
+ configured `lightweight_model` handles coding-session compaction; deterministic titles avoid an
186
+ otherwise unnecessary model request. Run `noah benchmark .` for the deterministic offline fixture
187
+ and `/tokens` for real provider-reported usage in the current run.
188
+
144
189
  ## Documentation
145
190
 
146
191
  - [Interactive interface and sessions](docs/interactive-reference.md)
@@ -163,7 +208,7 @@ noah update
163
208
  ## Development
164
209
 
165
210
  ```bash
166
- uv sync --extra dev
211
+ uv sync --extra dev --extra mcp --extra tracing
167
212
  uv run ruff check src tests
168
213
  uv run pytest tests
169
214
  uv build
@@ -28,8 +28,12 @@ and seccomp support. You also need an LLM provider account such as OpenAI, Anthr
28
28
  ## Features
29
29
 
30
30
  - Read files, search with ripgrep, and inspect Git status, diffs, and history.
31
- - Edit files with anchored replacements, full rewrites, and concurrent-change detection.
32
- - Run permission-gated shell commands with timeouts and streamed output.
31
+ - Navigate definitions, implementations, references, symbols, hover types, and diagnostics through
32
+ lazily launched language servers plus an mtime-cached repository map.
33
+ - Edit files with anchored replacements or atomic multi-file patches with exact preimages,
34
+ rollback, immediate diagnostics, and concurrent-change detection.
35
+ - Run permission-gated shell commands with timeouts and streamed output, or own long-running
36
+ servers and watchers as bounded background jobs with cursor-based logs.
33
37
  - Follow repository instructions from `AGENTS.md`, `CLAUDE.md`, and `.noah-code/instructions.md`.
34
38
  - Switch between implementation-focused **build** mode and read-only **plan** mode.
35
39
  - Approve actions once or for a session with ordered `allow`, `ask`, and `deny` rules.
@@ -37,7 +41,12 @@ and seccomp support. You also need an LLM provider account such as OpenAI, Anthr
37
41
  - Work in an adaptive Atom One Dark cockpit, a classic console, or one-shot non-interactive mode.
38
42
  - Type `/` for a live-filtering command and configuration reference; press Enter to send.
39
43
  - Follow batched live tool output, then inspect compact execution records with `F2`.
44
+ - Review `/diff` in a keyboard-driven staged/worktree ledger with per-file patches, line deltas,
45
+ validation state, changed symbols, explicit revert, and checkpoint undo.
40
46
  - Resume workspace-scoped sessions with todos and automatic context compaction.
47
+ - Keep full oversized tool results privately while sending the model a focused, reopenable preview.
48
+ - Inspect token, prompt-cache, model-wait, and tool-output usage with `/tokens`; switch live
49
+ `fast`, `balanced`, and `deep` budgets with `/efficiency`.
41
50
  - Switch AI models between turns, with optional cross-repository defaults.
42
51
  - Extend workflows with slash commands, opt-in skills, MCP servers, model selection, and tracing.
43
52
 
@@ -84,21 +93,55 @@ noah --version
84
93
  noah doctor .
85
94
  noah config show .
86
95
  noah update --check
96
+ noah benchmark .
87
97
  ```
88
98
 
99
+ Bring your own API key from inside the TUI by entering `/model`: choose the provider, paste the
100
+ key into the masked field, choose the model, then select its reasoning effort. Noah saves the key to the operating system's
101
+ credential store when one is available; otherwise it remains available only to that Noah process.
102
+ API-key values are never written to Noah config, repository, or session files.
103
+
104
+ Environment variables and the CLI remain available for scripts and headless use:
105
+
106
+ ```bash
107
+ export OPENAI_API_KEY="..." # or ANTHROPIC_API_KEY / OPENROUTER_API_KEY
108
+ noah providers list
109
+ noah providers add openai --model MODEL_NAME
110
+ noah .
111
+ ```
112
+
113
+ For reasoning models, choose `default`, `none`, `minimal`, `low`, `medium`, `high`, or `xhigh`.
114
+ Provider and model support varies; `default` omits the parameter. You can set it in the guided
115
+ `/model` flow, switch it live with `/reasoning high`, or launch with:
116
+
117
+ ```bash
118
+ uv run noah --model openai/MODEL --reasoning-effort high .
119
+ ```
120
+
121
+ Custom OpenAI-compatible gateways, vLLM, LM Studio, Ollama, Azure OpenAI, Bedrock, Gemini, Groq,
122
+ Mistral, xAI, DeepSeek, Together AI, and Perplexity are also supported. See the
123
+ [provider configuration guide](docs/configuration.md#bring-your-own-api-provider).
124
+
89
125
  The package also installs `noah-code` and `nc` as equivalent entry points. Because `nc` commonly
90
- refers to netcat, `noah` or `noah-code` is recommended. Keep provider API keys in the environment
91
- or trusted NOOA user configuration, never in a repository or Noah Code session metadata.
126
+ refers to netcat, `noah` or `noah-code` is recommended. Keep provider API keys in the OS
127
+ credential store or environment, never in a repository or Noah Code session metadata.
92
128
 
93
- Inside a session, `/model MODEL` switches the active model immediately and remembers it when that
94
- session is resumed. It does not change other sessions. Use `/model --global MODEL` when the new
95
- model should also become the default for future sessions in every repository.
129
+ Inside a session, bare `/model` opens guided provider, API-key, model, and reasoning setup. `/model MODEL`
130
+ switches the active model immediately and remembers it when that session is resumed. It does not
131
+ change other sessions. Use `/model --global MODEL` when the new model should also become the
132
+ default for future sessions in every repository.
96
133
 
97
134
  The TUI keeps the conversation central and adds a session-and-plan rail on terminals at least
98
135
  110 columns wide. Tool output streams in a bounded activity panel and compacts after completion,
99
136
  keeping long runs responsive without deleting persisted session data. Press `F2` for activity
100
137
  details or `F3` for paginated conversation history.
101
138
 
139
+ The default `fast` profile uses compact NOOA trajectory rendering, bounded tool results, batched
140
+ repository inspection, cache-friendly turn-boundary context refresh, and lazy MCP connections. A
141
+ configured `lightweight_model` handles coding-session compaction; deterministic titles avoid an
142
+ otherwise unnecessary model request. Run `noah benchmark .` for the deterministic offline fixture
143
+ and `/tokens` for real provider-reported usage in the current run.
144
+
102
145
  ## Documentation
103
146
 
104
147
  - [Interactive interface and sessions](docs/interactive-reference.md)
@@ -121,7 +164,7 @@ noah update
121
164
  ## Development
122
165
 
123
166
  ```bash
124
- uv sync --extra dev
167
+ uv sync --extra dev --extra mcp --extra tracing
125
168
  uv run ruff check src tests
126
169
  uv run pytest tests
127
170
  uv build
@@ -0,0 +1,279 @@
1
+ # Configuration, permissions, and updates
2
+
3
+ ## Configuration
4
+
5
+ Configuration is merged in this order, with later layers taking precedence:
6
+
7
+ 1. Built-in defaults.
8
+ 2. User config at `~/.config/noah-code/config.toml`.
9
+ 3. Project config at `.noah-code/config.toml`.
10
+ 4. `NOAH_CODE_*` environment variables.
11
+ 5. CLI flags.
12
+
13
+ ### First-run model setup
14
+
15
+ The first interactive `noah` launch asks for an AI model before starting the agent. Noah Code
16
+ saves that choice as the top-level `model` in `~/.config/noah-code/config.toml`, making it the
17
+ default for every repository. Enter a LiteLLM model name or an alias from the NOOA model registry.
18
+
19
+ An explicit `noah --model MODEL` on the first launch is saved without prompting. Project config,
20
+ `NOAH_CODE_MODEL`, and later `--model` flags still override the user default according to the
21
+ precedence above. Non-interactive commands such as `noah run`, `doctor`, and `config show` never
22
+ open the onboarding prompt.
23
+
24
+ Inside an interactive session, switch only the current session or replace the global default:
25
+
26
+ ```text
27
+ /model
28
+ /model openai/MODEL_NAME
29
+ /model --global anthropic/MODEL_NAME
30
+ ```
31
+
32
+ Bare `/model` opens a guided TUI flow: search for a provider, enter its API key in a masked
33
+ field, enter the model ID, and select reasoning effort. Noah attempts to save that key in the operating system credential
34
+ store. If no secure backend is available, the key remains active only in the current Noah process
35
+ and the TUI says so. Keys are never written to Noah configuration or session metadata.
36
+
37
+ Model switches take effect between turns and are stored in the current session metadata, so a
38
+ resumed session continues with its most recently selected model. A session-only `/model MODEL`
39
+ does not change the user configuration or affect new sessions.
40
+
41
+ ### Bring your own API provider
42
+
43
+ Enter `/model` for the common provider → API key → model flow. Run `noah providers list` or open
44
+ `/providers` in the TUI for advanced, secret-free setup. Noah supports
45
+ LiteLLM's provider routing and includes guided presets for OpenAI, Anthropic Claude, OpenRouter,
46
+ Google Gemini, Groq, Mistral, xAI, DeepSeek, Together AI, Perplexity, Azure OpenAI, Amazon
47
+ Bedrock, and local Ollama.
48
+
49
+ For scripting, export credentials before starting Noah and select a provider/model:
50
+
51
+ ```bash
52
+ # OpenAI
53
+ export OPENAI_API_KEY="..."
54
+ noah providers add openai --model MODEL_NAME
55
+
56
+ # Anthropic Claude
57
+ export ANTHROPIC_API_KEY="..."
58
+ noah providers add anthropic --model MODEL_NAME
59
+
60
+ # OpenRouter
61
+ export OPENROUTER_API_KEY="..."
62
+ noah providers add openrouter --model PROVIDER/MODEL
63
+
64
+ # Google Gemini (GOOGLE_API_KEY is also accepted)
65
+ export GEMINI_API_KEY="..."
66
+ noah providers add gemini --model MODEL_NAME
67
+ ```
68
+
69
+ Use `--no-set-default` to print a one-launch command without changing Noah's global default.
70
+ Inside Noah, `/providers use openrouter PROVIDER/MODEL` switches the current session and saves the
71
+ new global default.
72
+
73
+ For vLLM, LM Studio, a company gateway, or another OpenAI-compatible API, create a secret-free
74
+ NOOA model alias:
75
+
76
+ ```bash
77
+ export COMPANY_LLM_API_KEY="..."
78
+ noah providers add custom \
79
+ --alias company-llm \
80
+ --model MODEL_ID \
81
+ --base-url https://llm.example.com/v1 \
82
+ --api-key-env COMPANY_LLM_API_KEY
83
+ ```
84
+
85
+ The alias is stored in `~/.config/nooa/llm_config.yaml` with mode `0600`. Only the environment
86
+ variable's name is stored. For an unauthenticated local endpoint, omit `--api-key-env`. You can
87
+ then use the alias anywhere a model is accepted: `noah --model company-llm .` or
88
+ `/model company-llm`.
89
+
90
+ Example user configuration:
91
+
92
+ ```toml
93
+ model = "gpt-4o-mini"
94
+ reasoning_effort = "default" # default, none, minimal, low, medium, high, or xhigh
95
+ lightweight_model = "gpt-4o-mini"
96
+ mode = "build"
97
+ max_iterations = 40
98
+ cell_timeout = 120
99
+ command_timeout = 60
100
+ max_output_chars = 16000
101
+
102
+ [efficiency]
103
+ profile = "fast" # "fast", "balanced", or "deep"
104
+ strategy = "lean" # "standard" is the comparison fallback
105
+ deterministic_titles = true
106
+ lazy_mcp = true
107
+ max_output_lines = 250
108
+ max_search_results = 100
109
+ max_file_results = 500
110
+ tool_output_retention_hours = 24
111
+
112
+ [lsp]
113
+ enabled = true
114
+ timeout_seconds = 5
115
+ max_symbols = 300
116
+ # Trusted user config may override a language server command:
117
+ # servers.python = ["basedpyright-langserver", "--stdio"]
118
+
119
+ [processes]
120
+ max_jobs = 8
121
+ max_runtime_seconds = 3600
122
+ max_buffer_chars = 64000
123
+ stop_grace_seconds = 2
124
+
125
+ [ui]
126
+ theme = "atom-one-dark"
127
+ frontend = "tui" # "tui" or "console"
128
+ markdown = true
129
+ stream_shell = true
130
+ show_reasoning = false
131
+
132
+ [summarization]
133
+ policy = "token_budget" # or "none"
134
+ trigger_ratio = 0.35
135
+ preserve_recent = 6
136
+ target_chars = 2500
137
+
138
+ [tracing]
139
+ enabled = true
140
+ viewer = true
141
+ # jsonl_dir = "~/.local/share/noah-code/traces"
142
+
143
+ [updates]
144
+ auto_install = true
145
+ interval_hours = 24
146
+ ```
147
+
148
+ Supported environment overrides include:
149
+
150
+ - `NOAH_CODE_MODEL`
151
+ - `NOAH_CODE_LIGHTWEIGHT_MODEL`
152
+ - `NOAH_CODE_REASONING_EFFORT`
153
+ - `NOAH_CODE_AUTO`
154
+ - `NOAH_CODE_SESSION_DIR`
155
+ - `NOAH_CODE_MODE`
156
+ - `NOAH_CODE_EFFICIENCY`
157
+ - `NOAH_CODE_UNSAFE_INPROCESS`
158
+ - `NOAH_CODE_AUTO_UPDATE`
159
+
160
+ Repository-controlled configuration cannot weaken the host trust boundary. Project config is
161
+ ignored for `auto_approve`, `efficiency`, `enabled_skills`, `lsp`, `mcp`, `permission_rules`,
162
+ `processes`, `session_dir`, `tracing`, `updates`, and `unsafe_inprocess_code_execution`. Put those
163
+ settings in trusted user config, the environment, or an explicit CLI flag. Language-server
164
+ overrides are user-only because they launch local executables.
165
+
166
+ A user-configured `permission_rules` array replaces the default rule array. Copy forward every
167
+ default you still want before adding overrides. Hard secret, destructive-shell, and plan-mode
168
+ gates remain enforced in code.
169
+
170
+ Inspect the resolved configuration from the CLI or inside an interactive session. `/config`
171
+ lists every nested path, while an optional path scopes the output. Values whose names look like
172
+ credentials are redacted.
173
+
174
+ ```bash
175
+ noah config show .
176
+ ```
177
+
178
+ ```text
179
+ /config
180
+ /config summarization
181
+ /config updates.auto_install
182
+ ```
183
+
184
+ Model and provider configuration follows NOOA conventions, including its model registry,
185
+ environment variables, and configuration under `~/.config/nooa/`. Provider strings not shown in
186
+ the guided list still pass through to LiteLLM, so additional supported services can be selected
187
+ with `--model PROVIDER/MODEL`.
188
+
189
+ Reasoning effort is passed through NOOA to LiteLLM only when it is not `default`. Supported values
190
+ are `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`, but each provider/model may support
191
+ only a subset. Change the current session or the cross-repository default with:
192
+
193
+ ```text
194
+ /reasoning
195
+ /reasoning high
196
+ /reasoning --global low
197
+ ```
198
+
199
+ For headless launches use `--reasoning-effort high`, or add
200
+ `--reasoning-effort high` to `noah providers add ...` when saving a global model default.
201
+
202
+ ### Efficiency and model routing
203
+
204
+ `fast` is the default: at most 12 CodeAct iterations, 16,000 characters and 250 lines per
205
+ model-facing tool result, and lazy MCP attachment. `balanced` raises the live cap to 24 iterations
206
+ and its preview to 24,000 characters/400 lines. `deep` permits the configured `max_iterations` and
207
+ legacy-sized 80,000-character previews. Switch without restarting:
208
+
209
+ ```text
210
+ /efficiency
211
+ /efficiency balanced
212
+ /efficiency deep
213
+ ```
214
+
215
+ Oversized results are not discarded. Noah writes the exact output to a private cache file for the
216
+ configured retention period, returns a bounded head/tail preview, and gives the agent an output ID
217
+ for focused line-range retrieval. A truncated file preview is never returned as an editable Match
218
+ anchor.
219
+
220
+ Set `lightweight_model` to route compaction to a faster or cheaper model. If it is omitted, that
221
+ route follows live `/model` switches. Compaction starts at 35% of the active main model's context
222
+ window by default, preserves the six newest events, and writes a coding checkpoint covering the
223
+ objective, decisions, files, validation, blockers, and next steps.
224
+
225
+ ## Modes and permissions
226
+
227
+ | Mode | Behavior |
228
+ |------|----------|
229
+ | `build` | Reads are allowed; edits and shell commands follow permission rules and ask by default |
230
+ | `plan` | Reads are allowed; file edits and mutating shell commands are denied |
231
+
232
+ Switch modes with `--mode`, `/mode build`, or `/mode plan`. The active mode is stored with the
233
+ session.
234
+
235
+ Permission rules are evaluated in order, and the last matching rule wins. The default policy:
236
+
237
+ - Allows ordinary reads.
238
+ - Denies likely secrets, including `.env` variants, private keys, `.git` internals, and session
239
+ databases. `.env.example` remains readable.
240
+ - Asks before workspace edits and shell commands.
241
+ - Denies `git push`, `git clean`, and `git reset --hard`.
242
+ - Keeps file tools inside the active workspace and asks before skill or MCP access.
243
+ - Denies plan-mode mutations regardless of broader allow rules.
244
+
245
+ `--auto` changes ask decisions to allow but never overrides an explicit deny. Compound shell
246
+ commands and mutating or unrecognized Git commands cannot be silently auto-approved.
247
+
248
+ ## Installation and updates
249
+
250
+ The README executes the checked-in bootstrapper directly from GitHub. From a local clone, run the
251
+ same installer with:
252
+
253
+ ```bash
254
+ sh install.sh
255
+ ```
256
+
257
+ Installs created by the one-line command check PyPI at most once every 24 hours and install newer
258
+ Noah Code releases through uv. When an update is installed, Noah exits before starting the task
259
+ so it cannot mix old and new runtime modules. Rerun the command to continue on the new version.
260
+
261
+ ```bash
262
+ # Check without changing the installation
263
+ noah update --check
264
+
265
+ # Update immediately
266
+ noah update
267
+ ```
268
+
269
+ Disable automatic installation from trusted user configuration or the environment:
270
+
271
+ ```toml
272
+ [updates]
273
+ auto_install = false
274
+ interval_hours = 24
275
+ ```
276
+
277
+ ```bash
278
+ export NOAH_CODE_AUTO_UPDATE=0
279
+ ```
@@ -5,7 +5,7 @@
5
5
  Install the development environment and run the local checks:
6
6
 
7
7
  ```bash
8
- uv sync --extra dev
8
+ uv sync --extra dev --extra mcp --extra tracing
9
9
  uv run ruff check src tests
10
10
  uv run pytest tests
11
11
  uv build
@@ -13,6 +13,17 @@ uv build
13
13
 
14
14
  The default test suite is hermetic and does not require network access or provider keys.
15
15
 
16
+ Run the deterministic efficiency fixture without making provider calls:
17
+
18
+ ```bash
19
+ uv run noah benchmark .
20
+ uv run noah benchmark . --json
21
+ ```
22
+
23
+ It compares standard and lean NOOA trajectory rendering, then measures the configured managed
24
+ preview against a fixed high-volume tool result. The report uses a transparent four-characters-
25
+ per-token estimate; use `/tokens` during a real session for provider-reported usage.
26
+
16
27
  ## CI
17
28
 
18
29
  GitHub Actions runs the complete test suite on Python 3.12 and 3.13, plus platform smoke tests on
@@ -0,0 +1,94 @@
1
+ # Commands, skills, MCP, and tracing
2
+
3
+ ## Custom slash commands
4
+
5
+ Add reusable Markdown prompts in either location:
6
+
7
+ - `~/.config/noah-code/commands/*.md` for user commands.
8
+ - `.noah-code/commands/*.md` for repository commands. Repository commands override user commands
9
+ with the same name.
10
+
11
+ For example, `.noah-code/commands/fix.md`:
12
+
13
+ ```markdown
14
+ ---
15
+ description: Fix a bug and run focused tests
16
+ mode: build
17
+ ---
18
+ Fix $ARGUMENTS. Inspect nearby tests, make the smallest coherent change, and run the focused
19
+ test.
20
+ ```
21
+
22
+ Invoke it as `/fix the parser`. Commands support `$ARGUMENTS` and positional placeholders `$1`
23
+ through `$9`. Front matter may also select a mode or model.
24
+
25
+ ## Skills
26
+
27
+ Open the dedicated searchable picker with `/skills` or `Ctrl+K`. Selecting a document skill
28
+ inserts `$skill-name ` into the composer so you can add the task directly. Noah reads the standard
29
+ `SKILL.md` directory format used by Codex and Claude, including companion `scripts/`, `references/`,
30
+ and `assets/` folders.
31
+
32
+ Project skills are discovered before user skills from:
33
+
34
+ - `.agents/skills/`
35
+ - `.claude/skills/`
36
+ - `.noah-code/skills/`
37
+ - `./skills/`
38
+ - `~/.agents/skills/`
39
+ - `~/.claude/skills/`
40
+ - `~/.codex/skills/`
41
+ - `~/.config/noah-code/skills/`
42
+
43
+ Add an existing skill folder from the picker or the terminal:
44
+
45
+ ```text
46
+ /skills add ~/path/to/my-skill
47
+ ```
48
+
49
+ Noah validates the `SKILL.md` front matter, copies the whole directory to the shared
50
+ `~/.agents/skills/` root, and will not overwrite an existing skill. Skills that depend on a
51
+ vendor-specific runtime, binary, or remote tool still require that dependency to be installed.
52
+
53
+ Discovery does not grant access. Activate trusted skills from user configuration with patterns
54
+ such as:
55
+
56
+ ```toml
57
+ enabled_skills = ["cmd.*"]
58
+ ```
59
+
60
+ Explicit `$skill-name TASK` invocation is also gated by the `skill` permission category. Project
61
+ configuration cannot activate skills.
62
+
63
+ ## MCP
64
+
65
+ MCP support is optional:
66
+
67
+ ```bash
68
+ uv sync --extra mcp
69
+ ```
70
+
71
+ Open `/mcp` to search configured servers, connect one, or add a server through the guided STDIO
72
+ and Streamable HTTP setup. Terminal equivalents are:
73
+
74
+ ```text
75
+ /mcp add stdio filesystem npx -y @modelcontextprotocol/server-filesystem /path
76
+ /mcp add http remote https://example.com/mcp
77
+ /mcp connect filesystem
78
+ ```
79
+
80
+ Noah reads the portable `{"mcpServers": {...}}` structure from `.mcp.json`,
81
+ `.noah-code/mcp.json`, and `~/.config/noah-code/mcp.json`. The guided setup writes to the user
82
+ file with mode `0600`; use environment variables or a manually edited config for secrets and auth
83
+ headers. STDIO, SSE, Streamable HTTP, custom headers, and OAuth fields are passed through to the
84
+ MCP runtime. Under the default `lazy_mcp` setting, servers are cataloged but not connected at
85
+ startup, keeping unused schemas and connection latency out of the session. Select a server in
86
+ `/mcp` or run `/mcp connect NAME` to attach it to the live agent. Attachment is gated by the `mcp`
87
+ permission category and asks by default. Set `efficiency.lazy_mcp = false` in trusted user
88
+ configuration only when eager attachment is desired.
89
+
90
+ ## Tracing
91
+
92
+ Noah Code integrates with NOOA tracing. When a local viewer is available, spans can be exported
93
+ to it. JSONL export can also be enabled in user configuration. Use `/trace` to inspect the active
94
+ destination.