noah-code 0.1.0__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 (93) hide show
  1. {noah_code-0.1.0 → noah_code-0.2.0}/.github/workflows/ci.yml +3 -3
  2. {noah_code-0.1.0 → noah_code-0.2.0}/.github/workflows/release.yml +15 -3
  3. {noah_code-0.1.0 → noah_code-0.2.0}/PKG-INFO +70 -16
  4. {noah_code-0.1.0 → noah_code-0.2.0}/README.md +62 -10
  5. noah_code-0.2.0/docs/configuration.md +279 -0
  6. {noah_code-0.1.0 → noah_code-0.2.0}/docs/development.md +16 -3
  7. noah_code-0.2.0/docs/extensions.md +94 -0
  8. noah_code-0.2.0/docs/interactive-reference.md +132 -0
  9. noah_code-0.2.0/docs/releases/v0.1.0.md +25 -0
  10. noah_code-0.2.0/docs/releases/v0.1.1.md +40 -0
  11. noah_code-0.2.0/docs/releases/v0.2.0.md +52 -0
  12. {noah_code-0.1.0 → noah_code-0.2.0}/pyproject.toml +7 -5
  13. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/__init__.py +1 -1
  14. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/agent.py +230 -28
  15. noah_code-0.2.0/src/noah_code/benchmark.py +140 -0
  16. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/cli.py +252 -10
  17. noah_code-0.2.0/src/noah_code/commands.py +202 -0
  18. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/config.py +174 -6
  19. noah_code-0.2.0/src/noah_code/credentials.py +103 -0
  20. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/event_bridge.py +81 -17
  21. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/events.py +1 -0
  22. noah_code-0.2.0/src/noah_code/host.py +1249 -0
  23. noah_code-0.2.0/src/noah_code/llm.py +61 -0
  24. noah_code-0.2.0/src/noah_code/mcp_setup.py +252 -0
  25. noah_code-0.2.0/src/noah_code/providers.py +320 -0
  26. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/sessions.py +80 -3
  27. noah_code-0.2.0/src/noah_code/skills_setup.py +215 -0
  28. noah_code-0.2.0/src/noah_code/summarization.py +34 -0
  29. noah_code-0.2.0/src/noah_code/tool_output.py +97 -0
  30. noah_code-0.2.0/src/noah_code/tools/git_tools.py +210 -0
  31. noah_code-0.2.0/src/noah_code/tools/lsp_tools.py +835 -0
  32. noah_code-0.2.0/src/noah_code/tools/process_tools.py +336 -0
  33. noah_code-0.2.0/src/noah_code/tools/workspace_tools.py +627 -0
  34. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/ui/console.py +4 -2
  35. noah_code-0.2.0/src/noah_code/ui/textual.css +368 -0
  36. noah_code-0.2.0/src/noah_code/ui/textual_app.py +2137 -0
  37. noah_code-0.2.0/src/noah_code/usage.py +107 -0
  38. {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_agent_security.py +6 -0
  39. noah_code-0.2.0/tests/test_cli.py +155 -0
  40. noah_code-0.2.0/tests/test_config.py +152 -0
  41. noah_code-0.2.0/tests/test_credentials.py +60 -0
  42. noah_code-0.2.0/tests/test_efficiency.py +105 -0
  43. noah_code-0.2.0/tests/test_event_bridge.py +64 -0
  44. noah_code-0.2.0/tests/test_git_tools.py +56 -0
  45. noah_code-0.2.0/tests/test_host.py +464 -0
  46. noah_code-0.2.0/tests/test_llm.py +75 -0
  47. noah_code-0.2.0/tests/test_lsp_tools.py +90 -0
  48. noah_code-0.2.0/tests/test_mcp_setup.py +69 -0
  49. noah_code-0.2.0/tests/test_process_tools.py +83 -0
  50. noah_code-0.2.0/tests/test_providers.py +104 -0
  51. {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_sessions.py +58 -0
  52. noah_code-0.2.0/tests/test_skills_setup.py +62 -0
  53. {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_summarization.py +2 -0
  54. noah_code-0.2.0/tests/test_textual_tui.py +882 -0
  55. noah_code-0.2.0/tests/test_workspace_tools.py +292 -0
  56. {noah_code-0.1.0 → noah_code-0.2.0}/uv.lock +105 -11
  57. noah_code-0.1.0/docs/configuration.md +0 -126
  58. noah_code-0.1.0/docs/extensions.md +0 -58
  59. noah_code-0.1.0/docs/interactive-reference.md +0 -55
  60. noah_code-0.1.0/src/noah_code/commands.py +0 -70
  61. noah_code-0.1.0/src/noah_code/host.py +0 -662
  62. noah_code-0.1.0/src/noah_code/mcp_setup.py +0 -91
  63. noah_code-0.1.0/src/noah_code/skills_setup.py +0 -51
  64. noah_code-0.1.0/src/noah_code/tools/git_tools.py +0 -44
  65. noah_code-0.1.0/src/noah_code/tools/workspace_tools.py +0 -269
  66. noah_code-0.1.0/src/noah_code/ui/textual.css +0 -9
  67. noah_code-0.1.0/src/noah_code/ui/textual_app.py +0 -435
  68. noah_code-0.1.0/tests/test_cli.py +0 -64
  69. noah_code-0.1.0/tests/test_config.py +0 -58
  70. noah_code-0.1.0/tests/test_host.py +0 -113
  71. noah_code-0.1.0/tests/test_textual_tui.py +0 -93
  72. noah_code-0.1.0/tests/test_workspace_tools.py +0 -145
  73. {noah_code-0.1.0 → noah_code-0.2.0}/.gitignore +0 -0
  74. {noah_code-0.1.0 → noah_code-0.2.0}/docs/security.md +0 -0
  75. {noah_code-0.1.0 → noah_code-0.2.0}/install.sh +0 -0
  76. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/__main__.py +0 -0
  77. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/approvals.py +0 -0
  78. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/custom_commands.py +0 -0
  79. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/macos_sandbox.py +0 -0
  80. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/permissions.py +0 -0
  81. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/snapshots.py +0 -0
  82. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/tools/__init__.py +0 -0
  83. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/ui/__init__.py +0 -0
  84. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/ui/protocol.py +0 -0
  85. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/updates.py +0 -0
  86. {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/workspace.py +0 -0
  87. {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_custom_commands.py +0 -0
  88. {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_event_bridge_and_shell.py +0 -0
  89. {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_installer.py +0 -0
  90. {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_permissions.py +0 -0
  91. {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_run_exit.py +0 -0
  92. {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_snapshots.py +0 -0
  93. {noah_code-0.1.0 → 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
@@ -105,6 +105,11 @@ jobs:
105
105
  id-token: write
106
106
  attestations: write
107
107
  steps:
108
+ - name: Check out tagged release notes
109
+ uses: actions/checkout@v7
110
+ with:
111
+ persist-credentials: false
112
+
108
113
  - name: Download release distributions
109
114
  uses: actions/download-artifact@v6
110
115
  with:
@@ -123,5 +128,12 @@ jobs:
123
128
  - name: Create release and upload assets
124
129
  env:
125
130
  GH_TOKEN: ${{ github.token }}
131
+ GH_REPO: ${{ github.repository }}
126
132
  RELEASE_TAG: ${{ github.ref_name }}
127
- run: gh release create "$RELEASE_TAG" dist/* --verify-tag --generate-notes --title "$RELEASE_TAG"
133
+ run: |
134
+ notes_file="docs/releases/${RELEASE_TAG}.md"
135
+ if [ -f "$notes_file" ]; then
136
+ gh release create "$RELEASE_TAG" dist/* --verify-tag --notes-file "$notes_file" --title "$RELEASE_TAG"
137
+ else
138
+ gh release create "$RELEASE_TAG" dist/* --verify-tag --generate-notes --title "$RELEASE_TAG"
139
+ fi
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: noah-code
3
- Version: 0.1.0
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
@@ -58,10 +60,6 @@ or system package setup is required.
58
60
  ```bash
59
61
  curl -LsSf https://raw.githubusercontent.com/skundu42/noah-code/main/install.sh | sh
60
62
  ```
61
-
62
- The bootstrapper validates macOS/Linux support, installs the standalone uv package manager, and
63
- downloads an isolated Python 3.12 runtime plus Noah Code. It does not modify a system Python.
64
-
65
63
  Open a new terminal, move into a repository, and run:
66
64
 
67
65
  ```bash
@@ -74,14 +72,26 @@ and seccomp support. You also need an LLM provider account such as OpenAI, Anthr
74
72
  ## Features
75
73
 
76
74
  - Read files, search with ripgrep, and inspect Git status, diffs, and history.
77
- - Edit files with anchored replacements, full rewrites, and concurrent-change detection.
78
- - 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.
79
81
  - Follow repository instructions from `AGENTS.md`, `CLAUDE.md`, and `.noah-code/instructions.md`.
80
82
  - Switch between implementation-focused **build** mode and read-only **plan** mode.
81
83
  - Approve actions once or for a session with ordered `allow`, `ask`, and `deny` rules.
82
84
  - Undo and redo journaled file edits across process restarts.
83
- - Work in a full-screen TUI, a classic console, or one-shot non-interactive mode.
85
+ - Work in an adaptive Atom One Dark cockpit, a classic console, or one-shot non-interactive mode.
86
+ - Type `/` for a live-filtering command and configuration reference; press Enter to send.
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.
84
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`.
94
+ - Switch AI models between turns, with optional cross-repository defaults.
85
95
  - Extend workflows with slash commands, opt-in skills, MCP servers, model selection, and tracing.
86
96
 
87
97
  ## Quick start
@@ -127,11 +137,54 @@ noah --version
127
137
  noah doctor .
128
138
  noah config show .
129
139
  noah update --check
140
+ noah benchmark .
141
+ ```
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 .
130
155
  ```
131
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
+
132
169
  The package also installs `noah-code` and `nc` as equivalent entry points. Because `nc` commonly
133
- refers to netcat, `noah` or `noah-code` is recommended. Keep provider API keys in the environment
134
- 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.
172
+
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.
177
+
178
+ The TUI keeps the conversation central and adds a session-and-plan rail on terminals at least
179
+ 110 columns wide. Tool output streams in a bounded activity panel and compacts after completion,
180
+ keeping long runs responsive without deleting persisted session data. Press `F2` for activity
181
+ details or `F3` for paginated conversation history.
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.
135
188
 
136
189
  ## Documentation
137
190
 
@@ -140,6 +193,7 @@ or trusted NOOA user configuration, never in a repository or Noah Code session m
140
193
  - [Generated-code security](docs/security.md)
141
194
  - [Custom commands, skills, MCP, and tracing](docs/extensions.md)
142
195
  - [Development, CI, and releases](docs/development.md)
196
+ - [Release notes](docs/releases/)
143
197
 
144
198
  ## Updates
145
199
 
@@ -154,7 +208,7 @@ noah update
154
208
  ## Development
155
209
 
156
210
  ```bash
157
- uv sync --extra dev
211
+ uv sync --extra dev --extra mcp --extra tracing
158
212
  uv run ruff check src tests
159
213
  uv run pytest tests
160
214
  uv build
@@ -16,10 +16,6 @@ or system package setup is required.
16
16
  ```bash
17
17
  curl -LsSf https://raw.githubusercontent.com/skundu42/noah-code/main/install.sh | sh
18
18
  ```
19
-
20
- The bootstrapper validates macOS/Linux support, installs the standalone uv package manager, and
21
- downloads an isolated Python 3.12 runtime plus Noah Code. It does not modify a system Python.
22
-
23
19
  Open a new terminal, move into a repository, and run:
24
20
 
25
21
  ```bash
@@ -32,14 +28,26 @@ and seccomp support. You also need an LLM provider account such as OpenAI, Anthr
32
28
  ## Features
33
29
 
34
30
  - Read files, search with ripgrep, and inspect Git status, diffs, and history.
35
- - Edit files with anchored replacements, full rewrites, and concurrent-change detection.
36
- - 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.
37
37
  - Follow repository instructions from `AGENTS.md`, `CLAUDE.md`, and `.noah-code/instructions.md`.
38
38
  - Switch between implementation-focused **build** mode and read-only **plan** mode.
39
39
  - Approve actions once or for a session with ordered `allow`, `ask`, and `deny` rules.
40
40
  - Undo and redo journaled file edits across process restarts.
41
- - Work in a full-screen TUI, a classic console, or one-shot non-interactive mode.
41
+ - Work in an adaptive Atom One Dark cockpit, a classic console, or one-shot non-interactive mode.
42
+ - Type `/` for a live-filtering command and configuration reference; press Enter to send.
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.
42
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`.
50
+ - Switch AI models between turns, with optional cross-repository defaults.
43
51
  - Extend workflows with slash commands, opt-in skills, MCP servers, model selection, and tracing.
44
52
 
45
53
  ## Quick start
@@ -85,11 +93,54 @@ noah --version
85
93
  noah doctor .
86
94
  noah config show .
87
95
  noah update --check
96
+ noah benchmark .
97
+ ```
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 .
88
111
  ```
89
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
+
90
125
  The package also installs `noah-code` and `nc` as equivalent entry points. Because `nc` commonly
91
- refers to netcat, `noah` or `noah-code` is recommended. Keep provider API keys in the environment
92
- 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.
128
+
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.
133
+
134
+ The TUI keeps the conversation central and adds a session-and-plan rail on terminals at least
135
+ 110 columns wide. Tool output streams in a bounded activity panel and compacts after completion,
136
+ keeping long runs responsive without deleting persisted session data. Press `F2` for activity
137
+ details or `F3` for paginated conversation history.
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.
93
144
 
94
145
  ## Documentation
95
146
 
@@ -98,6 +149,7 @@ or trusted NOOA user configuration, never in a repository or Noah Code session m
98
149
  - [Generated-code security](docs/security.md)
99
150
  - [Custom commands, skills, MCP, and tracing](docs/extensions.md)
100
151
  - [Development, CI, and releases](docs/development.md)
152
+ - [Release notes](docs/releases/)
101
153
 
102
154
  ## Updates
103
155
 
@@ -112,7 +164,7 @@ noah update
112
164
  ## Development
113
165
 
114
166
  ```bash
115
- uv sync --extra dev
167
+ uv sync --extra dev --extra mcp --extra tracing
116
168
  uv run ruff check src tests
117
169
  uv run pytest tests
118
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
@@ -33,8 +44,10 @@ Before the first release, configure a PyPI Trusted Publisher for package `noah-c
33
44
  `skundu42`, repository `noah-code`, workflow `release.yml`, and GitHub environment `pypi`. The
34
45
  GitHub environment permits deployments only from tags matching `v*`.
35
46
 
36
- For every release, update the version in `pyproject.toml` and `src/noah_code/__init__.py`, commit
37
- and push the change, then push a matching annotated tag. For example:
47
+ For every release, update the version in `pyproject.toml`, `src/noah_code/__init__.py`, and
48
+ `uv.lock`. Add curated notes at `docs/releases/vX.Y.Z.md`; the release workflow uses that file
49
+ when it exists and otherwise falls back to generated notes. Commit and push the change, then push
50
+ a matching annotated tag. For example:
38
51
 
39
52
  ```bash
40
53
  git tag -a v0.2.0 -m "Noah Code v0.2.0"