safe-chains 0.193.0

Auto-allow safe bash commands in agentic coding tools
Documentation
[[command]]
name = "php"
description = "PHP language interpreter. With no script and no code arguments, the bare invocation is purely diagnostic (--help, --version, -m/--modules to list compiled extensions, -i/--info to print phpinfo, --ini to show .ini files in use). Code execution surfaces: a script file passed by path runs that file; -r runs PHP code from the command line; -S starts a long-running built-in HTTP server bound to a host:port, serving PHP from a docroot (-t). The -d <key>=<value> flag overrides any php.ini directive for this run — most are diagnostic or resource-cap (memory_limit, max_execution_time, error_reporting, display_errors, date.timezone) but several can pivot to code execution or relax sandboxing: auto_prepend_file and auto_append_file cause PHP to execute a file before/after the main script, disable_functions controls which built-in functions are callable (lowering it can re-enable functions that were locked out, e.g. exec or system), open_basedir restricts which paths the script can read (relaxing it widens filesystem access), and include_path changes which files include() finds. The two PHP scripts most often invoked this way are artisan (Laravel's CLI) and please (Statamic's CLI, an extension of Artisan) — both bootstrap the full application and dispatch the command they're given. PHP follows a predictable annual release cycle."
handler = "php"
url = "https://www.php.net/manual/en/features.commandline.options.php"
doc_body = "Routing: the handler walks `-d KEY=VALUE` directives (KEY allowlist in Rust because the validation is custom — see is_safe_ini_pair), then basename-normalizes the next token. `--help` / `--version` / etc. as the final token match [command.fallback]; `artisan` and `please` (or any path whose basename is one of those) match the corresponding [[command.sub]] and re-dispatch via the top-level `artisan` / `please` command."

# Delegate subs. `php artisan view:clear` and `php /var/www/please stache:clear`
# both dispatch as if `artisan` / `please` were the command. delegate_skip = 0
# passes the (basename-normalized) token list to command_verdict so the inner
# top-level TOML drives validation.
[[command.sub]]
name = "artisan"
delegate_skip = 0

[[command.sub]]
name = "please"
delegate_skip = 0

# Bare diagnostic flags. The handler probes this fallback after the
# `-d` pre-flag scan, with the trailing token spliced as if it were
# the only argument: `php -d memory_limit=512M --version` ⇒ probe
# ["php", "--version"].
[command.fallback]
level = "Inert"
bare = false
max_positional = 0
standalone = ["--help", "--info", "--ini", "--modules", "--version", "-V", "-h", "-i", "-m", "-v"]