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.
- {noah_code-0.1.0 → noah_code-0.2.0}/.github/workflows/ci.yml +3 -3
- {noah_code-0.1.0 → noah_code-0.2.0}/.github/workflows/release.yml +15 -3
- {noah_code-0.1.0 → noah_code-0.2.0}/PKG-INFO +70 -16
- {noah_code-0.1.0 → noah_code-0.2.0}/README.md +62 -10
- noah_code-0.2.0/docs/configuration.md +279 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/docs/development.md +16 -3
- noah_code-0.2.0/docs/extensions.md +94 -0
- noah_code-0.2.0/docs/interactive-reference.md +132 -0
- noah_code-0.2.0/docs/releases/v0.1.0.md +25 -0
- noah_code-0.2.0/docs/releases/v0.1.1.md +40 -0
- noah_code-0.2.0/docs/releases/v0.2.0.md +52 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/pyproject.toml +7 -5
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/__init__.py +1 -1
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/agent.py +230 -28
- noah_code-0.2.0/src/noah_code/benchmark.py +140 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/cli.py +252 -10
- noah_code-0.2.0/src/noah_code/commands.py +202 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/config.py +174 -6
- noah_code-0.2.0/src/noah_code/credentials.py +103 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/event_bridge.py +81 -17
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/events.py +1 -0
- noah_code-0.2.0/src/noah_code/host.py +1249 -0
- noah_code-0.2.0/src/noah_code/llm.py +61 -0
- noah_code-0.2.0/src/noah_code/mcp_setup.py +252 -0
- noah_code-0.2.0/src/noah_code/providers.py +320 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/sessions.py +80 -3
- noah_code-0.2.0/src/noah_code/skills_setup.py +215 -0
- noah_code-0.2.0/src/noah_code/summarization.py +34 -0
- noah_code-0.2.0/src/noah_code/tool_output.py +97 -0
- noah_code-0.2.0/src/noah_code/tools/git_tools.py +210 -0
- noah_code-0.2.0/src/noah_code/tools/lsp_tools.py +835 -0
- noah_code-0.2.0/src/noah_code/tools/process_tools.py +336 -0
- noah_code-0.2.0/src/noah_code/tools/workspace_tools.py +627 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/ui/console.py +4 -2
- noah_code-0.2.0/src/noah_code/ui/textual.css +368 -0
- noah_code-0.2.0/src/noah_code/ui/textual_app.py +2137 -0
- noah_code-0.2.0/src/noah_code/usage.py +107 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_agent_security.py +6 -0
- noah_code-0.2.0/tests/test_cli.py +155 -0
- noah_code-0.2.0/tests/test_config.py +152 -0
- noah_code-0.2.0/tests/test_credentials.py +60 -0
- noah_code-0.2.0/tests/test_efficiency.py +105 -0
- noah_code-0.2.0/tests/test_event_bridge.py +64 -0
- noah_code-0.2.0/tests/test_git_tools.py +56 -0
- noah_code-0.2.0/tests/test_host.py +464 -0
- noah_code-0.2.0/tests/test_llm.py +75 -0
- noah_code-0.2.0/tests/test_lsp_tools.py +90 -0
- noah_code-0.2.0/tests/test_mcp_setup.py +69 -0
- noah_code-0.2.0/tests/test_process_tools.py +83 -0
- noah_code-0.2.0/tests/test_providers.py +104 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_sessions.py +58 -0
- noah_code-0.2.0/tests/test_skills_setup.py +62 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_summarization.py +2 -0
- noah_code-0.2.0/tests/test_textual_tui.py +882 -0
- noah_code-0.2.0/tests/test_workspace_tools.py +292 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/uv.lock +105 -11
- noah_code-0.1.0/docs/configuration.md +0 -126
- noah_code-0.1.0/docs/extensions.md +0 -58
- noah_code-0.1.0/docs/interactive-reference.md +0 -55
- noah_code-0.1.0/src/noah_code/commands.py +0 -70
- noah_code-0.1.0/src/noah_code/host.py +0 -662
- noah_code-0.1.0/src/noah_code/mcp_setup.py +0 -91
- noah_code-0.1.0/src/noah_code/skills_setup.py +0 -51
- noah_code-0.1.0/src/noah_code/tools/git_tools.py +0 -44
- noah_code-0.1.0/src/noah_code/tools/workspace_tools.py +0 -269
- noah_code-0.1.0/src/noah_code/ui/textual.css +0 -9
- noah_code-0.1.0/src/noah_code/ui/textual_app.py +0 -435
- noah_code-0.1.0/tests/test_cli.py +0 -64
- noah_code-0.1.0/tests/test_config.py +0 -58
- noah_code-0.1.0/tests/test_host.py +0 -113
- noah_code-0.1.0/tests/test_textual_tui.py +0 -93
- noah_code-0.1.0/tests/test_workspace_tools.py +0 -145
- {noah_code-0.1.0 → noah_code-0.2.0}/.gitignore +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/docs/security.md +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/install.sh +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/__main__.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/approvals.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/custom_commands.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/macos_sandbox.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/permissions.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/snapshots.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/tools/__init__.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/ui/__init__.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/ui/protocol.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/updates.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/src/noah_code/workspace.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_custom_commands.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_event_bridge_and_shell.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_installer.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_permissions.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_run_exit.py +0 -0
- {noah_code-0.1.0 → noah_code-0.2.0}/tests/test_snapshots.py +0 -0
- {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]
|
|
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]
|
|
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:
|
|
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.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: noah-code
|
|
3
|
-
Version: 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.
|
|
25
|
-
Requires-Dist: nooa==0.0.
|
|
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.
|
|
38
|
+
Requires-Dist: nooa[mcp]==0.0.9; extra == 'mcp'
|
|
37
39
|
Provides-Extra: tracing
|
|
38
|
-
Requires-Dist: nooa[tracing]==0.0.
|
|
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
|
-
-
|
|
78
|
-
|
|
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
|
|
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
|
|
134
|
-
|
|
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
|
-
-
|
|
36
|
-
|
|
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
|
|
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
|
|
92
|
-
|
|
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
|
|
37
|
-
|
|
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"
|