Skip to content

Commit 8bf5608

Browse files
authored
chore: import agents.md inside claude.md (#1153)
Signed-off-by: Aleksy Siek <aleksy@alwaysfurther.ai>
1 parent 084638b commit 8bf5608

1 file changed

Lines changed: 2 additions & 203 deletions

File tree

CLAUDE.md

Lines changed: 2 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -1,204 +1,3 @@
1-
# nono - Development Guide
1+
# Project instructions live in AGENTS.md (imported below for Claude Code).
22

3-
## Project Overview
4-
5-
nono is a capability-based sandboxing system for running untrusted AI agents with OS-enforced isolation. It uses Landlock (Linux) and Seatbelt (macOS) to create sandboxes, and then layers on top a policy system, diagnostic tools, and a rollback mechanism for recovery. The library is designed to be a pure sandbox primitive with no built-in policy, while the CLI implements all security policy and UX.
6-
7-
The project is a Cargo workspace with three members:
8-
- **nono** (`crates/nono/`) - Core library. Pure sandbox primitive with no built-in security policy.
9-
- **nono-cli** (`crates/nono-cli/`) - CLI binary. Owns all security policy, profiles, hooks, and UX.
10-
- **nono-ffi** (`bindings/c/`) - C FFI bindings. Exposes the library via `extern "C"` functions and auto-generated `nono.h` header.
11-
- **nono-proxy** - Proxy that provides network filtering and credential injection
12-
13-
### Library vs CLI Boundary
14-
15-
The library is a **pure sandbox primitive**. It applies ONLY what clients explicitly add to `CapabilitySet`:
16-
17-
| In Library | In CLI |
18-
|------------|--------|
19-
| `CapabilitySet` builder | Policy groups (deny rules, dangerous commands, system paths) |
20-
| `Sandbox::apply()` | Group resolver (`policy.rs`) and platform-aware deny handling |
21-
| `SandboxState` | `ExecStrategy` (Direct/Monitor/Supervised) |
22-
| `DiagnosticFormatter` | Profile loading and hooks |
23-
| `QueryContext` | All output and UX |
24-
| `keystore` | `learn` mode |
25-
| `undo` module (ObjectStore, SnapshotManager, MerkleTree, ExclusionFilter) | Rollback lifecycle, exclusion policy, rollback UI |
26-
27-
## Build & Test
28-
29-
After every session, run these commands to verify correctness:
30-
31-
```bash
32-
# Build everything
33-
make build
34-
35-
# Run all tests
36-
make test
37-
38-
# Full CI check (clippy + fmt + tests)
39-
make ci
40-
```
41-
42-
Individual targets:
43-
```bash
44-
make build-lib # Library only
45-
make build-cli # CLI only
46-
make test-lib # Library tests only
47-
make test-cli # CLI tests only
48-
make test-doc # Doc tests only
49-
make clippy # Lint (strict: -D warnings -D clippy::unwrap_used)
50-
make fmt-check # Format check
51-
make fmt # Auto-format
52-
```
53-
54-
## Coding Standards
55-
56-
- **Error Handling**: Use `NonoError` for all errors; propagation via `?` only.
57-
- **Unwrap Policy**: Strictly forbid `.unwrap()` and `.expect()`; enforced by `clippy::unwrap_used`.
58-
- **Libraries should almost never panic**: Panics are for unrecoverable bugs, not expected error conditions. Use `Result` instead.
59-
- **Unsafe Code**: Restrict to FFI; must be wrapped in safe APIs with `// SAFETY:` docs.
60-
- **Path Security**: Validate and canonicalize all paths before applying capabilities.
61-
- **Arithmetic**: Use `checked_`, `saturating_`, or `overflowing_` methods for security-critical math.
62-
- **Memory**: Use the `zeroize` crate for sensitive data (keys/passwords) in memory.
63-
- **Testing**: Write unit tests for all new capability types and sandbox logic.
64-
- **Environment variables in tests**: Tests that modify `HOME`, `TMPDIR`, `XDG_CONFIG_HOME`, or other env vars must save and restore the original value. Rust runs unit tests in parallel within the same process, so an unrestored env var causes flaky failures in unrelated tests (e.g. `config::check_sensitive_path` fails when another test temporarily sets `HOME` to a fake path). Always use save/restore pattern and keep the modified window as short as possible.
65-
- **Attributes**: Apply `#[must_use]` to functions returning critical Results.
66-
- **Lazy use of dead code**: Avoid `#[allow(dead_code)]`. If code is unused, either remove it or write tests that use it.
67-
- **Commits**: All commits must include a DCO sign-off line (`Signed-off-by: Name <email>`).
68-
69-
## Key Design Decisions
70-
71-
1. **No escape hatch**: Once sandbox is applied via `restrict_self()` (Landlock) or `sandbox_init()` (Seatbelt), there is no API to expand permissions.
72-
73-
2. **Fork+wait process model**: nono stays alive as a parent process. On child failure, prints a diagnostic footer to stderr. Three execution strategies: `Direct` (exec, backward compat), `Monitor` (sandbox-then-fork, default), `Supervised` (fork-then-sandbox, for rollbacks/expansion).
74-
75-
3. **Capability resolution**: All paths are canonicalized at grant time to prevent symlink escapes.
76-
77-
4. **Library is policy-free**: The library applies ONLY what's in `CapabilitySet`. No built-in sensitive paths, dangerous commands, or system paths. Clients define all policy.
78-
79-
## Platform-Specific Notes
80-
81-
### macOS (Seatbelt)
82-
- Uses `sandbox_init()` FFI with raw profile strings
83-
- Profile is Scheme-like DSL: `(allow file-read* (subpath "/path"))`
84-
- Network denied by default with `(deny network*)`
85-
86-
### Linux (Landlock)
87-
- Uses landlock crate for safe Rust bindings
88-
- Detects highest available ABI (v1-v5)
89-
- ABI v4+ includes TCP network filtering
90-
- Strictly allow-list: cannot express deny-within-allow. `deny.access`, `deny.unlink`, and `symlink_pairs` are macOS-only. Avoid broad allow groups that cover deny paths.
91-
92-
## Security Considerations
93-
94-
**SECURITY IS NON-NEGOTIABLE.** This is a security-critical codebase. Every change must be evaluated through a security lens first. When in doubt, choose the more restrictive option.
95-
96-
### Core Principles
97-
- **Principle of Least Privilege**: Only grant the minimum necessary capabilities.
98-
- **Defense in Depth**: Combine OS-level sandboxing with application-level checks.
99-
- **Fail Secure**: On any error, deny access. Never silently degrade to a less secure state.
100-
- **Explicit Over Implicit**: Security-relevant behavior must be explicit and auditable.
101-
102-
### Path Handling (CRITICAL)
103-
- Always use path component comparison, not string operations. String `starts_with()` on paths is a vulnerability.
104-
- Canonicalize paths at the enforcement boundary. Be aware of TOCTOU race conditions with symlinks.
105-
- Validate environment variables before use. Never assume `HOME`, `TMPDIR`, etc. are trustworthy.
106-
- Escape and validate all data used in Seatbelt profile generation.
107-
108-
### Permission Scope (CRITICAL)
109-
- Never grant access to entire directories when specific paths suffice.
110-
- Separate read and write permissions explicitly.
111-
- Configuration load failures must be fatal. If security lists fail to load, abort.
112-
113-
### Common Footguns
114-
1. **String comparison for paths**: `path.starts_with("/home")` matches `/homeevil`. Use `Path::starts_with()`.
115-
2. **Silent fallbacks**: `unwrap_or_default()` on security config returns empty permissions = no protection.
116-
3. **Trusting resolved paths**: Symlinks can change between resolution and use.
117-
4. **Platform differences**: macOS `/etc` is a symlink to `/private/etc`. Both must be considered.
118-
5. **Overly broad permissions**: Granting `/tmp` read/write when only `/tmp/specific-file` is needed.
119-
6. **Solving for one architecture**: Linux and macOS have different capabilities and threat models. Design must account for both. Develop abstractions that can be implemented securely on both platforms. Test on both platforms regularly to catch divergences.
120-
121-
## Coding Agent Contribution Policy
122-
123-
These rules are mandatory for any automated or AI-assisted contribution.
124-
125-
### 1. Hard stop conditions
126-
127-
An agent **must not** open or submit a pull request if any of the following are true:
128-
129-
- An issue does not already exist for the proposed change.
130-
- The change does not fully comply with this document and all relevant repository rules.
131-
- The agent is an OpenClaw agent operating as part of a contributor-presence campaign.
132-
133-
If any hard stop condition is met, the agent must **stop immediately** and make no code changes, no pull request, and no contribution attempt beyond explaining why it stopped.
134-
135-
### 2. Required workflow
136-
137-
Before making any code change, the agent must complete this workflow in order:
138-
139-
1. Read this document and all repository contribution, security, and coding-standard documents relevant to the affected area.
140-
2. Search for an existing issue covering the work.
141-
3. If no issue exists, create one before making changes.
142-
4. In the issue discussion, disclose:
143-
- the exact intent of the change
144-
- the planned implementation approach
145-
- any expected risks, tradeoffs, or limitations
146-
5. Wait for project guidance or confirmation if the repository requires maintainer approval before implementation.
147-
6. Only then prepare a change.
148-
149-
### 3. Attribution and license compliance
150-
151-
When referencing, adapting, or extending existing code, the agent must:
152-
153-
- identify the original authors where required by project policy
154-
- link to the relevant files, functions, sections, commits, or discussions
155-
- clearly distinguish:
156-
- existing project code
157-
- adapted logic
158-
- newly written logic
159-
160-
Failure to provide required attribution is a policy violation and may also violate the project license, DCO requirements, or both.
161-
162-
### 4. Pull request requirements
163-
164-
A pull request may be opened only if all of the following are true:
165-
166-
- an issue already exists
167-
- the proposed change matches the issue discussion
168-
- attribution requirements have been satisfied
169-
- the code complies with all mandatory repository rules
170-
- the agent is not prohibited under the hard stop conditions above
171-
172-
The pull request description must include:
173-
174-
- link to the issue
175-
- statement that the contributor is an agent
176-
- summary of the approach taken
177-
- references to relevant files or sections consulted
178-
- explicit confirmation that the contribution complies with repository coding and security requirements
179-
180-
### 6. Special prohibition: OpenClaw contributor-presence campaigns
181-
182-
If the agent is an OpenClaw or Pi Coding agent acting as part of a campaign to build contributor presence, it is strictly prohibited from making any changes to the codebase, opening pull requests, or attempting to contribute.
183-
184-
### 7. Default behavior on uncertainty
185-
186-
If the agent is uncertain whether an action is permitted, compliant, properly attributed, or secure, it must treat that uncertainty as a failure condition and stop.
187-
188-
---
189-
190-
## Agent Compliance Check (required before opening a PR)
191-
192-
The agent must include this checklist in the pull request and truthfully complete it:
193-
194-
- [ ] I am not prohibited from contributing under this policy
195-
- [ ] An issue already exists
196-
- [ ] I described my intent and approach in the issue discussion
197-
- [ ] I reviewed repository coding and security rules for the affected area
198-
- [ ] I provided required attribution for reused or adapted code
199-
- [ ] I did not use forbidden patterns such as unwrap/expect
200-
- [ ] I used NonoError where required
201-
- [ ] I validated and canonicalized all relevant paths
202-
- [ ] This PR matches the approved or disclosed issue scope
203-
204-
If any item cannot be truthfully checked, the agent must not open a pull request. Instead, it must stop and report the issue.
3+
@AGENTS.md

0 commit comments

Comments
 (0)