Skip to main content
The nono policy command lets you inspect the group-based security policy, explore profiles, compare configurations, and validate user-defined profiles. Every subcommand supports --json for programmatic consumption.

Commands

nono policy groups

List all policy groups or show details for a specific group.
# List groups for the current platform
nono policy groups

# List groups for all platforms
nono policy groups --all-platforms

# Show details for a specific group
nono policy groups deny_credentials

# Machine-readable output
nono policy groups --json
Example output:
nono policy: 21 groups

  claude_code_macos                    Claude Code macOS-specific state and credential paths macos
  deny_credentials                     Block access to cryptographic keys, tokens, and cloud credentials cross-platform  required
  deny_shell_history                   Block access to shell command history files cross-platform  required
  node_runtime                         Node.js runtime and package manager paths  cross-platform
  system_read_macos                    macOS system paths required for executables to function macos
  ...
Detailed view shows every path in the group, with variables expanded to their actual values:
nono policy: group 'deny_credentials'

  Description:  Block access to cryptographic keys, tokens, and cloud credentials
  Platform:     cross-platform
  Required:     yes

  deny.access:
    ~/.ssh                               -> /Users/luke/.ssh
    ~/.aws                               -> /Users/luke/.aws
    ~/.config/gcloud                     -> /Users/luke/.config/gcloud
    ~/.docker                            -> /Users/luke/.docker
    ~/.git-credentials                   -> /Users/luke/.git-credentials
    ...

Options

OptionDescription
[NAME]Group name to show details for (omit to list all)
--jsonOutput as JSON
--all-platformsShow groups for all platforms, not just the current one

nono policy profiles

List all available profiles, showing built-in and user-defined profiles separately. User profiles that shadow a built-in name are flagged.
nono policy profiles
nono policy profiles --json
Example output:
nono policy: 15 profiles

  Built-in:
    claude-code      Anthropic Claude Code CLI agent            extends default
    codex            OpenAI Codex CLI agent                     extends default
    default          Default conservative base profile
    opencode         OpenCode AI coding assistant               extends default
    python-dev       Python SDK development profile             extends default
    ...

  User (~/.config/nono/profiles/):
    my-agent         Custom agent profile                       extends default
    ...
Malformed user profiles are surfaced with their error instead of being silently hidden:
  User (~/.config/nono/profiles/):
    broken-profile   [error: Profile error: missing field `meta`]
Load precedence is user-first. If a user profile file exists at ~/.config/nono/profiles/claude-code.json, it shadows the built-in claude-code profile. The profiles command reports the actual source: "user (overrides built-in)" in JSON output, and lists the profile under the User section.

Options

OptionDescription
--jsonOutput as JSON

nono policy show

Display a fully resolved profile, including all inherited groups, filesystem grants, network configuration, hooks, and rollback settings.
# Show a built-in profile
nono policy show default

# Show a user profile
nono policy show my-agent

# Show a profile by file path
nono policy show ./profiles/custom.json

# Show raw paths (before variable expansion)
nono policy show claude-code --raw

# Machine-readable output
nono policy show claude-code --json
Example output:
nono policy: profile 'claude-code'

  Description:  Anthropic Claude Code CLI agent
  Extends:      default

  Security groups:
    deny_credentials
    deny_keychains_macos
    node_runtime
    python_runtime
    rust_runtime
    unlink_protection
    ...

  Filesystem:
    allow (r+w):
      $HOME/.claude                        -> /Users/luke/.claude
    read_file:
      $HOME/.gitconfig                     -> /Users/luke/.gitconfig

  Workdir access:  ReadWrite

  Rollback exclusions:
    node_modules
    target
    __pycache__
    glob: *.tmp.[0-9]*.[0-9]*

  Open URLs:
    localhost allowed
    https://claude.ai
The --raw flag shows path variables as written in the profile (e.g., $HOME/.claude) rather than their expanded values. This is useful for understanding what a profile declares versus what it resolves to on a specific machine.

Options

OptionDescription
<PROFILE>Profile name or file path
--jsonOutput as JSON
--rawShow raw paths before variable expansion

nono policy diff

Compare two profiles side-by-side. Shows additions, removals, and changes across all profile sections: groups, filesystem, policy patches, security settings, network, hooks, rollback, open URLs, env credentials, and custom credentials.
# Compare two built-in profiles
nono policy diff default claude-code

# Compare a user profile against a built-in
nono policy diff default ./my-profile.json

# Machine-readable output
nono policy diff default claude-code --json
Example output:
nono policy: diff 'default' vs 'claude-code'

  Groups:
    + claude_code_macos
    + node_runtime
    + python_runtime
    + rust_runtime
    + unlink_protection
    + user_caches_macos

  Filesystem:
    + allow $HOME/.claude
    + read_file $HOME/.gitconfig
    + read_file $HOME/.gitignore_global

  Workdir:
    - access: None
    + access: ReadWrite

  Open URLs:
    + allow_origins https://claude.ai
    - allow_localhost: false
    + allow_localhost: true

  Hooks:
    + claude-code
For custom credentials and hooks, the diff detects value-level changes when two profiles share the same key but differ in configuration (e.g., different upstream URL or inject_mode):
  Custom credentials:
    ~ my-api (changed)
      - upstream: https://old-api.example.com
      + upstream: https://new-api.example.com
When profiles are identical, the output shows (no differences).

Options

OptionDescription
<PROFILE1>First profile name or path
<PROFILE2>Second profile name or path
--jsonOutput as JSON

nono policy validate

Validate a user profile JSON file against the embedded policy. Catches common mistakes before they cause runtime failures.
nono policy validate ~/my-profile.json
nono policy validate ./profiles/custom.json --json
Checks performed:
CheckSeverityDescription
JSON syntaxErrorFile must be valid JSON and deserialize into a profile
InheritanceErrorextends target must be a loadable profile
Group referencesErrorEvery group in security.groups must exist in policy.json
Required group exclusionErrorpolicy.exclude_groups cannot exclude required groups
Empty pathsWarningEmpty strings in filesystem path arrays
Example output for a valid profile:
nono policy: validating /Users/luke/my-profile.json

  [ok]  JSON syntax valid
  [ok]  All 3 group references valid

  Result: valid
Example output for an invalid profile:
nono policy: validating /Users/luke/bad-profile.json

  [ok]  JSON syntax valid
  [err]  Group 'nonexistent_group' not found in policy.json

  Result: invalid (1 error)
The command exits with a non-zero status when validation fails, making it suitable for CI pipelines.

Options

OptionDescription
<FILE>Profile JSON file to validate
--jsonOutput as JSON

JSON Output

All subcommands support --json for integration with scripts, CI pipelines, and tools like jq.
# List groups and extract names
nono policy groups --json | jq '.[].name'

# Check if a profile has network blocked
nono policy show my-profile --json | jq '.network.block'

# Get added groups between two profiles
nono policy diff default claude-code --json | jq '.groups.added'

# Validate in CI and check result
nono policy validate ./profile.json --json | jq '.valid'

Use Cases

Auditing security posture

Review exactly what a profile grants before deploying it:
# What does this profile actually allow?
nono policy show claude-code

# What groups protect sensitive data?
nono policy groups deny_credentials

# How does our custom profile differ from the built-in?
nono policy diff claude-code ./our-custom-profile.json

Debugging sandbox failures

When a sandboxed process fails because a path is blocked, trace the policy:
# What groups apply to the current platform?
nono policy groups

# Does the profile include the needed runtime group?
nono policy show my-profile | grep python_runtime

# Compare against a working profile
nono policy diff my-profile claude-code

CI/CD validation

Validate custom profiles before they ship:
# Validate all profile files in a directory
for f in profiles/*.json; do
  nono policy validate "$f" --json || exit 1
done

Detecting user overrides

Check whether built-in profiles have been shadowed by user files:
# JSON output flags the actual source
nono policy profiles --json | jq '.[] | select(.source | contains("overrides"))'