noah-code 0.2.3__tar.gz → 0.3.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 (153) hide show
  1. {noah_code-0.2.3 → noah_code-0.3.0}/.github/workflows/ci.yml +38 -0
  2. {noah_code-0.2.3 → noah_code-0.3.0}/.github/workflows/release.yml +3 -0
  3. noah_code-0.3.0/.pre-commit-config.yaml +21 -0
  4. noah_code-0.2.3/README.md → noah_code-0.3.0/PKG-INFO +83 -8
  5. noah_code-0.2.3/PKG-INFO → noah_code-0.3.0/README.md +38 -52
  6. noah_code-0.3.0/docs/assets/noah-logo.svg +15 -0
  7. {noah_code-0.2.3 → noah_code-0.3.0}/docs/configuration.md +112 -22
  8. {noah_code-0.2.3 → noah_code-0.3.0}/docs/development.md +13 -8
  9. {noah_code-0.2.3 → noah_code-0.3.0}/docs/extensions.md +77 -8
  10. {noah_code-0.2.3 → noah_code-0.3.0}/docs/interactive-reference.md +68 -31
  11. noah_code-0.3.0/docs/releases/v0.2.4.md +100 -0
  12. noah_code-0.3.0/docs/releases/v0.3.0.md +75 -0
  13. noah_code-0.3.0/docs/reliability.md +148 -0
  14. noah_code-0.3.0/docs/security.md +67 -0
  15. {noah_code-0.2.3 → noah_code-0.3.0}/pyproject.toml +20 -21
  16. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/__init__.py +1 -1
  17. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/agent.py +194 -16
  18. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/approvals.py +75 -16
  19. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/budget.py +151 -30
  20. noah_code-0.3.0/src/noah_code/checkpoints.py +310 -0
  21. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/cli.py +130 -26
  22. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/commands.py +25 -36
  23. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/composer.py +32 -9
  24. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/config.py +147 -17
  25. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/event_bridge.py +13 -0
  26. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/events.py +0 -1
  27. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/github.py +29 -1
  28. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/host.py +517 -95
  29. noah_code-0.3.0/src/noah_code/llm.py +289 -0
  30. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/macos_sandbox.py +35 -4
  31. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/mcp_setup.py +43 -0
  32. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/nooa_compat.py +6 -0
  33. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/permissions.py +264 -16
  34. noah_code-0.3.0/src/noah_code/runtime_state.py +832 -0
  35. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/sessions.py +51 -2
  36. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/snapshots.py +23 -9
  37. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/steer.py +42 -8
  38. noah_code-0.3.0/src/noah_code/telemetry.py +801 -0
  39. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/tool_output.py +49 -8
  40. noah_code-0.3.0/src/noah_code/tools/__init__.py +1 -0
  41. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/tools/diff_tools.py +0 -9
  42. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/tools/git_tools.py +25 -8
  43. noah_code-0.3.0/src/noah_code/tools/github_tools.py +183 -0
  44. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/tools/lsp_tools.py +144 -57
  45. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/tools/process_tools.py +230 -12
  46. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/tools/question_tools.py +59 -1
  47. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/tools/task_tools.py +45 -4
  48. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/tools/web_tools.py +49 -11
  49. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/tools/workspace_tools.py +347 -34
  50. noah_code-0.3.0/src/noah_code/ui/__init__.py +1 -0
  51. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/ui/textual.css +7 -1
  52. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/ui/textual_app.py +568 -51
  53. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/updates.py +74 -19
  54. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/usage.py +34 -0
  55. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/worktree.py +10 -3
  56. {noah_code-0.2.3 → noah_code-0.3.0}/tests/conftest.py +12 -0
  57. noah_code-0.3.0/tests/test_agent_security.py +267 -0
  58. noah_code-0.3.0/tests/test_approvals.py +113 -0
  59. noah_code-0.3.0/tests/test_budget.py +284 -0
  60. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_cache_context.py +50 -0
  61. noah_code-0.3.0/tests/test_checkpoints.py +278 -0
  62. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_cli.py +160 -1
  63. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_composer.py +64 -0
  64. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_config.py +66 -0
  65. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_efficiency.py +11 -0
  66. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_event_bridge.py +50 -4
  67. noah_code-0.3.0/tests/test_git_tools.py +270 -0
  68. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_github.py +109 -0
  69. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_host.py +310 -9
  70. noah_code-0.3.0/tests/test_llm.py +178 -0
  71. noah_code-0.3.0/tests/test_lsp_tools.py +262 -0
  72. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_mcp_setup.py +48 -0
  73. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_permissions.py +278 -9
  74. noah_code-0.3.0/tests/test_process_tools.py +361 -0
  75. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_question_tools.py +57 -0
  76. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_run_exit.py +10 -0
  77. noah_code-0.3.0/tests/test_runtime_state.py +139 -0
  78. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_sessions.py +63 -0
  79. noah_code-0.3.0/tests/test_snapshots.py +377 -0
  80. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_steer.py +3 -1
  81. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_task_tools.py +36 -0
  82. noah_code-0.3.0/tests/test_telemetry.py +217 -0
  83. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_textual_tui.py +604 -11
  84. noah_code-0.3.0/tests/test_tool_output.py +192 -0
  85. noah_code-0.3.0/tests/test_updates.py +399 -0
  86. noah_code-0.3.0/tests/test_web_tools.py +565 -0
  87. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_workspace_tools.py +365 -11
  88. noah_code-0.3.0/tests/test_worktree.py +356 -0
  89. {noah_code-0.2.3 → noah_code-0.3.0}/uv.lock +192 -29
  90. noah_code-0.2.3/.pre-commit-config.yaml +0 -8
  91. noah_code-0.2.3/docs/security.md +0 -36
  92. noah_code-0.2.3/src/noah_code/checkpoints.py +0 -186
  93. noah_code-0.2.3/src/noah_code/llm.py +0 -75
  94. noah_code-0.2.3/src/noah_code/tools/__init__.py +0 -17
  95. noah_code-0.2.3/src/noah_code/tools/github_tools.py +0 -93
  96. noah_code-0.2.3/src/noah_code/ui/__init__.py +0 -6
  97. noah_code-0.2.3/tests/test_agent_security.py +0 -99
  98. noah_code-0.2.3/tests/test_approvals.py +0 -29
  99. noah_code-0.2.3/tests/test_budget.py +0 -149
  100. noah_code-0.2.3/tests/test_checkpoints.py +0 -135
  101. noah_code-0.2.3/tests/test_git_tools.py +0 -107
  102. noah_code-0.2.3/tests/test_llm.py +0 -75
  103. noah_code-0.2.3/tests/test_lsp_tools.py +0 -90
  104. noah_code-0.2.3/tests/test_process_tools.py +0 -98
  105. noah_code-0.2.3/tests/test_snapshots.py +0 -99
  106. noah_code-0.2.3/tests/test_updates.py +0 -102
  107. noah_code-0.2.3/tests/test_web_tools.py +0 -164
  108. noah_code-0.2.3/tests/test_worktree.py +0 -92
  109. {noah_code-0.2.3 → noah_code-0.3.0}/.gitignore +0 -0
  110. {noah_code-0.2.3 → noah_code-0.3.0}/docs/assets/noah-in-action.svg +0 -0
  111. {noah_code-0.2.3 → noah_code-0.3.0}/docs/releases/v0.1.0.md +0 -0
  112. {noah_code-0.2.3 → noah_code-0.3.0}/docs/releases/v0.1.1.md +0 -0
  113. {noah_code-0.2.3 → noah_code-0.3.0}/docs/releases/v0.2.0.md +0 -0
  114. {noah_code-0.2.3 → noah_code-0.3.0}/docs/releases/v0.2.1.md +0 -0
  115. {noah_code-0.2.3 → noah_code-0.3.0}/docs/releases/v0.2.2.md +0 -0
  116. {noah_code-0.2.3 → noah_code-0.3.0}/docs/releases/v0.2.3.md +0 -0
  117. {noah_code-0.2.3 → noah_code-0.3.0}/install.sh +0 -0
  118. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/__main__.py +0 -0
  119. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/agents.py +0 -0
  120. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/credentials.py +0 -0
  121. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/custom_commands.py +0 -0
  122. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/hooks.py +0 -0
  123. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/llm_replies.py +0 -0
  124. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/project_notes.py +0 -0
  125. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/providers.py +0 -0
  126. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/redaction.py +0 -0
  127. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/secure_files.py +0 -0
  128. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/skills_setup.py +0 -0
  129. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/summarization.py +0 -0
  130. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/themes.py +0 -0
  131. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/tools/media_tools.py +0 -0
  132. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/tools/memory_tools.py +0 -0
  133. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/tools/plan_tools.py +0 -0
  134. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/ui/console.py +0 -0
  135. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/ui/protocol.py +0 -0
  136. {noah_code-0.2.3 → noah_code-0.3.0}/src/noah_code/workspace.py +0 -0
  137. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_agents.py +0 -0
  138. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_compaction_eviction.py +0 -0
  139. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_console_ui.py +0 -0
  140. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_credentials.py +0 -0
  141. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_custom_commands.py +0 -0
  142. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_diff_tools.py +0 -0
  143. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_event_bridge_and_shell.py +0 -0
  144. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_hooks.py +0 -0
  145. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_installer.py +0 -0
  146. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_llm_replies.py +0 -0
  147. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_plan_memory_tools.py +0 -0
  148. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_project_notes.py +0 -0
  149. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_providers.py +0 -0
  150. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_redaction.py +0 -0
  151. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_skills_setup.py +0 -0
  152. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_summarization.py +0 -0
  153. {noah_code-0.2.3 → noah_code-0.3.0}/tests/test_wave1_e2e.py +0 -0
@@ -5,6 +5,9 @@ on:
5
5
  push:
6
6
  branches:
7
7
  - main
8
+ # Also run on version tags so the exact released ref is checked.
9
+ tags:
10
+ - "v*"
8
11
 
9
12
  permissions:
10
13
  contents: read
@@ -67,6 +70,31 @@ jobs:
67
70
  - name: Build distributions
68
71
  run: uv build --out-dir build-dist
69
72
 
73
+ integration:
74
+ name: Integration tests (network)
75
+ runs-on: ubuntu-latest
76
+ timeout-minutes: 15
77
+ # Integration-marked tests hit the live network and can flake for reasons
78
+ # unrelated to the code; keep the signal visible without blocking PRs.
79
+ continue-on-error: true
80
+ steps:
81
+ - name: Check out source
82
+ uses: actions/checkout@v7
83
+ with:
84
+ persist-credentials: false
85
+
86
+ - name: Install uv and Python
87
+ uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
88
+ with:
89
+ enable-cache: true
90
+ python-version: "3.12"
91
+
92
+ - name: Install locked dependencies
93
+ run: uv sync --locked --all-extras --dev
94
+
95
+ - name: Run integration tests
96
+ run: uv run pytest -m integration -q
97
+
70
98
  platform:
71
99
  name: ${{ matrix.name }} smoke test
72
100
  runs-on: ${{ matrix.runner }}
@@ -109,8 +137,18 @@ jobs:
109
137
  rg --version
110
138
 
111
139
  - name: Run tests
140
+ if: runner.os != 'macOS'
112
141
  run: uv run pytest tests -W error::pytest.PytestUnraisableExceptionWarning
113
142
 
143
+ - name: Run tests with coverage (macOS)
144
+ if: runner.os == 'macOS'
145
+ # Collect coverage on macOS too so mac-only paths are measured, but
146
+ # without a fail-under gate: per-platform coverage totals differ,
147
+ # and the 70% gate stays on the ubuntu quality job.
148
+ run: |
149
+ uv run pytest tests --cov=noah_code --cov-report=term \
150
+ -W error::pytest.PytestUnraisableExceptionWarning
151
+
114
152
  - name: Verify command entry point
115
153
  run: uv run noah --version
116
154
 
@@ -53,6 +53,9 @@ jobs:
53
53
  sudo apt-get install -y ripgrep
54
54
  rg --version
55
55
 
56
+ - name: Type check
57
+ run: uv run mypy src/noah_code
58
+
56
59
  - name: Run release checks
57
60
  run: |
58
61
  uv run ruff check src tests
@@ -0,0 +1,21 @@
1
+ # Pre-commit hooks mirroring the CI lint gate.
2
+ # Install with: uv run pre-commit install (or `pre-commit install` once installed)
3
+ repos:
4
+ - repo: https://github.com/astral-sh/ruff-pre-commit
5
+ rev: v0.16.1
6
+ hooks:
7
+ - id: ruff-check
8
+ args: [--fix]
9
+
10
+ - repo: local
11
+ hooks:
12
+ - id: mypy
13
+ name: mypy
14
+ entry: uv run mypy
15
+ language: system
16
+ pass_filenames: false
17
+ - id: uv-lock-check
18
+ name: uv lock --check
19
+ entry: uv lock --check
20
+ language: system
21
+ pass_filenames: false
@@ -1,8 +1,55 @@
1
+ Metadata-Version: 2.5
2
+ Name: noah-code
3
+ Version: 0.3.0
4
+ Summary: Noah Code terminal coding agent, built on NVIDIA OO Agents (NOOA)
5
+ Project-URL: Homepage, https://github.com/skundu42/noah-code
6
+ Project-URL: Documentation, https://github.com/skundu42/noah-code#readme
7
+ Project-URL: Repository, https://github.com/skundu42/noah-code.git
8
+ Project-URL: Issues, https://github.com/skundu42/noah-code/issues
9
+ Project-URL: Releases, https://github.com/skundu42/noah-code/releases
10
+ Author: noah-code contributors
11
+ License: Apache-2.0
12
+ Keywords: agents,coding,nooa,terminal
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: License :: OSI Approved :: Apache Software License
16
+ Classifier: Operating System :: MacOS
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development
21
+ Requires-Python: <3.14,>=3.12
22
+ Requires-Dist: click<9.0.0,>=8.1.0
23
+ Requires-Dist: litellm<1.99.0,>=1.96.0
24
+ Requires-Dist: nooa-cli==0.0.9
25
+ Requires-Dist: nooa==0.0.9
26
+ Requires-Dist: packaging<27.0,>=24.0
27
+ Requires-Dist: pydantic<3.0.0,>=2.5.0
28
+ Requires-Dist: pyyaml<7.0.0,>=6.0.0
29
+ Requires-Dist: rich<16.0.0,>=13.0.0
30
+ Requires-Dist: textual<9.0.0,>=1.0.0
31
+ Provides-Extra: dev
32
+ Requires-Dist: mypy>=2.3.1; extra == 'dev'
33
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
34
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
35
+ Requires-Dist: pytest-socket>=0.7.0; extra == 'dev'
36
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
37
+ Requires-Dist: ruff>=0.8.0; extra == 'dev'
38
+ Requires-Dist: types-pyyaml>=6.0.12.20260815; extra == 'dev'
39
+ Provides-Extra: mcp
40
+ Requires-Dist: nooa[mcp]==0.0.9; extra == 'mcp'
41
+ Provides-Extra: tracing
42
+ Requires-Dist: nooa[tracing]==0.0.9; extra == 'tracing'
43
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http<2.0.0,>=1.44.0; extra == 'tracing'
44
+ Description-Content-Type: text/markdown
45
+
1
46
  <div align="center">
2
47
 
48
+ <img src="https://raw.githubusercontent.com/skundu42/noah-code/main/docs/assets/noah-logo.svg" alt="Noah Code terminal wordmark" width="760">
49
+
3
50
  # Noah Code
4
51
 
5
- **A terminal coding agent built on NVIDIA's NOAA framework**
52
+ **A durable, repository-aware terminal coding agent built on NVIDIA's NOOA framework**
6
53
 
7
54
  [![PyPI](https://img.shields.io/pypi/v/noah-code.svg)](https://pypi.org/project/noah-code/)
8
55
  [![CI](https://github.com/skundu42/noah-code/actions/workflows/ci.yml/badge.svg)](https://github.com/skundu42/noah-code/actions/workflows/ci.yml)
@@ -10,7 +57,7 @@
10
57
 
11
58
  </div>
12
59
 
13
- ![Noah Code handling a repository change in its terminal interface](docs/assets/noah-in-action.svg)
60
+ ![Noah Code handling a repository change in its terminal interface](https://raw.githubusercontent.com/skundu42/noah-code/main/docs/assets/noah-in-action.svg)
14
61
 
15
62
  <p align="center"><sub>The real Textual interface, captured from a deterministic Noah Code session.</sub></p>
16
63
 
@@ -49,10 +96,10 @@ configuration or session history.
49
96
  preimages, concurrent-change detection, immediate diagnostics, and rollback.
50
97
  - **Visible execution.** Stream bounded shell output while commands run, keep servers and watchers
51
98
  as managed background jobs, and revisit activity details with `F2`.
52
- - **Recoverable work.** Review staged and unstaged changes in `/diff`, then undo or redo journaled
53
- file edits even after restarting Noah.
54
- - **Persistent sessions.** Resume repository-scoped conversations, todos, model choices, and
55
- automatically compacted context without losing the full underlying tool results.
99
+ - **Crash-safe work.** Durable file intents roll back interrupted workspace-tool writes, Git
100
+ checkpoints protect shell-driven changes, and interrupted model runs resume after restart.
101
+ - **Persistent sessions.** Resume repository-scoped conversations, steering, todos, model choices,
102
+ budgets, background-job logs, and compacted context without losing full tool results.
56
103
  - **Token-efficient by construction.** Lean tool-output bounds with disk-backed recall, condensed
57
104
  subagent results, cache-stable request prefixes (volatile status arrives as appended events),
58
105
  and pointer-eviction compaction — measured live with `/tokens`.
@@ -60,6 +107,9 @@ configuration or session history.
60
107
  **plan** mode, with ordered `allow`, `ask`, and `deny` permission rules.
61
108
  - **Extensible workflows.** Add slash commands, opt-in skills, MCP servers, or markdown subagents;
62
109
  attach `@files` and images when the task needs more context.
110
+ - **Long-running by design.** Provider retries and configurable fallback models handle transient
111
+ failures, while workspace leases, bounded artifacts, durable process ownership, and `/health`
112
+ keep unattended sessions observable.
63
113
 
64
114
  Noah follows repository instructions from `AGENTS.md`, `CLAUDE.md`, and
65
115
  `.noah-code/instructions.md`.
@@ -116,6 +166,10 @@ Type `/` to search the full command and configuration reference. The most common
116
166
  | --- | --- |
117
167
  | `Enter` | Send the current prompt or accept a selected suggestion |
118
168
  | `Shift+Enter` | Insert a newline |
169
+ | Drag, then `Cmd+C` / `Ctrl+Shift+C` | Select and copy TUI text |
170
+ | `Ctrl+Shift+C` with no selection | Copy the latest Noah reply |
171
+ | `Ctrl+G` | Open the searchable skills picker |
172
+ | `Ctrl+]` | Return to live transcript output |
119
173
  | `Tab` | Switch between build and plan mode |
120
174
  | `F2` | Open execution activity |
121
175
  | `F3` | Open paginated conversation history |
@@ -123,13 +177,32 @@ Type `/` to search the full command and configuration reference. The most common
123
177
  | `/theme` | Choose Atom One Dark, Noah Ocean, Graphite, or High Contrast |
124
178
  | `/diff` | Review staged and unstaged changes |
125
179
  | `/undo` / `/redo` | Traverse the persistent edit journal |
180
+ | `/checkpoints` | List rolling Git worktree checkpoints |
181
+ | `/health` | Inspect durable run, job, inbox, event, and artifact state |
126
182
  | `/tokens` | Inspect tokens, cache usage, prefix stability, model wait, and tool output |
127
183
  | `/efficiency` | Switch between `fast`, `balanced`, and `deep` budgets |
128
184
 
129
185
  On wide terminals, the side rail prioritizes the active operation, Git branch and change counts,
130
186
  session, model usage, update state, and plan. Git status is refreshed in the background at turn
131
187
  boundaries, so the animated working state stays responsive. The main pane remains centered on the
132
- Noah mark until the first prompt, then becomes the conversation and execution timeline.
188
+ large Noah wordmark until the first prompt, then becomes the conversation and execution timeline.
189
+
190
+ ## Sessions and crash recovery
191
+
192
+ Start a new session with `noah .`, resume the latest repository session with
193
+ `noah --continue .`, or reopen an exact session with `noah --session SESSION_ID .`. Inside the TUI,
194
+ use `Ctrl+O`, `/sessions`, or `/continue`.
195
+
196
+ Noah stores conversational history and host runtime state separately. If the process stops during
197
+ an active run, the next launch restores pending steering, usage and budget counters, durable job
198
+ logs, and the original request. Incomplete workspace-tool writes are rolled back, verified orphan
199
+ process groups are cleaned up, and non-interactive runs continue automatically. A request that was
200
+ waiting for user input remains paused for the next user message.
201
+
202
+ By default, only one Noah process may own a checkout at a time. Use `/worktree create` when
203
+ independent agents need to work concurrently. See
204
+ [Reliability and long-running sessions](docs/reliability.md) for the recovery model, provider retry
205
+ controls, quotas, and operational limits.
133
206
 
134
207
  ## Models and providers
135
208
 
@@ -158,7 +231,8 @@ noah --model openai/MODEL --reasoning-effort high .
158
231
  ```
159
232
 
160
233
  See the [provider configuration guide](docs/configuration.md#bring-your-own-api-provider) for
161
- gateway-specific setup.
234
+ gateway-specific setup. Provider request deadlines, exponential retry, and ordered fallback models
235
+ are configured under `[reliability.retries]`.
162
236
 
163
237
  ## Updates
164
238
 
@@ -175,6 +249,7 @@ noah update
175
249
 
176
250
  - [Interactive interface and sessions](docs/interactive-reference.md)
177
251
  - [Configuration, modes, permissions, and updates](docs/configuration.md)
252
+ - [Reliability and long-running sessions](docs/reliability.md)
178
253
  - [Generated-code security](docs/security.md)
179
254
  - [Custom commands, skills, MCP, and tracing](docs/extensions.md)
180
255
  - [Development, CI, and releases](docs/development.md)
@@ -1,52 +1,10 @@
1
- Metadata-Version: 2.5
2
- Name: noah-code
3
- Version: 0.2.3
4
- Summary: Noah Code terminal coding agent, built on NVIDIA OO Agents (NOOA)
5
- Project-URL: Homepage, https://github.com/skundu42/noah-code
6
- Project-URL: Documentation, https://github.com/skundu42/noah-code#readme
7
- Project-URL: Repository, https://github.com/skundu42/noah-code.git
8
- Project-URL: Issues, https://github.com/skundu42/noah-code/issues
9
- Project-URL: Releases, https://github.com/skundu42/noah-code/releases
10
- Author: noah-code contributors
11
- License: Apache-2.0
12
- Keywords: agents,coding,nooa,terminal
13
- Classifier: Development Status :: 3 - Alpha
14
- Classifier: Environment :: Console
15
- Classifier: License :: OSI Approved :: Apache Software License
16
- Classifier: Operating System :: MacOS
17
- Classifier: Operating System :: POSIX :: Linux
18
- Classifier: Programming Language :: Python :: 3.12
19
- Classifier: Programming Language :: Python :: 3.13
20
- Classifier: Topic :: Software Development
21
- Requires-Python: <3.14,>=3.12
22
- Requires-Dist: click>=8.1.0
23
- Requires-Dist: litellm<1.92.0,>=1.84.0
24
- Requires-Dist: nooa-cli==0.0.9
25
- Requires-Dist: nooa==0.0.9
26
- Requires-Dist: packaging>=24.0
27
- Requires-Dist: pydantic>=2.5.0
28
- Requires-Dist: pyyaml>=6.0.0
29
- Requires-Dist: rich>=13.0.0
30
- Requires-Dist: textual>=1.0.0
31
- Provides-Extra: dev
32
- Requires-Dist: mypy>=1.13.0; extra == 'dev'
33
- Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
34
- Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
35
- Requires-Dist: pytest>=8.0.0; extra == 'dev'
36
- Requires-Dist: ruff>=0.8.0; extra == 'dev'
37
- Provides-Extra: mcp
38
- Requires-Dist: nooa[mcp]==0.0.9; extra == 'mcp'
39
- Provides-Extra: tracing
40
- Requires-Dist: nooa[tracing]==0.0.9; extra == 'tracing'
41
- Provides-Extra: tui
42
- Requires-Dist: textual>=1.0.0; extra == 'tui'
43
- Description-Content-Type: text/markdown
44
-
45
1
  <div align="center">
46
2
 
3
+ <img src="https://raw.githubusercontent.com/skundu42/noah-code/main/docs/assets/noah-logo.svg" alt="Noah Code terminal wordmark" width="760">
4
+
47
5
  # Noah Code
48
6
 
49
- **A terminal coding agent built on NVIDIA's NOAA framework**
7
+ **A durable, repository-aware terminal coding agent built on NVIDIA's NOOA framework**
50
8
 
51
9
  [![PyPI](https://img.shields.io/pypi/v/noah-code.svg)](https://pypi.org/project/noah-code/)
52
10
  [![CI](https://github.com/skundu42/noah-code/actions/workflows/ci.yml/badge.svg)](https://github.com/skundu42/noah-code/actions/workflows/ci.yml)
@@ -54,7 +12,7 @@ Description-Content-Type: text/markdown
54
12
 
55
13
  </div>
56
14
 
57
- ![Noah Code handling a repository change in its terminal interface](docs/assets/noah-in-action.svg)
15
+ ![Noah Code handling a repository change in its terminal interface](https://raw.githubusercontent.com/skundu42/noah-code/main/docs/assets/noah-in-action.svg)
58
16
 
59
17
  <p align="center"><sub>The real Textual interface, captured from a deterministic Noah Code session.</sub></p>
60
18
 
@@ -93,10 +51,10 @@ configuration or session history.
93
51
  preimages, concurrent-change detection, immediate diagnostics, and rollback.
94
52
  - **Visible execution.** Stream bounded shell output while commands run, keep servers and watchers
95
53
  as managed background jobs, and revisit activity details with `F2`.
96
- - **Recoverable work.** Review staged and unstaged changes in `/diff`, then undo or redo journaled
97
- file edits even after restarting Noah.
98
- - **Persistent sessions.** Resume repository-scoped conversations, todos, model choices, and
99
- automatically compacted context without losing the full underlying tool results.
54
+ - **Crash-safe work.** Durable file intents roll back interrupted workspace-tool writes, Git
55
+ checkpoints protect shell-driven changes, and interrupted model runs resume after restart.
56
+ - **Persistent sessions.** Resume repository-scoped conversations, steering, todos, model choices,
57
+ budgets, background-job logs, and compacted context without losing full tool results.
100
58
  - **Token-efficient by construction.** Lean tool-output bounds with disk-backed recall, condensed
101
59
  subagent results, cache-stable request prefixes (volatile status arrives as appended events),
102
60
  and pointer-eviction compaction — measured live with `/tokens`.
@@ -104,6 +62,9 @@ configuration or session history.
104
62
  **plan** mode, with ordered `allow`, `ask`, and `deny` permission rules.
105
63
  - **Extensible workflows.** Add slash commands, opt-in skills, MCP servers, or markdown subagents;
106
64
  attach `@files` and images when the task needs more context.
65
+ - **Long-running by design.** Provider retries and configurable fallback models handle transient
66
+ failures, while workspace leases, bounded artifacts, durable process ownership, and `/health`
67
+ keep unattended sessions observable.
107
68
 
108
69
  Noah follows repository instructions from `AGENTS.md`, `CLAUDE.md`, and
109
70
  `.noah-code/instructions.md`.
@@ -160,6 +121,10 @@ Type `/` to search the full command and configuration reference. The most common
160
121
  | --- | --- |
161
122
  | `Enter` | Send the current prompt or accept a selected suggestion |
162
123
  | `Shift+Enter` | Insert a newline |
124
+ | Drag, then `Cmd+C` / `Ctrl+Shift+C` | Select and copy TUI text |
125
+ | `Ctrl+Shift+C` with no selection | Copy the latest Noah reply |
126
+ | `Ctrl+G` | Open the searchable skills picker |
127
+ | `Ctrl+]` | Return to live transcript output |
163
128
  | `Tab` | Switch between build and plan mode |
164
129
  | `F2` | Open execution activity |
165
130
  | `F3` | Open paginated conversation history |
@@ -167,13 +132,32 @@ Type `/` to search the full command and configuration reference. The most common
167
132
  | `/theme` | Choose Atom One Dark, Noah Ocean, Graphite, or High Contrast |
168
133
  | `/diff` | Review staged and unstaged changes |
169
134
  | `/undo` / `/redo` | Traverse the persistent edit journal |
135
+ | `/checkpoints` | List rolling Git worktree checkpoints |
136
+ | `/health` | Inspect durable run, job, inbox, event, and artifact state |
170
137
  | `/tokens` | Inspect tokens, cache usage, prefix stability, model wait, and tool output |
171
138
  | `/efficiency` | Switch between `fast`, `balanced`, and `deep` budgets |
172
139
 
173
140
  On wide terminals, the side rail prioritizes the active operation, Git branch and change counts,
174
141
  session, model usage, update state, and plan. Git status is refreshed in the background at turn
175
142
  boundaries, so the animated working state stays responsive. The main pane remains centered on the
176
- Noah mark until the first prompt, then becomes the conversation and execution timeline.
143
+ large Noah wordmark until the first prompt, then becomes the conversation and execution timeline.
144
+
145
+ ## Sessions and crash recovery
146
+
147
+ Start a new session with `noah .`, resume the latest repository session with
148
+ `noah --continue .`, or reopen an exact session with `noah --session SESSION_ID .`. Inside the TUI,
149
+ use `Ctrl+O`, `/sessions`, or `/continue`.
150
+
151
+ Noah stores conversational history and host runtime state separately. If the process stops during
152
+ an active run, the next launch restores pending steering, usage and budget counters, durable job
153
+ logs, and the original request. Incomplete workspace-tool writes are rolled back, verified orphan
154
+ process groups are cleaned up, and non-interactive runs continue automatically. A request that was
155
+ waiting for user input remains paused for the next user message.
156
+
157
+ By default, only one Noah process may own a checkout at a time. Use `/worktree create` when
158
+ independent agents need to work concurrently. See
159
+ [Reliability and long-running sessions](docs/reliability.md) for the recovery model, provider retry
160
+ controls, quotas, and operational limits.
177
161
 
178
162
  ## Models and providers
179
163
 
@@ -202,7 +186,8 @@ noah --model openai/MODEL --reasoning-effort high .
202
186
  ```
203
187
 
204
188
  See the [provider configuration guide](docs/configuration.md#bring-your-own-api-provider) for
205
- gateway-specific setup.
189
+ gateway-specific setup. Provider request deadlines, exponential retry, and ordered fallback models
190
+ are configured under `[reliability.retries]`.
206
191
 
207
192
  ## Updates
208
193
 
@@ -219,6 +204,7 @@ noah update
219
204
 
220
205
  - [Interactive interface and sessions](docs/interactive-reference.md)
221
206
  - [Configuration, modes, permissions, and updates](docs/configuration.md)
207
+ - [Reliability and long-running sessions](docs/reliability.md)
222
208
  - [Generated-code security](docs/security.md)
223
209
  - [Custom commands, skills, MCP, and tracing](docs/extensions.md)
224
210
  - [Development, CI, and releases](docs/development.md)
@@ -0,0 +1,15 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 230" role="img" aria-labelledby="title description">
2
+ <title id="title">Noah Code</title>
3
+ <desc id="description">The six-line Noah terminal wordmark used by the Noah Code TUI.</desc>
4
+ <rect width="760" height="230" rx="22" fill="#07151d"/>
5
+ <rect x="1" y="1" width="758" height="228" rx="21" fill="none" stroke="#173746" stroke-width="2"/>
6
+ <g fill="#e6edf3" font-family="ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, monospace" font-size="20" font-weight="700" text-anchor="middle">
7
+ <text x="380" y="43">███╗ ██╗ ██████╗ █████╗ ██╗ ██╗</text>
8
+ <text x="380" y="69">████╗ ██║██╔═══██╗██╔══██╗██║ ██║</text>
9
+ <text x="380" y="95">██╔██╗ ██║██║ ██║███████║███████║</text>
10
+ <text x="380" y="121">██║╚██╗██║██║ ██║██╔══██║██╔══██║</text>
11
+ <text x="380" y="147">██║ ╚████║╚██████╔╝██║ ██║██║ ██║</text>
12
+ <text x="380" y="173">╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝</text>
13
+ </g>
14
+ <text x="380" y="207" fill="#5bd1d7" font-family="ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, monospace" font-size="16" font-weight="700" letter-spacing="5" text-anchor="middle">NOAH / C O D E</text>
15
+ </svg>
@@ -112,6 +112,8 @@ max_output_lines = 250
112
112
  max_search_results = 100
113
113
  max_file_results = 500
114
114
  tool_output_retention_hours = 24
115
+ subagent_result_max_chars = 4000
116
+ max_concurrent_subagents = 3
115
117
 
116
118
  [lsp]
117
119
  enabled = true
@@ -122,15 +124,51 @@ max_symbols = 300
122
124
 
123
125
  [processes]
124
126
  max_jobs = 8
125
- max_runtime_seconds = 3600
127
+ max_runtime_seconds = 86400 # 24 hours
126
128
  max_buffer_chars = 64000
127
129
  stop_grace_seconds = 2
128
130
 
131
+ [sampling]
132
+ # Omit values to use provider defaults.
133
+ # temperature = 0.2
134
+ # top_p = 0.95
135
+ # seed = 42
136
+
137
+ [budget]
138
+ # Persistent session-wide limits; omitted values are unlimited.
139
+ # max_tokens = 500000
140
+ # max_cost_usd = 25
141
+ # max_seconds = 28800
142
+
143
+ [checkpoints]
144
+ enabled = true
145
+ max_per_session = 50
146
+ capture_before_mutation = true
147
+
148
+ [reliability]
149
+ auto_resume_interrupted_runs = true
150
+ interaction_timeout_seconds = 86400
151
+ artifact_max_bytes = 2000000000
152
+ session_max_bytes = 5000000000
153
+ max_runtime_events = 20000
154
+ workspace_lease = true
155
+
156
+ [reliability.retries]
157
+ max_attempts = 5
158
+ base_delay_seconds = 0.5
159
+ max_delay_seconds = 20
160
+ jitter_ratio = 0.2
161
+ request_timeout_seconds = 180
162
+ fallback_models = []
163
+
164
+ [hooks]
165
+ # pre_tool = [{ match = "ws_*", command = "./scripts/pre-tool-check" }]
166
+ # post_tool = [{ match = "*", command = "./scripts/audit-tool" }]
167
+
129
168
  [ui]
130
169
  theme = "atom-one-dark" # atom-one-dark, noah-ocean, graphite, or high-contrast
131
170
  frontend = "tui" # "tui" or "console"
132
171
  markdown = true
133
- stream_shell = true
134
172
  show_reasoning = false
135
173
 
136
174
  [summarization]
@@ -141,8 +179,19 @@ target_chars = 2500
141
179
 
142
180
  [tracing]
143
181
  enabled = true
144
- viewer = true
182
+ # Local traces remain available without a collector.
183
+ jsonl_enabled = true
145
184
  # jsonl_dir = "~/.local/share/noah-code/traces"
185
+ # Send traces, metrics, and structured logs over OTLP/HTTP.
186
+ # otlp_endpoint = "http://localhost:4318"
187
+ logs_enabled = true
188
+ metrics_enabled = true
189
+ # Sensitive agent content is excluded unless explicitly opted in.
190
+ capture_content = false
191
+ max_span_attributes = 256
192
+ max_attribute_length = 4096
193
+ metric_export_interval_millis = 30000
194
+ export_timeout_millis = 5000
146
195
 
147
196
  [updates]
148
197
  auto_install = false
@@ -161,11 +210,19 @@ Supported environment overrides include:
161
210
  - `NOAH_CODE_UNSAFE_INPROCESS`
162
211
  - `NOAH_CODE_AUTO_UPDATE`
163
212
 
213
+ OpenTelemetry's standard environment variables are also honored. In particular,
214
+ `OTEL_EXPORTER_OTLP_ENDPOINT` enables remote traces, metrics, and logs without storing an endpoint
215
+ in Noah configuration. Signal-specific endpoint variables and `OTEL_EXPORTER_OTLP_HEADERS` are
216
+ supported by the OTLP exporters; keep authentication headers in the environment or a collector
217
+ secret store rather than TOML.
218
+
164
219
  Repository-controlled configuration cannot weaken the host trust boundary. Project config is
165
- ignored for `auto_approve`, `efficiency`, `enabled_skills`, `lsp`, `mcp`, `permission_rules`,
166
- `processes`, `session_dir`, `tracing`, `updates`, and `unsafe_inprocess_code_execution`. Put those
167
- settings in trusted user config, the environment, or an explicit CLI flag. Language-server
168
- overrides are user-only because they launch local executables.
220
+ ignored for `auto_approve`, `budget`, `efficiency`, `enabled_skills`, `hooks`, `lsp`, `mcp`,
221
+ `permission_rules`, `processes`, `reliability`, `session_dir`, `tracing`, `updates`, and
222
+ `unsafe_inprocess_code_execution`. Put those settings in trusted user config, the environment, or
223
+ an explicit CLI flag. Language-server overrides and hooks are user-only because they launch local
224
+ executables; reliability and budget settings are user-only so repository content cannot weaken
225
+ host limits.
169
226
 
170
227
  A user-configured `permission_rules` array replaces the default rule array. Copy forward every
171
228
  default you still want before adding overrides. Hard secret, destructive-shell, and plan-mode
@@ -175,6 +232,10 @@ Inspect the resolved configuration from the CLI or inside an interactive session
175
232
  lists every nested path, while an optional path scopes the output. Values whose names look like
176
233
  credentials are redacted.
177
234
 
235
+ Configuration is validated strictly: unknown keys (including typos such as `theem` under `[ui]`)
236
+ and invalid values or TOML syntax fail every command with a one-line error naming the file and
237
+ field, never a traceback. Fix the named key or remove it; `noah doctor` reports the same error.
238
+
178
239
  ```bash
179
240
  noah config show .
180
241
  ```
@@ -219,40 +280,67 @@ safety rail (default 40), not an efficiency-profile cap. Switch without restarti
219
280
  /efficiency deep
220
281
  ```
221
282
 
222
- Oversized results are not discarded. Noah writes the exact output to a private cache file for the
223
- configured retention period, returns a bounded head/tail preview, and gives the agent an output ID
224
- for focused line-range retrieval. A truncated file preview is never returned as an editable Match
225
- anchor.
283
+ Oversized results are not discarded. During a durable session Noah writes the exact output to a
284
+ private, content-addressed artifact store, returns a bounded head/tail preview, and gives the agent
285
+ an output ID for focused line-range retrieval. Artifacts remain available when the session is
286
+ resumed and count toward `reliability.artifact_max_bytes` and `session_max_bytes`. A truncated file
287
+ preview is never returned as an editable Match anchor. `tool_output_retention_hours` applies to the
288
+ fallback cache used when workspace tools are embedded without a durable session runtime.
226
289
 
227
290
  Set `lightweight_model` to route compaction to a faster or cheaper model. If it is omitted, that
228
291
  route follows live `/model` switches. Compaction starts at 35% of the active main model's context
229
292
  window by default, preserves the six newest events, and writes a coding checkpoint covering the
230
293
  objective, decisions, files, validation, blockers, and next steps.
231
294
 
295
+ ### Budgets, checkpoints, and reliability
296
+
297
+ `[budget]` limits are cumulative across the parent agent, lightweight route, and custom-model
298
+ subagents. Token, cost, and elapsed-time counters survive process restarts. When a configured cap
299
+ is exceeded, the breach is sticky and later model calls fail before contacting the provider.
300
+
301
+ Git checkpoints are enabled by default and use rolling retention: once the configured maximum is
302
+ reached, Noah removes the oldest ref and continues capturing instead of silently stopping.
303
+ `capture_before_mutation` protects shell-driven changes; workspace-tool edits additionally use
304
+ durable pre-images and the persistent `/undo` journal.
305
+
306
+ `[reliability.retries]` controls transient model-call retries and ordered fallback models. Noah does
307
+ not retry authentication, invalid-request, content-policy, or context-window failures through this
308
+ route. `[reliability]` also controls crash-run resumption, interaction timeouts, session and artifact
309
+ quotas, event retention, and the exclusive checkout lease. See
310
+ [Reliability and long-running sessions](reliability.md) for the recovery sequence and operational
311
+ limits.
312
+
232
313
  ## Modes and permissions
233
314
 
234
315
  | Mode | Behavior |
235
316
  |------|----------|
236
- | `build` | Reads are allowed; edits and shell commands follow permission rules and ask by default |
317
+ | `build` | Routine workspace reads, edits, inspection, web research, skills, and delegation proceed automatically; higher-risk operations ask |
237
318
  | `plan` | Reads are allowed; file edits and mutating shell commands are denied. `self.plan.write` may pin `.noah-code/plan.md` |
238
319
 
239
320
  Switch modes with `--mode`, `/mode build`, or `/mode plan`. The agent can propose a switch with
240
- `self.plan.enter()` / `self.plan.exit_to_build()` after writing a plan. The active mode is stored with the
241
- session.
321
+ `self.plan.enter()` / `self.plan.exit_to_build()` after writing a plan; the transition always asks
322
+ for confirmation and is never auto-approved, so in `noah run --auto` it is refused and the session
323
+ stays in plan mode. The active mode is stored with the session.
242
324
 
243
325
  Permission rules are evaluated in order, and the last matching rule wins. The default policy:
244
326
 
245
327
  - Allows ordinary reads.
246
- - Denies likely secrets, including `.env` variants, private keys, `.git` internals, and session
247
- databases. `.env.example` remains readable.
248
- - Asks before workspace edits, shell commands, web fetches, web searches, and subagents.
328
+ - Denies likely secrets, including `.env` variants, private keys, `.git` internals, credential
329
+ stores (`.npmrc`, `.pypirc`, `.netrc`, `.pgpass`, `.kube/config`, `.docker/config.json`,
330
+ `.aws/credentials`), Java/JCEKS key stores, and session databases. `.env.example` remains
331
+ readable. The same denials apply to Git object syntax (`git show HEAD:.env`) and to patch-output
332
+ Git commands with no path scope (`git log -p`, bare `git show`), which ask instead of being
333
+ auto-approved.
334
+ - Allows workspace edits, read-only in-workspace shell inspection, web reads, skills, and
335
+ delegated tasks without interrupting the turn.
336
+ - Asks before arbitrary shell execution, external paths, MCP access, and remote mutations.
249
337
  - Allows the question tool so the agent can pause for a structured choice.
250
338
  - Denies `git push`, `git clean`, `git reset --hard`, and mutating `gh pr`
251
339
  (`create`, `checkout`, `merge`, `close`, `ready`, `review`). Push and PR
252
340
  mutations go through `/pr` / `self.github` instead.
253
341
  - Allows listing and viewing pull requests; asks before create, push, checkout,
254
342
  or comment.
255
- - Keeps file tools inside the active workspace and asks before skill or MCP access.
343
+ - Keeps file tools inside the active workspace and asks before MCP access.
256
344
  - Denies plan-mode mutations regardless of broader allow rules. Plan mode may still run
257
345
  read-only subagents. Its shell allowlist accepts only literal, unqualified read-only programs;
258
346
  test collection and interpreter execution are not treated as read-only because they can load
@@ -260,10 +348,12 @@ Permission rules are evaluated in order, and the last matching rule wins. The de
260
348
 
261
349
  `--auto` changes routine ask decisions to allow but never overrides an explicit deny.
262
350
  Elevated-risk commands such as file removal, downloads, and package installation still require
263
- explicit approval. Compound shell commands and mutating or unrecognized Git commands cannot be
264
- silently auto-approved. Interpreters, eval/source commands, and indirect execution wrappers, plus
265
- arguments hidden behind variable, command, ANSI-C, or brace expansion, are denied under `--auto`;
266
- run without `--auto` when one of these commands needs explicit approval.
351
+ explicit approval: interactively they ask, and in non-interactive `noah run --auto` they are
352
+ rejected outright instead of being silently approved. Compound shell commands and mutating or
353
+ unrecognized Git commands cannot be silently auto-approved. Interpreters, eval/source commands, and
354
+ indirect execution wrappers, plus arguments hidden behind variable, command, ANSI-C, or brace
355
+ expansion, are denied under `--auto`; run without `--auto` when one of these commands needs
356
+ explicit approval.
267
357
 
268
358
  ## Installation and updates
269
359