CLI Reference

The ash command-line interface is the primary way to interact with Ash. This reference covers all commands and options.

Command Overview

ash --help
  run, r       Run a command in a sandboxed session
  observe, o   Run a command in an observation session
  test, t      Test an action against a policy
  check, c     Validate policy correctness
  lint, l      Find and fix common policy issues
  init         Initialize a new policy file
  add          Add dependencies to a policy
  remove       Remove dependencies from a policy
  format       Format a policy file
  expand       Generate an expanded version of the policy
  update       Update policy dependencies
  outdated     Find outdated policy dependencies
  search       Search for a policy in the registry
  info         Display information about a registry policy
  publish      Upload a policy to the registry
  yank         Remove a published policy from the registry index
  auth         Authentication commands
  ping         Test connection to the daemon
  status       Get system status and health info
  logs         View ash audit logs
  telemetry    Get or set anonymous telemetry status
  restart-ne   Restart the Network Extension and show logs
  uninstall-ne Uninstall the Network Extension

ash run

Run a command in a sandboxed session.

USAGE: ash run [OPTIONS] -- <command>

ARGUMENTS:
  <command>              Command(s) to run

OPTIONS:
  --policy <policy>      Path to YAML policy file (default: .ash/policy.yml)
  --terminal-prompts     Use terminal prompts for policy decisions instead of GUI notifications
  --no-pty               Disable PTY allocation (use standard I/O)
  --verbose              Enable verbose output (session info, warnings)
  --id <id>              Custom session ID for debugging

If a process in the session attempts an action that is not explicitly covered by the policy, it is denied. The first denial triggers a user notification. If the user clicks on that notification, they can choose to set a session-scoped rule or permanently modify the policy.

Examples:

# Run with default policy (.ash/policy.yml)
ash run -- claude

# Run with specific policy
ash run --policy my-policy.yml -- npm start

# Run with verbose output
ash run --verbose -- ./my-script.sh

# Use terminal prompts instead of GUI notifications
ash run --terminal-prompts -- aider

ash observe

Run a command in observation mode to build up a policy. Observation is allow by default: all actions are allowed unless explicitly denied. Whenever an unknown action is observed, Ash adds it to the policy file.

USAGE: ash observe [OPTIONS] -- <command>

ARGUMENTS:
  <command>              Command(s) to run

OPTIONS:
  --policy <policy>      Path to YAML policy file (default: .ash/policy.yml)
  --overwrite-denied     Allow actions that are explicitly denied in the policy
  --no-pty               Disable PTY allocation (use standard I/O)
  --verbose              Enable verbose output (session info, warnings)
  --id <id>              Custom session ID for debugging

The purpose of the observe command is to automatically build a policy based on typical agent behavior; once the policy is built, switch to run for safe use.

Examples:

# Allow unknown actions and add them to the policy
ash observe -- ./unknown-script.sh

# Add previously denied actions to the policy
ash observe --overwrite-denied -- npm install

ash test

Test an action against a policy without running a command.

ash test --help
  file          Test a filesystem action
  network       Test a network action
  exec          Test an exec action
  io_device     Test an IO device action
  environment   Test whether an ENV variable is allowed

Exit codes:

  • 0 - Test completed successfully (result is allow, deny, or unknown)
  • 1 - Error (invalid policy, missing file, invalid arguments)

ash test file

Test a file action.

USAGE: ash test file [--policy <policy>] <operation> <path>

ARGUMENTS:
  <operation>            File operation: create, delete, read, write, rename
  <path>                 Path to test

OPTIONS:
  --policy <policy>      Path to policy file (default: .ash/policy.yml or session policy)

Examples:

ash test file read /etc/passwd
# Output: deny

ash test file write ~/project/src/main.rs
# Output: allow

ash test file --policy strict.yml delete /tmp/cache
# Output: allow

ash test network

Test a network action.

USAGE: ash test network [OPTIONS] <host>[:<port>]

ARGUMENTS:
  <host>[:<port>]        Hostname or IP address, with optional port (default: 443)

OPTIONS:
  --policy <policy>      Path to policy file (default: .ash/policy.yml or session policy)
  --direction <dir>      Connection direction: inbound, outbound (default: outbound)
  --transport <proto>    Transport protocol: tcp, udp (default: tcp)

Examples:

ash test network api.good.bot:443 # => allow
ash test network --direction outbound evil.com:80 # => deny
ash test network 192.168.1.1 # => unknown

ash test exec

Test an exec action.

USAGE: ash test exec [--policy <policy>] <command>

ARGUMENTS:
  <command>              The CLI command to evaluate, with subcommands and args

OPTIONS:
  --policy <policy>      Path to policy file (default: .ash/policy.yml or session policy)

Examples:

ash test exec git push origin main
# Output: allow

ash test exec rm -rf /
# Output: deny

ash test exec /usr/bin/python3 script.py
# Output: allow

ash test io_device

Test an IO device action.

USAGE: ash test io_device [--policy <policy>] <device>

ARGUMENTS:
  <device>               The device name to access

OPTIONS:
  --policy <policy>      Path to policy file (default: .ash/policy.yml or session policy)

Examples:

ash test io_device microphone
# Output: deny

ash test io_device camera
# Output: allow

ash test environment

Test whether an environment variable is passed into the session.

USAGE: ash test environment [--policy <policy>] <variable>

ARGUMENTS:
  <variable>             The environment variable name

OPTIONS:
  --policy <policy>      Path to policy file (default: .ash/policy.yml or session policy)

Examples:

ash test environment PATH
# Output: allow

ash test environment AWS_SECRET_ACCESS_KEY
# Output: deny

ash test environment CUSTOM_VAR
# Output: unknown

ash init

Initialize a new policy file.

USAGE: ash init [OPTIONS]

OPTIONS:
  --policy <policy>      Output path for policy file (default: .ash/policy.yml)
  --no-deps              Skip auto-detected dependencies
  --force                Overwrite existing file
  --no-skill             Do not install a SKILL.md file

By default, ash init scans the current working directory for files that indicate project tooling and automatically adds matching dependencies to the generated policy:

FileDependency
Cargo.tomlash/rust-dev
package.jsonash/js-dev
pyproject.tomlash/python-dev
*.xcodeprojash/xcode-dev
.claudeash/claude-code
.gitash/git
.githubash/github

The ash/base-macos dependency is always included unless --no-deps is passed. When --no-deps is passed, no dependencies are included at all.

By default, writes a SKILL.md file alongside the policy file (in the same directory). This file teaches AI agents how to use ash test to check permissions before attempting actions. Use --no-skill to skip this. If the policy file already exists but SKILL.md does not, only the skill file is created.

Examples:

# Create policy with auto-detected dependencies and SKILL.md
ash init

# Create policy at custom path
ash init --policy security/policy.yml

# Create minimal policy without any dependencies
ash init --no-deps

# Overwrite an existing policy file
ash init --force

# Create policy without the AI agent skill file
ash init --no-skill

ash add

Add dependencies to a policy.

USAGE: ash add [OPTIONS] [<dep>[@<version>] ...]

ARGUMENTS:
  <dep>                  Policy name
  <version>              Semantic versioning requirements string

OPTIONS:
  --policy <policy>      Policy file path (default: .ash/policy.yml)
  --local <path>         Add a local dependency path
  --registry <url>       Registry URL (default: https://hub.ashell.dev)

Examples:

# Add a registry dependency
ash add js-dev

# Add with version constraint
ash add python-dev@1.2

# Add multiple dependencies
ash add git-dev rust-dev go-dev

# Add a local policy file as dependency
ash add --local ../shared/team-policy.yml

ash remove

Remove dependencies from a policy.

USAGE: ash remove [OPTIONS] [<dep> ...]

ARGUMENTS:
  <dep>                  Policy names to remove

OPTIONS:
  --policy <policy>      Policy file path (default: .ash/policy.yml)
  --local <path>         Remove a local dependency path
  --registry <url>       Registry URL (default: https://hub.ashell.dev)

Examples:

# Remove a dependency
ash remove python-dev

# Remove multiple dependencies
ash remove rust-dev go-dev

# Remove a local dependency
ash remove --local ../shared/old-policy.yml

ash check

Validate policy correctness, including dependencies.

USAGE: ash check [OPTIONS]

OPTIONS:
  --policy <policy>      Policy file path (default: .ash/policy.yml)
  --offline              Run without accessing the network
  --registry <url>       Registry URL (default: https://hub.ashell.dev)

Examples:

# Check the default policy
ash check

# Check a specific policy
ash check --policy strict.yml

# Check without network access
ash check --offline

ash lint

Find and fix common policy issues.

USAGE: ash lint [OPTIONS]

OPTIONS:
  --policy <policy>      Policy file path (default: .ash/policy.yml)
  --fix                  Auto-fix fixable issues and write back

Checks:

  • macOS symlink paths (/tmp, /var, /etc/private/...) — error, fixable
  • Overly broad allow/deny rules — warning
  • environment.allow: all with no deny list — warning
  • Overly broad IOKit device allow — warning
  • Symlinks on disk in rule paths — warning, fixable

Exit codes: 0 = no errors, 1 = lint errors or parse failure.

Examples:

# Lint the default policy
ash lint

# Lint and auto-fix issues
ash lint --fix

# Lint a specific policy
ash lint --policy strict.yml

ash format

Format a policy file.

USAGE: ash format [OPTIONS]

OPTIONS:
  --policy <policy>      Policy file path (default: .ash/policy.yml)

Examples:

# Format the default policy
ash format

# Format a specific policy
ash format --policy custom.yml

ash merge

Merge similar rules in the policy file.

USAGE: ash merge [OPTIONS]

OPTIONS:
  --policy <policy>      Policy file path (default: .ash/policy.yml)
  -y, --yes              Skip confirmation prompts for wildcard merges

Behavior:

  • Merge identical rules automatically
  • Merge overlapping rules automatically (e.g., filesystem rules with an identical path & action but distinct operations; network rules with an identical domain & action but different ports, directions, transports)
  • Merge similar rules into wildcards interactively (e.g., filesystem rules with a shared path prefix and 5+ distinct absolute suffixes; network rules with a shared domain and 5+ distinct absolute subdomains; exec rules with a shared path prefix and 5+ distinct absolute suffixes)

Wildcard merges require user confirmation unless --yes is passed.

Examples:

# Merge rules interactively
ash merge

# Merge rules and auto-confirm wildcard merges
ash merge --yes

# Merge rules in a specific policy
ash merge --policy custom.yml

ash expand

Generate an expanded version of the policy with all dependencies resolved.

USAGE: ash expand [OPTIONS]

OPTIONS:
  --policy <policy>      Policy file path (default: .ash/policy.yml)
  --format <format>      Output format: yaml (default) or json
  --registry <url>       Registry URL (default: https://hub.ashell.dev)

The expanded policy contains all rules from all dependencies, fully resolved.

Examples:

# Show expanded policy as YAML
ash expand

# Show as JSON
ash expand --format json

# Expand a specific policy
ash expand --policy my-policy.yml

ash update

Update policy dependencies to the latest version allowed by version constraints.

USAGE: ash update [OPTIONS] [<dep> ...]

ARGUMENTS:
  <dep>                  Specific dependencies to update (default: all)

OPTIONS:
  --policy <policy>      Policy file path (default: .ash/policy.yml)
  --registry <url>       Registry URL (default: https://hub.ashell.dev)

Examples:

# Update all dependencies
ash update

# Update specific dependencies
ash update js-dev python-dev

ash outdated

Find policy dependencies that have newer versions available.

USAGE: ash outdated [OPTIONS]

OPTIONS:
  --policy <policy>      Policy file path (default: .ash/policy.yml)
  --registry <url>       Registry URL (default: https://hub.ashell.dev)

Examples:

ash outdated
# Output:
# js-dev: 1.2.0 -> 1.3.0 (compatible)
# base-macos: 1.0.0 -> 2.0.0 (breaking)

Search for a policy in the registry.

USAGE: ash search [OPTIONS] <query>

ARGUMENTS:
  <query>                Policy name or search term

OPTIONS:
  --limit <n>            Limit results (default: 10, max: 100)
  --registry <url>       Registry URL (default: https://hub.ashell.dev)

Examples:

ash search python
# Output:
# python-dev (1.2.0) - Python and pip development tools
# python-ml (1.0.0) - Python ML/AI libraries

ash info

Display information about a registry policy.

USAGE: ash info [OPTIONS] <policy>

ARGUMENTS:
  <policy>               Policy name

OPTIONS:
  --registry <url>       Registry URL (default: https://hub.ashell.dev)

Examples:

ash info js-dev
# Output:
# Name: js-dev
# Version: 1.3.0
# Description: Node.js, npm, and npx development tools
# Dependencies: base-macos@1
# ...

ash publish

Upload a policy to the registry. Requires authentication.

USAGE: ash publish [OPTIONS]

OPTIONS:
  --policy <policy>      Policy file path (default: .ash/policy.yml)
  --readme <path>        README file path (default: .ash/README.md)
  --dry-run              Check and bundle without uploading
  --registry <url>       Registry URL (default: https://hub.ashell.dev)

The policy must include valid publish metadata. See Policy Hub for details.

Examples:

# Validate before publishing
ash publish --dry-run

# Publish the policy
ash publish

ash yank

Remove a published policy version from the registry index. The policy can only be yanked by its publisher.

USAGE: ash yank [OPTIONS] <policy>

ARGUMENTS:
  <policy>               Policy name

OPTIONS:
  --version <version>    Policy version to yank (default: latest)
  --reason <reason>      Reason for yanking (shown as a warning when others attempt to use this version)
  --undo                 Undo a yank, restoring the version to the index
  --registry <url>       Registry URL (default: https://hub.ashell.dev)

Examples:

# Yank the latest version
ash yank my-policy

# Yank a specific version
ash yank my-policy --version 1.2.0

# Restore a yanked version
ash yank my-policy --version 1.2.0 --undo

ash auth

Authentication commands for the registry.

ash auth --help
  login    Log in to an Ash account
  logout   Log out of an Ash account
  status   Display active account and authentication state

ash auth login

Log in to an Ash account. Opens your browser for OAuth authentication.

ash auth login

ash auth logout

Log out and delete the local authentication token.

ash auth logout

ash auth status

Display the current authentication state.

ash auth status
# Output: Logged in as user@example.com

ash ping

Test connection to the Ash daemon.

ash ping
# Output: Daemon is running (version 1.0.0)

ash status

Get system status and health information.

ash status
# Output:
# Daemon: running
# Network Extension: active
# Active sessions: 2
# Policy cache: 15 policies

ash logs

View ash audit logs

USAGE: ash logs [--session <session>] [--denials] [--lines <lines>] [--follow]

OPTIONS:
  --session <session>     Filter by session ID
  --denials               Only show denials
  -l, --lines <lines>     Number of lines to show (default: 50) (default: 50)
  --follow                Follow log file (like tail -f)

ash telemetry

Get or set anonymous telemetry status

USAGE: ash telemetry [<action>]

ARGUMENTS:
  <action>                set status to enabled or disabled (values: enable, disable)

ash restart-ne

Restart the Network Extension and show logs. Used for debugging during development.

ash restart-ne

ash uninstall-ne

Uninstall the Network Extension. Used for debugging during development.

ash uninstall-ne