This branch contains the CLI for Ferret v2. For the stable v1 CLI, see the
v1branch.
Ferret CLI is the command-line interface for Ferret, a declarative-first, expression-oriented embedded language and runtime for data automation.
FQL combines a declarative core with domain orchestration through expressions such as match, for, filter, query, and waitfor. When a workflow needs state, var and while provide constrained mutation without turning FQL into a general-purpose language.
Use it to run FQL scripts, format and check source files, inspect compiled bytecode, manage browser sessions, and debug local scripts.
Full documentation lives at ferretlang.org.
Build the checkout with Go 1.26.5 or newer and make to use the features
documented here:
git clone https://github.com/MontFerret/cli.git
cd cli
make compile
export PATH="$PWD/bin:$PATH"The binary is written to bin/ferret. The export command adds that directory to
PATH for the current shell; you can also run ./bin/ferret directly.
For prebuilt binaries, choose a v2 release from the releases page. Published releases may not include features added since their tag. GitHub's latest stable release and the shell installer can still select the v1 CLI.
Run the REPL:
ferret replRun an inline expression:
ferret run --eval 'return "Hello, Ferret!"'Run a script:
ferret run example.fqlPass parameters:
ferret run example.fql --param url=https://example.com --param limit=10Parameter values are parsed as JSON when possible. Values that are not valid JSON are passed as strings.
ferret run example.fql --param active=true
ferret run example.fql --param tags='["news","tech"]'
ferret run example.fql --param code='"123"'Use parameters in FQL with @name:
let page = web::html::open(@url)
return web::html::element(page, "title").innerText
ferret run script.fql # Run a script
ferret exec script.fql # Alias for run
ferret repl # Start the interactive shell
ferret check script.fql # Check syntax and semantics
ferret fmt script.fql # Format source
ferret build script.fql # Compile to a bytecode artifact
ferret inspect script.fql # Print compiled program details
ferret debug script.fql # Start the interactive debugger
ferret migrate run . # Migrate supported Ferret v1 Go and FQL source behavior
ferret migrate check . # Check FQL source for v1 compatibility issues
ferret browser open # Start a managed browser
ferret config list # Show configuration
ferret mod search sqlite # Search the Ferret module registry
ferret mod install montferret/archive # Install a module into a Go application
ferret mod publish # Submit a tagged module release to the Registry
ferret version # Show version informationRun ferret [command] --help for command-specific options.
Run ferret migrate run with a standalone lowercase .fql file or a project
directory. The path defaults to the current directory:
ferret migrate run
ferret migrate run path/to/project
ferret migrate run scripts/query.fqlThe selected directory is the migration boundary, including when the path is
omitted and defaults to .. When selected Go source belongs to a containing Go
module, the command uses that module for metadata and dependency updates without
scanning source outside the selected directory. It rewrites documented Ferret
v1 imports to their Ferret v2 compatibility packages and updates go.mod and
go.sum only when a selected import was rewritten. A selected directory with no
eligible Go source is treated as FQL-only even when a containing go.mod exists.
A standalone file migration changes only that file.
The command finds lowercase .fql files and preserves v1's implicit result for
a final top-level FOR by returning it explicitly:
// Before
FOR item IN 1..3
RETURN item
// After
return for item in 1..3 {
return item
}
For loop migration, only a structurally recognized final top-level FOR without
an explicit terminal return is changed. Nested, assigned, expression-contained,
function-contained, non-final, and already-returned loops retain their structure.
The command also migrates safe unqualified legacy stdlib calls to canonical
lowercase names. For example, JSON_PARSE(body) becomes
encoding::json_parse(body), has(obj, key) becomes object::has_key(obj, key),
and abs(value) becomes math::abs(value). Supported mappings include:
| Namespace | Legacy calls migrated automatically |
|---|---|
encoding:: |
json_parse, json_stringify, encode_uri_component → query_escape, decode_uri_component → query_unescape, to_base64 → base64_encode, from_base64 → base64_decode, escape_html → html_escape, unescape_html → html_unescape |
crypto:: |
md5, sha1, sha512, random_token |
path:: |
base, clean, dir, ext, is_abs, separate, match |
arrays:: |
first, flatten, last, sorted, unique, slice, intersection, nth → at, remove_values → remove_any, minus → difference, union → concat, union_distinct → union, range |
random:: |
Zero-argument rand() → float() |
object:: |
values, has → has_key, zip, keep_keys, merge, merge_recursive → merge_deep, and one-argument keys(obj) |
datetime:: |
now, date → parse, date_dayofweek → day_of_week, date_dayofyear → day_of_year, date_leapyear → is_leap_year; date_year, date_month, date_day, date_hour, date_minute, date_second, date_millisecond, date_quarter, date_days_in_month, date_format, date_add, date_subtract lose their date_ prefix |
math:: |
pi, abs, acos, asin, atan, atan2, ceil, cos, degrees, exp, exp2, floor, log, log2, log10, pow, radians, round, sin, sqrt, tan |
Argument-aware replacements also include:
| Legacy call | Replacement |
|---|---|
position(a, v) or position(a, v, false) |
arrays::contains(a, v) |
position(a, v, true) |
arrays::index_of(a, v) |
append(a, v) / push(a, v), optionally with false |
arrays::append(a, v) |
remove_value(a, v), optionally with a negative integer literal |
arrays::remove(a, v) |
sorted_unique(a) |
arrays::sorted(arrays::unique(a)) |
shift(a) |
arrays::slice(a, 1) |
outersection(a, b) |
arrays::symmetric_difference(a, b) |
keys(o, false) |
object::keys(o) |
keys(o, true) |
arrays::sorted(object::keys(o)) |
date_diff(a, b, unit, true) |
datetime::diff(a, b, unit) |
Boolean modes and negative integer limits may be parenthesized; arbitrary
constant expressions are not evaluated. Retained arguments preserve their
evaluation order and count. Strings, comments, object keys, and variable names
are not matched. Nested calls migrate independently, including inside composed
replacements and calls requiring manual review. Already-qualified targets are
preserved. Array and object replacements use immutable operations, never
arrays::mut or object::mut.
Manual follow-up includes the original path and line and explains why a call was preserved:
joinis ambiguous between legacy path joining and modern global string joining.- Dynamic modes in
position,keys,append, andpushneed manual review. - Unique
append/pushsuppresses only the incoming duplicate; applyingarrays::uniquewould also remove existing duplicates. - Zero, positive, and dynamic
remove_valuelimits have no canonical limit mode. outersectionwith three or more arrays uses exactly-one-input semantics; canonical symmetric difference uses odd-number-of-inputs semantics.popneeds an evaluation-count-preserving replacement;unshiftmust retain argument evaluation order;remove_nthretains host-list removal semantics.- Parameterized
randuses historical rounded/floored calculations rather than canonical continuous or integer bounds. - Unsupported arities of argument-aware rules require manual review.
date_comparehas component-range semantics that differ fromdatetime::same;date_diffwithout a literaltruefloating flag may truncate toward zero, whereasdatetime::diffalways returns a Float.average,sum,min,max,median,percentile,stddev_population,stddev_sample,variance_population, andvariance_samplehave permissive legacy behavior that differs from strict canonical math.- A matching function declaration or function alias anywhere in the file may
change call resolution. These checks are deliberately conservative, including
case variants and declarations in nested scopes. A namespace alias blocks a
replacement when it would redirect any introduced namespace, including both
arraysandobjectfor sorted keys.
Other safe calls in the same file still migrate. Rerunning migration produces no further edits; unresolved manual actions remain. If the formatter cannot preserve comments, the entire file is left unchanged and reported for manual follow-up.
Changed FQL is canonically formatted; files needing only formatting remain byte-for-byte unchanged. FQL-only targets do not require a Go module or Go toolchain and do not change Go dependencies. A directory containing eligible Go source still requires a containing Go module so import and dependency changes remain one safe migration.
Preview the affected paths without changing the project, or print a unified diff for review:
ferret migrate run --dry-run
ferret migrate run --print path/to/projectWithin the selected directory, the source scan excludes descendant vendor,
testdata, node_modules, hidden and underscore-prefixed directories, and
nested Go modules. The selected directory itself is scanned even when its name
would be excluded as a descendant, such as .tmp or testdata. Malformed FQL
is left unchanged and reported with its first useful diagnostic and line while
other files continue to migrate. Unsupported and generated-file imports are
also reported as manual follow-up. Symlink targets are rejected, and directory
symlinks are not followed.
When the selected directory covers only part of a Go module, migration retains the existing Ferret v1 dependency because source outside the selected directory is not inspected. Run the migration from the module root when the entire module is ready to remove that dependency.
Migration is intentionally limited to documented mechanical changes. It does
not translate arbitrary v1 APIs or application logic, rewrite generated Go
files or source in excluded descendant directories, or guess replacements for
unsupported v1 packages such as the former drivers packages. If a project
vendors dependencies, run go mod vendor after reviewing and applying the
migration.
Migration execution is available only through ferret migrate run. Bare
ferret migrate displays the check and run subcommands and does not modify
files.
migrate check reports final collecting FOR compatibility and the same legacy
stdlib findings as migrate run: encoding, crypto, path, immutable arrays and
objects, datetime, scalar math, range, and zero-argument random replacements,
plus calls requiring manual review.
It uses the same conservative declaration and alias guards described above.
Already-qualified calls are left alone. A clean check covers these supported
rules, not all v1 application semantics.
Check a standalone FQL file or recursively inspect a directory without modifying source files:
ferret migrate check --from v1 .
ferret migrate check scripts/query.fqlThe path defaults to the current directory, and --from currently defaults to
and accepts only v1. The check does not require a Go module, run Go tooling,
resolve dependencies, or format source. Directory scans include lowercase
.fql files in test fixtures, hidden or underscore-prefixed directories, and
nested Go modules. They skip .git, .hg, .svn, vendor, and
node_modules, and do not follow directory symlinks.
Compatibility findings use editor-friendly locations and include a suggested replacement or a manual-review explanation:
1_hackernews.fql:2:1: Final collecting FOR no longer becomes the script result in Ferret v2.
help: Add `return` before this loop.
query.fql:1:8: Legacy stdlib call `has` should use `object::has_key`.
help: Preview automatic replacements with `ferret migrate run --print`.
Found 2 v1 compatibility issues in 2 of 12 FQL files.
The command exits nonzero for automatic replacement suggestions, manual-review
findings, or FQL parse failures. Use ferret migrate run --print path/to/source
to preview edits; the check does not verify whether the formatter can preserve
the source during rewriting. Malformed files are reported while the remaining
files continue to be checked. Filesystem, cancellation, and internal failures
stop the check immediately.
Ferret CLI handles module discovery, installation into Go applications, project scaffolding, and preparation of registry publication records. Installation uses the Go module toolchain and the package path published by the Ferret registry.
Search the public registry by canonical module ID or description, or inspect one registered module:
ferret mod search sqlite
ferret mod info montferret/sqliteInstall a compatible registered release into an existing Go application:
ferret mod install montferret/archive
ferret mod install montferret/archive@1.0.0-rc.3
ferret mod install --yes montferret/archive # Approve safe missing prerequisites automaticallyIf the application is missing github.com/MontFerret/ferret/v2 or an active
ferret.New(...) composition, an interactive install shows the complete setup
before changing the project. It can add the exact Ferret version embedded in the
CLI and create an exported NewFerret(options ...ferret.Option) helper in
ferret.go when the destination package is unambiguous. Empty modules derive the
package name from the module path; projects with one package use that package.
Projects with multiple packages must add a composition manually.
Use -y or --yes to approve safe missing prerequisites in automation.
Non-interactive installs without that flag fail with equivalent manual steps
instead of reading stdin. The application must already have a go.mod.
The installer updates go.mod, go.sum, and the composition, then builds only
its owning package before committing all changes. It does not modify the Ferret
CLI runtime or create Ferret-specific project state. Installed modules are Go
code compiled into the application and execute with the application's process
permissions.
Initialize a new module project with the guided flow. It explains each value, offers editable defaults, and shows the resolved configuration before creating files:
ferret mod initYou can also provide any known values up front; the wizard asks only for what is missing. For non-interactive use, provide the module name and Go import path. The directory and namespace retain their module-name defaults:
ferret mod init acme/sqlite \
--go-module github.com/acme/ferret-sqlite \
--dir sqlite \
--namespace DB::SQLITEThe scaffold contains schema-valid TODO metadata. Replace it before publishing a release. The manifest must identify a public repository that supports anonymous HTTPS Git access. Commit the module files, create and push the release tag, then run the publication command from the module root:
git tag v1.0.0
git push origin v1.0.0
ferret mod publishBy default, the tag is v<version> for a standalone module or
<repository.directory>/v<version> for a monorepo module. For non-standard
release tags, pass --tag.
To publish a nested monorepo module while staying in the repository root, pass the local module directory explicitly:
ferret mod publish --dir modules/widget--dir selects the local module directory containing ferret.yaml; it does not
override the manifest's repository.directory. The flag can also be combined
with --dry-run or --print.
Publication validates ferret.yaml, resolves the public tag and pinned commit,
checks the adjacent README.md and go.mod, consults the current Registry, and
prepares only the immutable Barn source records needed for the release. The CLI
then uses the GitHub API to create or reuse your personal Barn fork, create a
focused publication branch, and open a pull request against
MontFerret/barn. You do not need a local Barn checkout or knowledge of its
record layout.
Set GH_TOKEN or GITHUB_TOKEN before publishing. If neither is set, Ferret
uses the token from gh auth token --hostname github.com; authenticate it with
gh auth login --hostname github.com when needed. The credential must be able
to write to your personal Barn fork and open a pull request against the public
Barn repository.
Validate the complete release without authenticating or mutating GitHub:
ferret mod publish --dry-runPrint the deterministic Barn-relative records as a versioned JSON document for inspection or unusual manual automation:
ferret mod publish --print--dry-run and --print cannot be combined, and neither mode submits records.
Publication retries are safe: an already-published version exits successfully,
and an exact open pull request or publication branch is reused. Ferret never
overwrites an immutable Registry record or a divergent branch; delete a stale
publication branch from your fork before retrying if its contents differ.
This CLI integrates Wire v1.0.0-alpha.4, Universal API v1.0.0-alpha.21, and
Ferret v2.0.0-alpha.62. The host must support the alpha.3 handshake, including
hosted runtime version metadata and chunked output framing; alpha.1 and alpha.2
hosts are incompatible.
Wire alpha.4 restores structured diagnostics for preparation failures such as syntax errors, allowing the Wire REPL to recover and continue with the next query. Alpha.3 hosts lose those diagnostics and end the REPL on preparation failures; use an alpha.4 host to retain diagnostic recovery.
Builtin execution remains the default. Select --runtime wire explicitly to run
source against an application-configured Universal API runtime. HTTP URLs in
--runtime continue to use the Worker execution and metadata endpoints.
Start the development host in terminal 1:
go run ./examples/wire-hostIt prints an ephemeral endpoint such as tcp://127.0.0.1:54321. In terminal 2,
substitute that endpoint in these commands:
ferret run --runtime wire --runtime-endpoint tcp://127.0.0.1:54321 \
--eval 'RETURN DEMO::IDENTITY(@value)' --param value=42
ferret exec --runtime wire --runtime-endpoint tcp://127.0.0.1:54321 script.fql
ferret run --runtime wire --runtime-endpoint tcp://127.0.0.1:54321 \
--eval 'let arr = []
return'
ferret repl --runtime wire --runtime-endpoint tcp://127.0.0.1:54321
ferret version --runtime wire --runtime-endpoint tcp://127.0.0.1:54321DEMO::IDENTITY(value) exists only in the example host. Try it in the REPL, submit
RETURN ), then correct the query. Syntax errors retain source snippets, carets,
and hints. Use exit or Ctrl-D to exit; Ctrl-C stops the shell. Stop the example
host with Ctrl-C when finished.
| Flag and config key | Environment variable | Default |
|---|---|---|
runtime-endpoint |
FERRET_RUNTIME_ENDPOINT |
Required for Wire; no default port |
runtime-connect-timeout |
FERRET_RUNTIME_CONNECT_TIMEOUT |
5s, must be positive |
Only tcp://127.0.0.1:<port> is supported (ports 1–65535, no other URL components).
Both connection establishment and the Wire handshake respect the timeout and
command cancellation. Connection failure never falls back or reconnects the
logical runtime automatically. Endpoint and connection-timeout settings require
Wire mode.
This plaintext transport is for trusted local development. Loopback access does not authenticate either the client or runtime. There are no TLS or credential settings in this integration. HTTP headers and policy flags are not Wire credentials.
The CLI reads script files locally and transmits their semantic name and contents. Compilation happens on the host, allowing application-only functions and modules. FQL filesystem operations use the runtime host's configured filesystem defaults (the example host uses its working directory as the root); the CLI does not send its current directory as a filesystem root. Explicit filesystem/HTTP policies and browser configuration, including settings in config or environment variables, are rejected in Wire mode. Untouched flag defaults do not count as explicit configuration.
Each run owns one logical runtime and transport; the REPL reuses one pair. Active calls settle before runtime and transport cleanup. Wire performs detached cleanup bounded by its 30-second cleanup timeout after cancellation. The host owns its engine independently; closing a CLI connection does not close it.
Run output is printed as encoded bytes, including available output accompanying an error. Errors go to stderr and fail the command; successfully produced empty output prints nothing. Artifacts and debugging remain builtin-only.
Wire and HTTP Worker execution stream encoded chunks directly to stdout, with
backpressure from the output writer. Bytes are preserved without decoding or
re-encoding. Available output remains printed if execution or delivery later
fails; read, write, and cleanup failures fail the command. HTTP delivery uses a
bounded buffer rather than memory proportional to the response size. The HTTP
REPL ends on request, response-read, or cleanup failures.
REPLs recover from structured query diagnostics; Worker response bodies remain
raw output. For execution responses, an HTTP error status alone does not fail
the command: the body is streamed unchanged, without interpreting it as query
diagnostics. Worker requests still use
POST / with source text and parameters, and GET /info for the hosted Ferret
version. Worker does not support Universal API compilation, debugging, output
codec selection, or per-session filesystem-root selection.
For Go callers, runtime.Run, RunSource, RunArtifact,
Builtin.RunArtifact, and run.Execute now return a caller-owned api.Output
instead of io.ReadCloser. Output is one-shot: call Consume to process chunks
or Collect to materialize detached Content.Data. Consumer callbacks borrow
read-only chunks valid only until the callback returns; copy any bytes you retain.
Non-nil collected content can accompany an error and contain partial output.
runtime.Run, RunArtifact, and run.Execute transfer their invocation-owned
runtime and transport resources to the returned output. RunSource borrows the
supplied Resources, and Builtin.RunArtifact borrows its receiver while
transferring its temporary session and plan to the output. Consume or close the
output before releasing borrowed parents; the caller remains responsible for
closing those parents.
Keep the invocation context alive until consumption or closure finishes.
Consume and Collect observe terminal execution, delivery, and cleanup failures
and finalize output-owned resources. Close abandons unread output without
certifying successful execution. Debugger events carry detached content.
Streaming delivery does not imply incremental query evaluation.
ferret version --runtime wire reports the hosted runtime version alongside the
CLI version. The Wire REPL banner shows the endpoint and hosted version. Version
values come directly from the Universal API and are preserved as opaque strings,
including empty values. Wire captures this metadata during the initial handshake;
reading it adds no RPC. Hosted metadata failure fails construction within the
connection timeout, before the REPL requests input. The example derives its
Ferret version from Go build information; builtin execution retains CLI-injected
version metadata (or unknown in a build without version injection).
Ferret can use Chrome or Chromium through the Chrome DevTools Protocol.
The HTML module uses the memory driver by default. Select the CDP driver in your script to use a browser:
let page = web::html::open("https://example.com", { driver: "cdp" })
return web::html::element(page, "title").innerText
The browser flags below manage browser startup and the debugger address; they do not select the HTML driver for the script.
Open a managed browser:
ferret browser openRun a script with a visible browser:
ferret run --browser-open script.fqlRun with a headless browser:
ferret run --browser-headless script.fqlUse an existing browser endpoint:
ferret run --browser-address http://127.0.0.1:9222 script.fqlStart the debugger for a local source file:
ferret debug script.fqlUseful debugger commands:
break 12 Set a breakpoint
breakpoints List breakpoints
continue Resume execution
step Step into
next Step over
out Step out
where Show stack trace
locals Show local variables
print <expr> Evaluate a safe debug expression
quit Exit
print supports limited expressions over paused program state, including
variable access and arithmetic. It does not execute function calls, queries, or
mutation.
The debugger currently supports local source scripts with the builtin runtime. Compiled artifacts, remote debugging, DAP, conditional breakpoints, hit-count breakpoints, and logpoints are not supported yet.
Ferret's builtin runtime exposes filesystem functions through a writable sandbox rooted at the CLI's current working directory. Select a narrower relative or absolute root, and optionally make it read-only:
ferret run \
--policy-fs-root=./fixtures \
--policy-fs-read-only \
script.fqlFilesystem policy options are available on run, repl, and debug and apply only to the builtin runtime. Supplying one with a remote runtime is a configuration error.
| Flag and config key | Environment variable | Default | Behavior |
|---|---|---|---|
policy-fs-root |
FERRET_POLICY_FS_ROOT |
Current working directory | Filesystem sandbox root |
policy-fs-read-only |
FERRET_POLICY_FS_READ_ONLY |
false |
Reject writes, directory changes, and removals |
In the builtin runtime, Ferret's HTTP client blocks localhost, loopback, private-network, and link-local HTTP access by default. Grant only the access a script needs; for example, a script that intentionally calls a local development service through this client requires an explicit opt-in:
ferret run \
--policy-http-allow-localhost \
--policy-http-default-headers='{"X-Trace":"local"}' \
script.fqlHTTP policy options are available on run, repl, and debug and apply only to
the builtin runtime. Supplying one with a remote runtime is a configuration error.
They configure integrations using Ferret's HTTP client, such as io::net::http
and net::rest; they do not govern requests made by Chrome itself. The existing
--proxy and --user-agent options continue to configure HTML/browser drivers.
List values accept repeated flags or comma-separated values. Default headers use a JSON object with string values. Only values explicitly supplied through a flag, environment variable, or config file override Ferret's secure defaults. Numeric zero retains the Ferret default; use the dedicated no-timeout or unlimited-* option to disable a limit.
| Flag and config key | Environment variable | Default | Behavior |
|---|---|---|---|
policy-http-allowed-schemes |
FERRET_POLICY_HTTP_ALLOWED_SCHEMES |
http,https |
Allowed URL schemes |
policy-http-allowed-methods |
FERRET_POLICY_HTTP_ALLOWED_METHODS |
GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS |
Allowed HTTP methods |
policy-http-allowed-hosts |
FERRET_POLICY_HTTP_ALLOWED_HOSTS |
unrestricted | Exact allowed hosts or host:port values |
policy-http-blocked-hosts |
FERRET_POLICY_HTTP_BLOCKED_HOSTS |
none | Exact blocked hosts or host:port values |
policy-http-allow-localhost |
FERRET_POLICY_HTTP_ALLOW_LOCALHOST |
false |
Allow localhost and loopback addresses |
policy-http-allow-private-networks |
FERRET_POLICY_HTTP_ALLOW_PRIVATE_NETWORKS |
false |
Allow private-network addresses |
policy-http-allow-link-local |
FERRET_POLICY_HTTP_ALLOW_LINK_LOCAL |
false |
Allow link-local addresses |
policy-http-default-headers |
FERRET_POLICY_HTTP_DEFAULT_HEADERS |
none | Default request headers as a JSON string map |
policy-http-blocked-request-headers |
FERRET_POLICY_HTTP_BLOCKED_REQUEST_HEADERS |
none | Block requests containing these header names |
policy-http-timeout |
FERRET_POLICY_HTTP_TIMEOUT |
30s |
Overall HTTP timeout |
policy-http-no-timeout |
FERRET_POLICY_HTTP_NO_TIMEOUT |
false |
Explicitly disable the overall timeout |
policy-http-max-request-size |
FERRET_POLICY_HTTP_MAX_REQUEST_SIZE |
16777216 |
Maximum request-body size in bytes |
policy-http-unlimited-request-size |
FERRET_POLICY_HTTP_UNLIMITED_REQUEST_SIZE |
false |
Explicitly disable the request-body limit |
policy-http-max-response-size |
FERRET_POLICY_HTTP_MAX_RESPONSE_SIZE |
16777216 |
Maximum response-body size in bytes |
policy-http-unlimited-response-size |
FERRET_POLICY_HTTP_UNLIMITED_RESPONSE_SIZE |
false |
Explicitly disable the response-body limit |
policy-http-max-response-header-size |
FERRET_POLICY_HTTP_MAX_RESPONSE_HEADER_SIZE |
1048576 |
Maximum response-header size in bytes |
policy-http-follow-redirects |
FERRET_POLICY_HTTP_FOLLOW_REDIRECTS |
true |
Follow HTTP redirects |
policy-http-max-redirects |
FERRET_POLICY_HTTP_MAX_REDIRECTS |
10 |
Maximum redirects to follow |
Configuration values can come from command-line flags, environment variables, or the config file.
Priority order:
- Command-line flags
- Environment variables, for example
FERRET_RUNTIME - Config file
- Defaults
The config file is ~/.ferret/config.yaml: a .ferret directory inside the
resolved user home directory on all supported platforms.
Examples:
ferret config set runtime builtin
ferret config set browser-address http://127.0.0.1:9222
ferret config set policy-fs-root ./fixtures
ferret config set policy-fs-read-only true
ferret config set policy-http-allow-localhost true
ferret config set policy-http-allowed-hosts api.example.com,cdn.example.com
ferret config set policy-http-default-headers '{"X-Trace":"local"}'
ferret config get browser-address
ferret config list
ferret config unset policy-http-allowed-hostsconfig set validates the complete persisted filesystem and HTTP policy before writing it. Invalid policy values and conflicting controls, such as setting both policy-http-timeout and policy-http-no-timeout=true, leave the existing config unchanged. List values use comma-separated strings, and default headers use a JSON object with string values.
config unset removes only the value stored in the config file and restores the implicit default for that key. Command-line flags and environment variables remain unaffected.
From the checkout described under Installation, build and test locally:
make compile
make testInstall the formatter and linters before using the remaining development
commands. Ensure Go's binary installation directory is on PATH:
make install-tools
make fmt
make lint
make buildIssues and pull requests are welcome. Before opening a pull request, run the formatter, linter, and test suite.
Apache-2.0