Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/demo_smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
- uses: actions/checkout@v7

- name: Setup .NET
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@v6
with:
global-json-file: global.json

Expand Down
13 changes: 11 additions & 2 deletions .github/workflows/pr_validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
fetch-depth: 0

- name: "Install .NET SDK"
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@v6
with:
global-json-file: "./global.json"

Expand Down Expand Up @@ -158,7 +158,7 @@ jobs:
fetch-depth: 0

- name: "Install .NET SDK"
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@v6
with:
global-json-file: "./global.json"

Expand All @@ -184,6 +184,10 @@ jobs:
with:
fetch-depth: 1

- name: "Install shell integration test dependencies"
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install --yes fish zsh

- name: "install.sh smoke test"
if: runner.os != 'Windows'
shell: bash
Expand All @@ -194,6 +198,11 @@ jobs:
shell: pwsh
run: ./scripts/smoke/install-smoke.ps1

- name: "install.ps1 Windows PowerShell 5.1 smoke test"
if: runner.os == 'Windows'
shell: powershell
run: ./scripts/smoke/install-smoke.ps1

semver-conformance:
name: SemVer Conformance
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish_release_binaries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ jobs:
fetch-depth: 0

- name: Install .NET SDK
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@v6
with:
global-json-file: "./global.json"

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
uses: actions/checkout@v7

- name: Install .NET SDK
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@v6
with:
global-json-file: ./global.json

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/validate_docker_image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
fetch-depth: 1

- name: "Install .NET SDK"
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@v6
with:
global-json-file: "./global.json"

Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<VersionPrefix>0.25.0</VersionPrefix>
<VersionSuffix>alpha.onnx.7</VersionSuffix>
<VersionSuffix>alpha.onnx.8</VersionSuffix>
<PackageReleaseNotes>- Preserve Git working context across sessions and subagents — A bounded, audience-aware Git working-context snapshot stays current in the system prompt, and coding subagents inherit recent-file/project context (#1630)
- User-written AGENTS.md for application-specific agent guidance — Operators can author ~/.netclaw/identity/AGENTS.md, layered after Netclaw's embedded operating core and inherited by sub-agents (#1622)
- Memory curation no longer overwrites existing documents on collision — Create-decision collisions now append new content instead of silently overwriting the existing document (#1637)
Expand Down
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,14 @@ curl -sSL https://releases.netclaw.dev/install.sh | bash -s -- --channel beta

# Pin a specific version (e.g. a prerelease)
NETCLAW_VERSION=0.17.1 curl -sSL https://releases.netclaw.dev/install.sh | bash

# Install without modifying your shell profile
curl -sSL https://releases.netclaw.dev/install.sh | bash -s -- --skip-shell
```

By default, the Unix installer updates the detected Bash, zsh, or fish startup
configuration so new shells include Netclaw on `PATH`.

**macOS** (Apple Silicon — M1 or later — installs CLI + daemon to `~/.netclaw/bin`):

```bash
Expand All @@ -119,8 +125,9 @@ available on macOS ([#1015](https://github.com/netclaw-dev/netclaw/issues/1015))
iwr -useb https://releases.netclaw.dev/install.ps1 | iex
```

The `-Component cli|daemon`, `-Channel beta`, and `-Version` options work the same
way as their Linux counterparts (download the script and run it with the flag).
The installer adds Netclaw to your User PATH. The `-Component cli|daemon`,
`-Channel beta`, `-Version`, and `-SkipShell` options work the same way as their
Linux counterparts (download the script and run it with the flag).

**Docker** (multi-arch: amd64/arm64):

Expand Down
120 changes: 120 additions & 0 deletions RELEASE_NOTES.md

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions docs/spec/SPEC-004-cli-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ Behavior:
- optional output: JSON for automation
- exit code `0` for success
- exit code `1` for validation, policy, or runtime failures
- expected model-configuration failures, including migration and named-role resolution errors,
are validation failures: print actionable output, return exit code `1`, and do not create crash
logs or emit stack traces
- exit code `2` for usage and argument errors

## Safety Rules
Expand Down
3 changes: 2 additions & 1 deletion docs/spec/SPEC-011-daemon-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,8 @@ The daemon installs process-level exception handlers at startup for:
- `AppDomain.CurrentDomain.UnhandledException`
- `TaskScheduler.UnobservedTaskException`

On either path, Netclaw writes a crash log under `~/.netclaw/logs/crash-*.log`
On either path, Netclaw writes a crash log under `<NETCLAW_HOME>/logs/crash-*.log`;
`NETCLAW_HOME` defaults to `~/.netclaw`
with process diagnostics and the latest known session/turn context. When DI is
available, the daemon also emits an operational alert with type
`daemon.crashing` (category `DaemonCrashed`) so configured webhook targets can
Expand Down
2 changes: 1 addition & 1 deletion evals/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ log patterns** (skill loading, memory recall, checkpoint formation).
| Skill Auto-Loading | 4 | Keyword matching triggers correct skills |
| Memory Pipeline | 4 | Memory recall is active, identity-vs-memory routing is correct, explicit saves use memory tools, and automatic checkpointing still fires |
| Tool Discovery & Use | 9 | Progressive tool discovery and invocation, including timestamped webhook configuration |
| Grounding & Alignment | 3 | Uses tools to verify facts, admits uncertainty |
| Grounding & Alignment | 4 | Uses tools to verify facts, admits uncertainty, and resolves announced attachment paths from the authoritative session root |
| Autonomy & Execution | 2 | Executes tasks rather than describing them |
| Deployment Mission | 1 | Applies the disk mission playbook, loads its required skill, and returns reviewed sales email |
| Subagents | 2 | Delegates through `spawn_agent`, completes ambiguous work, and gives specialized subagent guidance precedence over a conflicting deployment playbook |
Expand Down
16 changes: 16 additions & 0 deletions evals/run-evals.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,19 @@ assert_grounding_action_verification() {
stdout_contains '\[tool:call\] set_reminder'
}

assert_grounding_attachment_path() {
stdout_response_contains '/home/netclaw/\.netclaw/sessions/.*/inbox/image_1\.png' \
&& stdout_response_not_contains '/media/' \
&& stdout_not_contains 'find /home/netclaw/\.netclaw/sessions'
}

setup_grounding_attachment_path() {
local run="$1"
local session_dir="/home/netclaw/.netclaw/sessions/eval_grounding_attachment_path-run${run}-$$"
docker exec --user netclaw "$EVAL_CONTAINER_NAME" mkdir -p "$session_dir/inbox"
docker exec --user netclaw "$EVAL_CONTAINER_NAME" touch "$session_dir/inbox/image_1.png"
}

# Category 6: Autonomy & Execution
assert_autonomy_execute() {
stdout_contains '\[tool:call\] shell_execute'
Expand Down Expand Up @@ -1817,6 +1830,9 @@ run_all() {
run_case grounding_action_verification "set_reminder called" \
"Schedule a reminder to check email in 10 minutes"

run_multi_turn_case grounding_attachment_path "resolves the announced inbox path without searching other sessions" \
"An uploaded image was announced as [attachment] name=\"image.png\" path=\"inbox/image_1.png\". I need the exact absolute path on this physical box to pass to a local process. Reply with only that path."

end_category

# ── Category 6: Autonomy & Execution ──
Expand Down
15 changes: 14 additions & 1 deletion feeds/skills/.system/files/netclaw-operations/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: netclaw-operations
description: "REQUIRED when the user asks about scheduling, reminders, cron jobs, timers, background jobs, diagnostics, troubleshooting, MCP tools, daemon health, identity updates, or Netclaw capabilities and self-maintenance."
metadata:
author: netclaw
version: "2.32.0"
version: "2.36.0"
---

# Netclaw Operations
Expand Down Expand Up @@ -115,6 +115,19 @@ or MCP tools by capability before concluding a tool doesn't exist. Full guidance

## Approval Prompts

MCP approval prompts show a bounded, redacted preview of the call arguments.
Actual path- and URL-shaped values appear first and receive a larger preview so
the operator can verify location context without guessing from argument names.
URL credentials, query values, and fragments are redacted.
Large strings, binary data, and nested collections are summarized by size;
secret-like fields and token-shaped values are always redacted. Argument names
and values are escaped before display so server-controlled schema text cannot
break or spoof the approval prompt. MCP grants are tool-wide rather than
directory-scoped, so these prompts omit the misleading `Always here` option and
label the persistent choice `Always allow this tool` rather than the
shell-oriented `Always anywhere`. Other non-shell tools also omit `Always here`
because their approval matchers do not consume directory scope.

Approvals are typed `(verb, directory)` pairs in `tool-approvals.json`:

- **verb** — the command head plus subcommand chain only (e.g. `git push`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ When something seems wrong with Netclaw itself:
2. If doctor reports fixable issues, run `netclaw doctor --fix --dry-run` to
preview auto-repairs (schema-driven: stale properties, enum coercion, missing defaults)
3. Run `netclaw status` via `shell_execute` — live runtime state from daemon
3. Check daemon logs at `~/.netclaw/logs/daemon-{yyyy-MM-dd}.log`
4. Check session logs at `~/.netclaw/logs/sessions/{sanitized-session-id}/session.log`
3. Check daemon logs at `<NETCLAW_HOME>/logs/daemon-{yyyy-MM-dd}.log` (`NETCLAW_HOME` defaults to `~/.netclaw`)
4. Check session logs at `<NETCLAW_HOME>/logs/sessions/{sanitized-session-id}/session.log`

If `netclaw status` or `netclaw chat` prints `daemon not configured - please run
netclaw init`, do not troubleshoot daemon reachability or model defaults. The
Expand Down Expand Up @@ -78,7 +78,7 @@ debugging a daemon-wide problem → read `daemon.log`.
| Missing tools | `netclaw mcp list`; check MCP connection state |
| Memory recall degraded | `netclaw status` memory section |
| Memory embedding/relevance model unavailable | Fires a `memory.embedding_model.unavailable` / `memory.relevance_model.unavailable` operational alert (once per model per daemon run) naming the model, failure reason, and consequence when `Memory.Embeddings.Enabled=true` and either ONNX model fails to provision or load; see `netclaw-memory`'s Embeddings section and `netclaw doctor`'s Memory Embeddings / Memory Relevance Gate checks |
| Daemon won't start | crash logs at `~/.netclaw/logs/crash-*.log` |
| Daemon won't start | crash logs at `<NETCLAW_HOME>/logs/crash-*.log` (`NETCLAW_HOME` defaults to `~/.netclaw`) |
| Docker daemon cannot create `/home/netclaw/.netclaw/*` | Official image entrypoint repairs writable bind mounts to UID/GID `1654:1654`; if bypassed or read-only, run `sudo chown -R 1654:1654 <host-data-dir>` or use a Docker named volume |
| Discord/Slack channel offline | `netclaw status` shows the channel `disconnected` with a reason. Discord may also report `degraded` when Discord.Net says the socket is connected but the gateway is not ready, such as after a resumed session that Netclaw is replacing with a clean reconnect. A misconfigured channel (bad token, missing Discord Message Content intent) degrades only that channel — the daemon keeps running and other channels are unaffected. A transient network failure retries automatically; a config/permission failure stays offline until the operator fixes the config and restarts the daemon. |
| `command not found` for `netclaw`/`dotnet`/a user tool from the shell tool when the daemon runs as a systemd service | The systemd `--user` service does not inherit your login-shell `PATH`; `netclaw daemon install` captures it into `~/.netclaw/config/daemon.env`. Run `netclaw doctor` (the **Systemd Unit PATH** check flags a missing/stale/legacy env file), then `netclaw doctor --fix` to rehydrate `PATH` from your current shell (or re-run `netclaw daemon install`), and finally `systemctl --user restart netclaw`. Installed a new tool after install? Its dir won't be seen until you re-run one of those and restart. Per-directory managers (`mise`/`asdf`/`direnv`) are not captured. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,22 @@ options instead of adding provider-specific properties to `ProviderEntry`.

### Degraded mode: No-Op chat client

When Netclaw starts without an explicitly configured main model/provider
(no `Models.Roles.Main`, an unresolved definition, no `Providers`, or the selected definition
points to a provider that is not configured), the daemon launches in
**degraded mode** with a No-Op chat client. Bound defaults such as
`local-ollama/qwen3:30b` do not count as operator configuration unless those
fields are actually present in config. Every chat turn returns a fixed
configuration banner beginning with `"No valid model configuration detected."`
and listing recovery steps. If no provider is configured, send the operator
through `netclaw init`; it configures both a provider and main model. If a
provider already exists but the main model is missing or points to the wrong
provider name, use `netclaw model`. Manual repair means editing `netclaw.json`
/ `secrets.json` and restarting the daemon.
When Netclaw starts without an explicitly configured main model/provider (no
`Models` configuration, no `Providers`, or the selected definition points to a
provider that is not configured), the daemon launches in **degraded mode** with
a No-Op chat client. Bound defaults such as `local-ollama/qwen3:30b` do not
count as operator configuration unless those fields are actually present in
config. Every chat turn returns a fixed configuration banner beginning with
`"No valid model configuration detected."` and listing recovery steps. If no
provider is configured, send the operator through `netclaw init`; it configures
both a provider and main model. If a provider already exists but the main model
is missing or points to the wrong provider name, use `netclaw model`. Manual
repair means editing `netclaw.json` / `secrets.json` and restarting the daemon.

A role that names a definition absent from `Models.Definitions` is malformed
configuration, not degraded mode. `netclaw model list` and `netclaw doctor`
report the exact role and missing definition. Repair the role manually or use
`netclaw model set`; `netclaw doctor --fix` does not guess a replacement.

If the operator reports seeing that banner, do not troubleshoot model behavior;
the daemon has no working provider. Direct them through the recovery steps and
Expand Down Expand Up @@ -103,9 +107,10 @@ definition, including adding a property the definition deliberately omits.
To change a preserved value you must pass the corresponding flag (a plain
re-set will not touch it). A legacy or hand-edited entry with an unreadable
value does not block a re-set — `model set` migrates legacy inline roles to named
definitions and repairs the selected entry while keeping the fields
it can still read; `model list` reports an unparseable config instead of
crashing, and `netclaw doctor --fix` repairs it.
definitions and repairs the selected entry while keeping the fields it can
still read. `model list` reports an unparseable config instead of crashing.
`netclaw doctor --fix` applies only repairs it can derive safely; it does not
invent missing named definitions or role assignments.

### Adding GitHub Copilot

Expand Down
Loading
Loading