@nathapp/nax 0.82.0 → 0.82.2
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.
- package/README.md +78 -44
- package/dist/nax.js +1271 -658
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
[](https://npmjs.com/@nathapp/nax)
|
|
4
4
|
[](https://github.com/nathapp-io/nax/actions)
|
|
5
5
|
[](https://bun.sh)
|
|
6
|
-
[](https://nodejs.org)
|
|
7
6
|
[](LICENSE)
|
|
8
7
|
|
|
9
8
|
**AI Coding Agent Orchestrator** — loops until done.
|
|
@@ -14,7 +13,7 @@ Give it a spec. It writes tests, implements code, verifies quality, and retries
|
|
|
14
13
|
|
|
15
14
|
nax is an **orchestrator, not an agent** — it doesn't write code itself. It drives whatever coding agent you choose through a disciplined loop until your tests pass.
|
|
16
15
|
|
|
17
|
-
- **Agent-agnostic** —
|
|
16
|
+
- **Agent-agnostic** — runs its own in-process native agent by default, or drives Claude Code, Codex, Gemini CLI, OpenCode, or any ACP-compatible agent
|
|
18
17
|
- **TDD-enforced** — acceptance tests must fail before implementation starts
|
|
19
18
|
- **Loop until done** — verify, retry, escalate, and regression-check automatically
|
|
20
19
|
- **Monorepo-ready** — per-package config and per-story working directories
|
|
@@ -23,6 +22,7 @@ nax is an **orchestrator, not an agent** — it doesn't write code itself. It dr
|
|
|
23
22
|
- **Semantic review** — LLM-based behavioral review against story acceptance criteria; catches stubs, placeholders, and out-of-scope changes
|
|
24
23
|
- **Adversarial review** — LLM-based adversarial code review that probes for input handling, error paths, and abandoned implementations
|
|
25
24
|
- **Context curator** — deterministic post-run analysis that proposes additions/deletions to context.md and rules files, preventing context drift
|
|
25
|
+
- **Guarded agent commands** — agent-authored shell commands run inside an OS sandbox by default, are adjudicated by a per-stage bash approval mode, and can pause for interactive approval that you can remember and later revoke (`nax approvals`)
|
|
26
26
|
|
|
27
27
|
## Install
|
|
28
28
|
|
|
@@ -32,20 +32,23 @@ npm install -g @nathapp/nax
|
|
|
32
32
|
bun install -g @nathapp/nax
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
Requires: Bun 1.3.7+
|
|
35
|
+
Requires: Bun 1.3.7+ (nax runs on the Bun runtime even when installed through npm; CI pins Bun 1.4.0). Git must be initialized.
|
|
36
|
+
|
|
37
|
+
The default `native` agent needs provider credentials — run `nax auth login <provider>` or, for CI, set the provider's environment variable (a stored credential takes precedence).
|
|
36
38
|
|
|
37
39
|
## Quick Start
|
|
38
40
|
|
|
39
41
|
```bash
|
|
40
42
|
cd your-project
|
|
41
43
|
nax init # Create .nax/ structure
|
|
44
|
+
nax setup # Optional: LLM-analyze the repo and write .nax/config.json
|
|
42
45
|
nax features create my-feature # Scaffold a feature
|
|
43
46
|
|
|
44
47
|
# Write your spec, then plan + run
|
|
45
48
|
nax plan -f my-feature --from spec.md
|
|
46
49
|
nax run -f my-feature
|
|
47
50
|
|
|
48
|
-
# Or
|
|
51
|
+
# Or plan and run in one command
|
|
49
52
|
nax run -f my-feature --plan --from spec.md
|
|
50
53
|
```
|
|
51
54
|
|
|
@@ -61,7 +64,7 @@ See [docs/](docs/) for full guides on configuration, test strategies, monorepo s
|
|
|
61
64
|
2. **Acceptance setup** — Generate acceptance tests; assert RED before implementation
|
|
62
65
|
3. **Route** — Classify story complexity and select model tier (fast → balanced → powerful)
|
|
63
66
|
4. **Context** — Gather relevant code, tests, and project standards per story
|
|
64
|
-
5. **Execute** — Run agent session (Claude Code, Codex, Gemini CLI
|
|
67
|
+
5. **Execute** — Run agent session (native in-process agent by default, or an ACP agent such as Claude Code, Codex, Gemini CLI)
|
|
65
68
|
6. **Verify** — Run scoped tests; rectify on failure before escalating
|
|
66
69
|
7. **Review** — Run lint + typecheck + semantic review + adversarial review; autofix before escalating
|
|
67
70
|
8. **Escalate** — On repeated failure, retry with a higher model tier
|
|
@@ -76,17 +79,35 @@ See [docs/](docs/) for full guides on configuration, test strategies, monorepo s
|
|
|
76
79
|
| Command | Description |
|
|
77
80
|
|:--------|:-----------|
|
|
78
81
|
| [`nax init`](docs/guides/cli-reference.md#nax-init) | Initialize nax in your project |
|
|
82
|
+
| `nax setup` | Analyze the repo and generate `.nax/config.json` via LLM |
|
|
79
83
|
| [`nax features create`](docs/guides/cli-reference.md#nax-features-create-name) | Scaffold a new feature directory |
|
|
80
84
|
| [`nax features list`](docs/guides/cli-reference.md#nax-features-list) | List all features and story status |
|
|
81
|
-
|
|
|
82
|
-
| [`nax
|
|
83
|
-
|
|
|
84
|
-
| [`nax
|
|
85
|
+
| `nax features resolve` | Resolve a feature name and its spec source |
|
|
86
|
+
| [`nax plan`](docs/guides/cli-reference.md#nax-plan--f-name---from-spec) | Generate `prd.json` from a spec file (`--decompose <storyId>` splits an existing story) |
|
|
87
|
+
| `nax spec lint` | Check a spec's machine-extracted sections before planning |
|
|
88
|
+
| [`nax run`](docs/guides/cli-reference.md#nax-run--f-name) | Execute the orchestration loop (`--compare` for a multi-agent bake-off, `--schedule` to defer) |
|
|
89
|
+
| `nax resume` | Resume an interrupted run from its checkpoint |
|
|
90
|
+
| [`nax precheck`](docs/guides/cli-reference.md#nax-precheck--f-name) | Validate project readiness |
|
|
91
|
+
| [`nax status`](docs/guides/cli-reference.md#nax-status--f-name) | Show live run progress |
|
|
85
92
|
| [`nax logs`](docs/guides/cli-reference.md#nax-logs) | Stream or query run logs |
|
|
86
|
-
| [`nax
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
| [`nax
|
|
93
|
+
| [`nax runs`](docs/guides/cli-reference.md#nax-runs) | List recorded run metadata (`nax runs show <run-id>`) |
|
|
94
|
+
| `nax replay` | Reconstruct a post-mortem timeline for a previous run |
|
|
95
|
+
| `nax accept` | Override failed acceptance criteria |
|
|
96
|
+
| [`nax unlock`](docs/guides/cli-reference.md#nax-unlock) | Release a stale lock from a crashed nax process |
|
|
97
|
+
| [`nax generate`](docs/guides/cli-reference.md#nax-generate) | Generate agent context files (`CLAUDE.md`, `AGENTS.md`, …) from `.nax/context.md` |
|
|
98
|
+
| [`nax prompts`](docs/guides/cli-reference.md#nax-prompts--f-name) | Assemble or initialize prompts |
|
|
99
|
+
| `nax context` | Inspect context-engine artifacts and feature fragments |
|
|
100
|
+
| `nax rules` | Lint, export, or migrate the canonical rules store (`.nax/rules/`) |
|
|
101
|
+
| `nax detect` | Detect test-file patterns and optionally persist them |
|
|
102
|
+
| [`nax agents`](docs/guides/cli-reference.md#nax-agents) | List available coding agents |
|
|
103
|
+
| `nax auth` | Manage provider credentials for the native agent (`login`, `import`, `list`, `rm`) |
|
|
104
|
+
| [`nax approvals`](docs/guides/cli-reference.md#nax-approvals-list) | List or revoke remembered command approvals (`list`, `rm`) |
|
|
105
|
+
| `nax mcp lock` | Pin configured MCP servers' tool surface to `.nax/mcp-lock.json` |
|
|
106
|
+
| [`nax config`](docs/guides/cli-reference.md#nax-config) | Display the effective merged config (`--explain`, `--diff`); `nax config profile` manages config profiles |
|
|
107
|
+
| [`nax curator`](docs/guides/cli-reference.md#nax-curator-status) | Inspect, commit, or garbage-collect curator proposals |
|
|
108
|
+
| `nax routing calibrate` | Propose complexity→tier mapping adjustments from run history |
|
|
109
|
+
| `nax plugins list` | List installed plugins |
|
|
110
|
+
| `nax migrate` | Move generated content from `.nax/` to the output directory (`~/.nax/<project>/`) |
|
|
90
111
|
|
|
91
112
|
For full flag details, see the [CLI Reference](docs/guides/cli-reference.md).
|
|
92
113
|
|
|
@@ -98,10 +119,24 @@ For full flag details, see the [CLI Reference](docs/guides/cli-reference.md).
|
|
|
98
119
|
|
|
99
120
|
```json
|
|
100
121
|
{
|
|
122
|
+
"agent": {
|
|
123
|
+
"protocol": "hybrid", // "acp" | "native" | "hybrid" — which transports are permitted
|
|
124
|
+
"default": "native" // In-process nax-ai agent; or an ACP agent such as "claude"
|
|
125
|
+
},
|
|
101
126
|
"execution": {
|
|
102
|
-
"maxIterations":
|
|
127
|
+
"maxIterations": 20, // Note: `nax run -m <n>` overrides this only when the flag is passed
|
|
103
128
|
"permissionProfile": "unrestricted", // "unrestricted" | "safe" | "scoped"
|
|
104
|
-
"storyIsolation": "shared"
|
|
129
|
+
"storyIsolation": "shared", // "shared" | "worktree"
|
|
130
|
+
"bashApproval": "raw", // "raw" | "gated" | "escalate" — how agent Bash commands are adjudicated
|
|
131
|
+
"sandbox": {
|
|
132
|
+
"enabled": true, // OS sandbox around agent-authored Bash / Exec commands (on by default)
|
|
133
|
+
"network": { "allowedDomains": ["registry.npmjs.org"] } // Omit for unrestricted, [] for no network
|
|
134
|
+
},
|
|
135
|
+
"commandInterceptor": {
|
|
136
|
+
"provider": "rtk", // Token-reducing proxy for the Git tool
|
|
137
|
+
"enabled": true, // Off by default — opt in per project
|
|
138
|
+
"git": { "verbs": ["log", "diff"] } // Only these subcommands are rewritten
|
|
139
|
+
}
|
|
105
140
|
},
|
|
106
141
|
"tdd": {
|
|
107
142
|
"strategy": "auto" // How to write tests (see Test Strategies)
|
|
@@ -111,44 +146,40 @@ For full flag details, see the [CLI Reference](docs/guides/cli-reference.md).
|
|
|
111
146
|
},
|
|
112
147
|
"quality": {
|
|
113
148
|
"commands": {
|
|
114
|
-
"test": "bun test",
|
|
149
|
+
"test": "bun test", // Root test command
|
|
115
150
|
"lint": "bun lint", // Optional linter
|
|
116
|
-
"typecheck": "bun typecheck"
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
"hooks": {
|
|
120
|
-
"hooks": {
|
|
121
|
-
"on-all-stories-complete": { "command": "npm run build" } // Fire after all stories pass
|
|
151
|
+
"typecheck": "bun typecheck" // Optional type checker
|
|
122
152
|
}
|
|
123
153
|
},
|
|
124
154
|
"mcp": {
|
|
125
155
|
"servers": {
|
|
126
156
|
"codebase-memory": {
|
|
127
|
-
"command": "codebase-memory-mcp",
|
|
128
|
-
"args": [],
|
|
129
|
-
"stages": ["run"],
|
|
130
|
-
"allowedTools": ["search_graph"]
|
|
157
|
+
"command": "codebase-memory-mcp", // stdio MCP server binary (client only)
|
|
158
|
+
"args": [], // Optional server args
|
|
159
|
+
"stages": ["run"], // Attach in these pipeline stages ("*" = all)
|
|
160
|
+
"allowedTools": ["search_graph"] // Optional: subset of locked tools that is grantable
|
|
131
161
|
}
|
|
132
162
|
}
|
|
133
|
-
},
|
|
134
|
-
"execution": {
|
|
135
|
-
"commandInterceptor": {
|
|
136
|
-
"provider": "rtk", // Token-reducing proxy for the Git tool
|
|
137
|
-
"enabled": true, // Off by default — opt in per project
|
|
138
|
-
"git": { "verbs": ["log", "diff"] } // Only these subcommands are rewritten
|
|
139
|
-
}
|
|
140
163
|
}
|
|
141
164
|
}
|
|
142
165
|
```
|
|
143
166
|
|
|
144
|
-
`mcp` attaches external Model Context Protocol (MCP) servers as tool providers — nax is a client only, never an MCP server. The server id is the tool-name namespace: the `codebase-memory` server advertises its tools as `codebase-memory__search_graph`, `codebase-memory__trace_path`, and so on. Before any of those tools are grantable, run `nax mcp lock` at the project root: it connects every enabled server once, pins the advertised tool surface (name + input-schema hash) to `.nax/mcp-lock.json`, and that lockfile is committed like `bun.lock`. `stages` is the attachment control — a server's tools attach only to the listed pipeline stages, and an empty list attaches nowhere. MCP
|
|
167
|
+
`mcp` attaches external Model Context Protocol (MCP) servers as tool providers — nax is a client only, never an MCP server. The server id is the tool-name namespace: the `codebase-memory` server advertises its tools as `codebase-memory__search_graph`, `codebase-memory__trace_path`, and so on. Before any of those tools are grantable, run `nax mcp lock` at the project root: it connects every enabled server once, pins the advertised tool surface (name + input-schema hash) to `.nax/mcp-lock.json`, and that lockfile is committed like `bun.lock`. `stages` is the attachment control — a server's tools attach only to the listed pipeline stages, and an empty list attaches nowhere. MCP tool reach follows the permission profile: `unrestricted` advertises every attached server's tools, `scoped` only what the stage's `Mcp(...)` rules admit, and `safe` none at all. `allowedTools` narrows which locked tools are grantable; omitted means every locked tool is.
|
|
145
168
|
|
|
146
169
|
`execution.commandInterceptor` rewrites the `Git` tool's argv through `rtk` so `log` and `diff` output reaches the model compressed. It is confined to the Git site: user-authored `quality.commands` and `acceptance.command` are never wrapped. It fails open — if the `rtk` binary is missing the call runs as plain git.
|
|
147
170
|
|
|
148
|
-
**Both features are native-agent only.** An ACP agent (`claude`, `codex`, `opencode`, `gemini`) brings its own tools, so nax's `Git` tool is never invoked and no MCP tool is advertised. A project on `"protocol": "acp"` can hold a complete, valid config for both and get zero effect, with no error.
|
|
171
|
+
**Both features are native-agent only.** An ACP agent (`claude`, `codex`, `opencode`, `gemini`) brings its own tools, so nax's `Git` tool is never invoked and no MCP tool is advertised. A project on `"protocol": "acp"` can hold a complete, valid config for both and get zero effect, with no error. The built-in defaults (`agent.protocol: "hybrid"`, `agent.default: "native"`) let both take effect once configured (the interceptor itself is off by default); a config that switches to an acpx agent does not.
|
|
149
172
|
|
|
150
173
|
See [MCP & Command Interception](docs/guides/mcp-and-interception.md) for setup, verification and troubleshooting, and the [Configuration Guide](docs/guides/configuration.md) for the full schema.
|
|
151
174
|
|
|
175
|
+
`execution.bashApproval` decides how an agent's Bash command is adjudicated (ADR-030). The default `raw` is a pass-through — no per-segment grant matching or root containment, only a best-effort screen that refuses a parseable command naming a nax-owned file (`.nax/config.json`, a feature `prd.json`, the queue-control files). `gated` matches each segment against the stage's single `Bash(...)` allow rule, and `escalate` turns a denial the gate could not adjudicate into an interactive approval prompt; under either, a stage without a `Bash(...)` rule never gets the tool, and nax warns about such inert stages at run start. Approvals you choose to remember are kept per project and managed with `nax approvals list` / `nax approvals rm`; `execution.approvalTimeout` (default 600000 ms) bounds how long a prompt waits before denying.
|
|
176
|
+
|
|
177
|
+
`execution.sandbox` wraps agent-authored Bash and `RunCommand` exec commands in an OS sandbox (backend `srt`, **on by default**): writes are confined to the repository root, system temp directories and package-manager caches, credential files are unreadable, and `network.allowedDomains` optionally limits network access. When the sandbox is enabled but unavailable on the machine, `raw` Bash is refused rather than run unsandboxed — switch the stage to `gated`/`escalate` or set `sandbox.enabled: false`. `execution.commandSafety.shadow` optionally attaches a loopback shadow classifier that scores every agent command and records the result without ever deciding anything.
|
|
178
|
+
|
|
179
|
+
These settings govern nax's own `Bash` and `RunCommand` tools, so, like MCP and the interceptor, they take effect for the native agent; an ACP agent runs commands under its own tooling.
|
|
180
|
+
|
|
181
|
+
See [Sandbox & Command Safety](docs/guides/sandbox-and-command-safety.md), [Approvals](docs/guides/approvals.md), [The Bash Tool](docs/guides/bash-tool.md) and [Permissions](docs/guides/permissions.md).
|
|
182
|
+
|
|
152
183
|
---
|
|
153
184
|
|
|
154
185
|
## Key Concepts
|
|
@@ -169,19 +200,19 @@ See [Test Strategies Guide](docs/guides/test-strategies.md) for the full routing
|
|
|
169
200
|
|
|
170
201
|
### Story Decomposition
|
|
171
202
|
|
|
172
|
-
|
|
203
|
+
An oversized story is split into smaller sub-stories with `nax plan -f <feature> --decompose <storyId>` — a plan-time operation, not a mid-run stage. The precheck story-size gate (`precheck.storySizeGate`) flags stories over its thresholds. The parent is marked `decomposed` and the sub-stories, with dependency ordering, are added to the PRD.
|
|
173
204
|
|
|
174
205
|
See [Story Decomposition Guide](docs/guides/decomposition.md).
|
|
175
206
|
|
|
176
207
|
### Regression Gate
|
|
177
208
|
|
|
178
|
-
After all stories pass, nax runs the full test suite once. If it fails, it
|
|
209
|
+
After all stories pass, nax runs the full test suite once. If it fails, nax maps each failing test file back to the story that introduced it and runs a targeted rectification cycle for that story. A suite timeout is accepted as a pass by default (`execution.regressionGate.acceptOnTimeout`). If failures remain, the affected stories are marked `regression-failed`, the run status becomes `failed`, and the `on-final-regression-fail` hook fires.
|
|
179
210
|
|
|
180
211
|
See [Regression Gate Guide](docs/guides/regression-gate.md).
|
|
181
212
|
|
|
182
213
|
### Parallel & Isolated Execution
|
|
183
214
|
|
|
184
|
-
|
|
215
|
+
With `--parallel <n>`, nax runs up to `n` stories whose dependencies are already satisfied at the same time, each in its own git worktree (`0` = auto, based on CPU cores). Both modes run the regression gate once at the end; only sequential runs attribute a regression to a story and rectify it — in parallel mode it is reported for a human.
|
|
185
216
|
|
|
186
217
|
Even in sequential mode, stories can be isolated in per-story git worktrees (`execution.storyIsolation: "worktree"`) to prevent cross-story state leakage.
|
|
187
218
|
|
|
@@ -195,7 +226,7 @@ See [Monorepo Guide](docs/guides/monorepo.md).
|
|
|
195
226
|
|
|
196
227
|
### Hooks
|
|
197
228
|
|
|
198
|
-
Lifecycle hooks fire at key points (`on-start`, `on-story-complete`, `on-all-stories-complete`, `on-complete`, `on-final-regression-fail`, and more). Use them to trigger deployments, send notifications, or integrate with external systems.
|
|
229
|
+
Lifecycle hooks, defined in `.nax/hooks.json` (project) and `~/.nax/hooks.json` (global) — not in `config.json` — fire at key points (`on-start`, `on-story-complete`, `on-all-stories-complete`, `on-complete`, `on-final-regression-fail`, and more). Use them to trigger deployments, send notifications, or integrate with external systems.
|
|
199
230
|
|
|
200
231
|
See [Hooks Guide](docs/guides/hooks.md).
|
|
201
232
|
|
|
@@ -203,21 +234,23 @@ See [Hooks Guide](docs/guides/hooks.md).
|
|
|
203
234
|
|
|
204
235
|
Extensible plugin architecture for prompt optimization, custom routing, code review, and reporting. Plugins live in `.nax/plugins/` (project) or `~/.nax/plugins/` (global). Post-run action plugins (e.g. auto-PR creation) can implement `IPostRunAction` for results-aware post-completion workflows.
|
|
205
236
|
|
|
206
|
-
See [
|
|
237
|
+
See [Plugin System](docs/architecture/subsystems.md#23-plugin-system).
|
|
207
238
|
|
|
208
239
|
---
|
|
209
240
|
|
|
210
241
|
## Agents
|
|
211
242
|
|
|
212
|
-
nax
|
|
243
|
+
The default agent is `native`: nax drives the model in-process over `@nathapp/nax-ai` (no CLI binary), using the built-in `models.native` Anthropic tier map, so it needs Anthropic credentials (`nax auth` or the provider's environment variable) unless you override the map. Every other agent is reached via [ACP](https://github.com/openclaw/acpx) (Agent Client Protocol) — a JSON-RPC protocol that provides persistent sessions, exact token/cost reporting, and multi-turn session continuity.
|
|
213
244
|
|
|
214
245
|
| Agent | Binary | Notes |
|
|
215
246
|
|:------|:-------|:------|
|
|
216
|
-
|
|
|
247
|
+
| Native (nax-ai) | — (in-process) | Default. `agent.default: "native"` |
|
|
248
|
+
| Claude Code | `claude` | Set `agent.default: "claude"` |
|
|
217
249
|
| OpenCode | `opencode` | Set `agent.default: "opencode"` |
|
|
218
250
|
| Codex | `codex` | Set `agent.default: "codex"` |
|
|
219
251
|
| Gemini CLI | `gemini` | Set `agent.default: "gemini"` |
|
|
220
|
-
|
|
|
252
|
+
| Pi Coding Agent | `pi` | Set `agent.default: "pi"` (via the pi-acp bridge) |
|
|
253
|
+
| Aider | `aider` | Known name with no dedicated ACP adapter entry (generic defaults) |
|
|
221
254
|
| Any ACP-compatible | — | See [acpx agent docs](https://github.com/openclaw/acpx#agents) |
|
|
222
255
|
|
|
223
256
|
See [Agents Guide](docs/guides/agents.md) and the [Context Engine Guide](docs/guides/context-engine.md) for agent-portable context configuration.
|
|
@@ -228,10 +261,11 @@ See [Agents Guide](docs/guides/agents.md) and the [Context Engine Guide](docs/gu
|
|
|
228
261
|
|
|
229
262
|
| Problem | Solution |
|
|
230
263
|
|:--------|:---------|
|
|
231
|
-
|
|
|
264
|
+
| Precheck blocks with "Uncommitted changes detected" | Commit or stash your changes — nax's own runtime files are ignored by the check |
|
|
232
265
|
| HOME env warning | Set HOME to an absolute path — nax warns if it contains `~` |
|
|
233
266
|
| ACP sessions leaking | Upgrade to nax v0.48+ and ensure `.nax/acp-sessions.json` is gitignored |
|
|
234
267
|
| Monorepo packages misclassified | Ensure `.nax/mono/packages/<pkg>/config.json` is set up per package |
|
|
268
|
+
| Agent Bash refused with "sandbox unavailable" | The OS sandbox is on by default and `raw` Bash requires it; the message names why the sandbox probe failed (e.g. unsupported platform, or a container where the sandbox cannot enforce). Fix the environment, set the stage's `bashApproval` to `gated`/`escalate`, or set `execution.sandbox.enabled: false` |
|
|
235
269
|
| Acceptance tests regenerating every run | Check `acceptance-meta.json` — stale fingerprints indicate outdated story context |
|
|
236
270
|
|
|
237
271
|
See the [Troubleshooting Guide](docs/guides/troubleshooting.md) for more.
|