Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 7 additions & 0 deletions .agents/skills/nemoclaw-user-reference/references/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ $ nemoclaw onboard [--non-interactive] [--resume] [--recreate-sandbox] [--from <
> **Warning:** For NemoClaw-managed environments, use `nemoclaw onboard` when you need to create or recreate the OpenShell gateway or sandbox.
> Avoid `openshell self-update`, `npm update -g openshell`, `openshell gateway start --recreate`, or `openshell sandbox create` directly unless you intend to manage OpenShell separately and then rerun `nemoclaw onboard`.

The installer detects existing sandbox sessions before onboarding and prints a warning if any are found.
To make the installer abort instead of continuing, set `NEMOCLAW_SINGLE_SESSION=1`:

```console
$ NEMOCLAW_SINGLE_SESSION=1 curl -fsSL https://www.nvidia.com/nemoclaw.sh | bash
```

The wizard prompts for a provider first, then collects the provider credential if needed.
Supported non-experimental choices include NVIDIA Endpoints, OpenAI, Anthropic, Google Gemini, and compatible OpenAI or Anthropic endpoints.
Credentials are stored in `~/.nemoclaw/credentials.json`. For file permissions, plaintext storage behavior, and hardening guidance, see Credential Storage (see the `nemoclaw-user-configure-security` skill).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ The baseline policy is always applied regardless of the selected tier.
| Balanced (default) | npm, pypi, huggingface, brew, brave | Full dev tooling and web search. No messaging platform access. |
| Open | npm, pypi, huggingface, brew, brave, slack, discord, telegram, jira, outlook | Broad access across third-party services including messaging and productivity. |

> **Note:** The `weather` preset (`wttr.in`, `api.open-meteo.com`, `geocoding-api.open-meteo.com`) is not included in any default tier because most agent workflows do not require it. Apply it manually if you use the built-in weather skill: `nemoclaw <sandbox> policy-add weather`. See [#1417](https://github.com/NVIDIA/NemoClaw/issues/1417).

After selecting a tier, a combined preset and access-mode screen lets you include or exclude individual presets and toggle each between read (GET only) and read-write (GET + POST/PUT/PATCH) access.
Tier-default presets are pre-selected; additional presets can be added from the full list.

Expand Down
2 changes: 2 additions & 0 deletions docs/reference/network-policies.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ The baseline policy is always applied regardless of the selected tier.
| Balanced (default) | npm, pypi, huggingface, brew, brave | Full dev tooling and web search. No messaging platform access. |
| Open | npm, pypi, huggingface, brew, brave, slack, discord, telegram, jira, outlook | Broad access across third-party services including messaging and productivity. |

> **Note:** The `weather` preset (`wttr.in`, `api.open-meteo.com`, `geocoding-api.open-meteo.com`) is not included in any default tier because most agent workflows do not require it. Apply it manually if you use the built-in weather skill: `nemoclaw <sandbox> policy-add weather`. See [#1417](https://github.com/NVIDIA/NemoClaw/issues/1417).
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

After selecting a tier, a combined preset and access-mode screen lets you include or exclude individual presets and toggle each between read (GET only) and read-write (GET + POST/PUT/PATCH) access.
Tier-default presets are pre-selected; additional presets can be added from the full list.

Expand Down
35 changes: 35 additions & 0 deletions nemoclaw-blueprint/policies/presets/weather.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

preset:
name: weather
description: "Weather data via wttr.in and Open-Meteo — required for the built-in weather skill"

network_policies:
weather:
name: weather
endpoints:
# wttr.in — primary weather source used by the weather skill (web_fetch)
- host: wttr.in
port: 443
protocol: rest
enforcement: enforce
rules:
- allow: { method: GET, path: "/**" }
# Open-Meteo — free weather API (no key required), used as fallback
- host: api.open-meteo.com
port: 443
protocol: rest
enforcement: enforce
rules:
- allow: { method: GET, path: "/**" }
# Open-Meteo geocoding — required to resolve city names to coordinates
- host: geocoding-api.open-meteo.com
port: 443
protocol: rest
enforcement: enforce
rules:
- allow: { method: GET, path: "/**" }
binaries:
- { path: /usr/local/bin/node }
- { path: /usr/local/bin/openclaw }
43 changes: 43 additions & 0 deletions test/validate-blueprint.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,3 +341,46 @@ describe("huggingface preset", () => {
}
});
});

describe("weather preset", () => {
// The weather skill requires wttr.in and Open-Meteo to be reachable.
// Regression test to ensure the preset file exists and covers the required hosts.
// See: https://github.com/NVIDIA/NemoClaw/issues/1417
const WEATHER_PRESET_PATH = new URL(
"../nemoclaw-blueprint/policies/presets/weather.yaml",
import.meta.url,
);

const weatherPreset = YAML.parse(
readFileSync(WEATHER_PRESET_PATH, "utf-8"),
) as Record<string, unknown>;

type Endpoint = { host?: string; rules?: Array<{ allow?: { method?: string } }> };

function weatherEndpoints(): Endpoint[] {
const np = weatherPreset.network_policies as Record<string, unknown> | undefined;
if (!np) return [];
const w = np.weather as { endpoints?: unknown } | undefined;
return Array.isArray(w?.endpoints) ? (w!.endpoints as Endpoint[]) : [];
}

it("regression #1417: weather preset covers wttr.in", () => {
const hosts = weatherEndpoints().map((ep) => ep.host);
expect(hosts).toContain("wttr.in");
});

it("regression #1417: weather preset covers api.open-meteo.com", () => {
const hosts = weatherEndpoints().map((ep) => ep.host);
expect(hosts).toContain("api.open-meteo.com");
});

Copilot AI Apr 15, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regression tests for the weather preset assert wttr.in and api.open-meteo.com, but do not assert geocoding-api.open-meteo.com even though the preset includes it and the PR description calls it required for city-name lookups. Add an assertion for the geocoding host so a future removal/rename doesn’t silently break the weather skill while tests still pass.

Suggested change
it("regression #1417: weather preset covers geocoding-api.open-meteo.com", () => {
const hosts = weatherEndpoints().map((ep) => ep.host);
expect(hosts).toContain("geocoding-api.open-meteo.com");
});

Copilot uses AI. Check for mistakes.
it("regression #1417: weather endpoints allow GET requests", () => {
for (const ep of weatherEndpoints()) {
const rules = Array.isArray(ep.rules) ? ep.rules : [];
const hasGet = rules.some(
(r) => r?.allow?.method?.toUpperCase() === "GET",
);
expect(hasGet).toBe(true);
}
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.
});
Loading