Skip to content

Commit c313e5b

Browse files
authored
Merge branch 'main' into tool-sandbox
2 parents 7de7144 + 7a7fccd commit c313e5b

8 files changed

Lines changed: 106 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## [0.64.1] - 2026-06-20
4+
5+
### Refactoring
6+
7+
- *(credentials)* Require explicit activation for custom credentials (#1215) ([#1215](https://github.com/always-further/nono/pull/1215))
8+
39
## [0.64.0] - 2026-06-18
410

511
### Bug Fixes

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ From here **fork the config**, tweak it, theme it, make it your own, and share i
4343

4444
## Quickstart
4545

46+
#### curl
47+
48+
```bash
49+
curl -fsSL https://nono.sh/install.sh | sh
50+
```
51+
4652
#### macOS / Linux (Homebrew)
4753
```bash
4854
brew install nono

bindings/c/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ name = "nono_ffi"
1515
crate-type = ["cdylib", "staticlib"]
1616

1717
[dependencies]
18-
nono = { version = "0.64.0", path = "../../crates/nono", default-features = false }
18+
nono = { version = "0.64.1", path = "../../crates/nono", default-features = false }
1919
serde.workspace = true
2020
serde_json.workspace = true
2121

crates/nono-cli/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "nono-cli"
3-
version = "0.64.0"
3+
version = "0.64.1"
44
edition.workspace = true
55
rust-version.workspace = true
66
authors.workspace = true
@@ -41,8 +41,8 @@ system-keyring = ["dep:keyring", "nono/system-keyring", "nono-proxy/system-keyri
4141
test-trust-overrides = []
4242

4343
[dependencies]
44-
nono = { version = "0.64.0", path = "../nono", default-features = false }
45-
nono-proxy = { version = "0.64.0", path = "../nono-proxy", default-features = false }
44+
nono = { version = "0.64.1", path = "../nono", default-features = false }
45+
nono-proxy = { version = "0.64.1", path = "../nono-proxy", default-features = false }
4646
clap = { version = "4", features = ["derive", "env"] }
4747
clap_complete = "4"
4848
colored = "3"

crates/nono-proxy/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "nono-proxy"
3-
version = "0.64.0"
3+
version = "0.64.1"
44
edition.workspace = true
55
rust-version.workspace = true
66
authors.workspace = true
@@ -18,7 +18,7 @@ default = ["system-keyring"]
1818
system-keyring = ["nono/system-keyring"]
1919

2020
[dependencies]
21-
nono = { version = "0.64.0", path = "../nono", default-features = false }
21+
nono = { version = "0.64.1", path = "../nono", default-features = false }
2222
tokio.workspace = true
2323
hyper.workspace = true
2424
hyper-util.workspace = true

crates/nono/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "nono"
3-
version = "0.64.0"
3+
version = "0.64.1"
44
edition.workspace = true
55
rust-version.workspace = true
66
authors.workspace = true

docs/cli/features/profile-authoring.mdx

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,90 @@ Profile files use **JSONC** (JSON with Comments): standard JSON plus `//` line c
3232
For an overview of what profiles are and how they compose with groups, see [Profiles & Groups](/cli/features/profiles-groups).
3333
</Tip>
3434

35+
## How `extends` Works
36+
37+
`extends` lets your profile build on top of an existing one. Instead of writing everything from scratch, you pick a base and only specify what you want to add or change.
38+
39+
```json
40+
{
41+
"extends": "default",
42+
"filesystem": {
43+
"allow": ["/opt/my-tools"]
44+
}
45+
}
46+
```
47+
48+
This profile inherits everything from `default` and adds one extra directory. The base profile is unchanged.
49+
50+
### What happens when profiles are combined
51+
52+
When nono loads a profile that extends a base, it merges the two together. Most fields fall into one of two patterns:
53+
54+
**List fields grow.** Things like allowed paths, denied commands, and security groups are combined — the base list and your list are joined together. Duplicates are removed automatically. You can always *add* to a list, but you cannot remove something a base already includes.
55+
56+
**Single-value fields can be overridden.** Things like `binary`, `allow_gpu`, `workdir`, and all `security.*` settings work differently: if you set them in your profile they replace the base value, and if you leave them out you inherit whatever the base had.
57+
58+
A few fields have their own specific rules:
59+
60+
| Field | How it works |
61+
|-------|----------|
62+
| `network.block` | Sticks once set. If any base sets this to `true`, your profile cannot set it back to `false`. |
63+
| `open_urls` | Your value replaces the base entirely. Leave it out to inherit the base value. |
64+
| `network.credentials` | Leave it out to inherit. Set it to `[]` to explicitly disable inherited credentials. Otherwise your list is combined with the base. |
65+
| `network.network_profile` | Leave it out to inherit. Set it to `null` to explicitly clear the inherited proxy profile. |
66+
| `hooks`, `env_credentials`, `environment.set_vars` | Merged as key-value maps. Your keys win over the base on any conflict. |
67+
68+
### Extending multiple profiles
69+
70+
You can extend more than one profile at once by passing an array:
71+
72+
```json
73+
{ "extends": ["team-base", "python-tools"] }
74+
```
75+
76+
The profiles are merged left-to-right, then your profile is applied on top. So for any single-value field where the bases conflict, the **rightmost** one wins. List fields are always combined from all of them.
77+
78+
```
79+
team-base → python-tools → your profile
80+
(your settings win)
81+
```
82+
83+
### What if two bases share a common ancestor?
84+
85+
If you extend profiles A and B, and both of them extend a common base C, that's fine. List entries from C end up in the final profile once — duplicates are removed automatically. For single-value fields, the same rightmost-wins rule applies: if A and B both set the same field, B's value is what you get (assuming B is listed second in the array).
86+
87+
The one thing to watch out for is if A and B intentionally set the same single-value field to *different* values, because only one can win and it might not be obvious which. If you're unsure what you're actually getting, run `nono profile show my-profile` to see the resolved result.
88+
89+
### The `default` profile is always included
90+
91+
Every profile automatically gets the `default` built-in merged in, even if you don't write `extends` at all. You don't need to add `"extends": "default"` — it's already there.
92+
93+
If you want to remove a group that `default` includes, use `groups.exclude`:
94+
95+
```json
96+
{
97+
"groups": {
98+
"exclude": ["dangerous_commands"]
99+
}
100+
}
101+
```
102+
103+
### Checking what your profile actually resolves to
104+
105+
Inheritance can stack up. Use these commands to see the final result after all merging is done:
106+
107+
```bash
108+
# Show the fully resolved profile
109+
nono profile show my-profile
110+
111+
# See exactly what changed compared to default
112+
nono profile diff default my-profile
113+
```
114+
115+
<Note>
116+
Inheritance chains are capped at 10 levels. If you hit this limit, nono will fail with a `ProfileInheritance` error — that's usually a sign the profile structure needs simplifying.
117+
</Note>
118+
35119
## Generating a Profile
36120

37121
Use `nono profile init` to scaffold a new profile:

0 commit comments

Comments
 (0)