Custom Functions
Custom functions let you define reusable jq logic and call it from eval: expressions anywhere in your configuration.
Functions are written in plain jq def syntax and placed in a .jq file.
That file is then loaded as a jq module via $extends or $includes.
For the full syntax of $extends and $includes see the Syntax Reference.
For available builtin variables and functions see the Builtins page.
Defining a module
Create a file with a .jq extension.
Each function is declared with the standard jq def keyword.
A parameterless function:
greet.jqdef hello_world:
"Hello, world!";
A parameterized function (jq uses ; to separate parameters):
utils.jqdef port_of($service):
refexpr(".ports.\($service)");
def url_of($service):
refexpr(".urls.\($service)");
Functions in a .jq module have full access to jq++ builtins such as ref, refexpr, reftag, parent, and topathexpr.
They do not run in a restricted "plain jq only" context, so they can resolve dynamic values directly instead of forcing every such value through explicit parameters.
Loading a module
Reference the .jq file in the $extends or $includes list of your configuration:
{
"$extends": ["greet.jq"],
"greeting": "eval:string:greet::hello_world"
}
The file is resolved using the standard search path (current directory first, then JF_PATH).
See the Syntax Reference — Search Paths section for details.
Calling a function
Inside an eval: expression, call a custom function using module-qualified syntax:
modulename::functionname
The module name is the filename without the .jq extension.
For example, greet.jq becomes the module greet, and utils.jq becomes utils.
input.json — parameterless call{
"$extends": ["greet.jq"],
"greeting": "eval:string:greet::hello_world"
}
input.json — parameterized call{
"$extends": ["utils.jq"],
"apiUrl": "eval:string:utils::url_of(\"api\")"
}
Using jq++ builtins inside functions
Custom functions can call any jq++ builtin.
A function wrapping parent to return a path expression:
nav.jqdef current_path:
parent;
input.json{
"$extends": ["nav.jq"],
"info": {
"nested": {
"path": "eval:string:nav::current_path | topathexpr(.)"
}
}
}
The expression evaluates to the jq path of the nested object (e.g., .info.nested).
A function can also resolve values from the surrounding jq++ document directly:
funcs.jqdef port_of($service):
refexpr(".ports.\($service)");
def tag_value:
reftag("thetag");
input.json{
"$extends": ["funcs.jq"],
"thetag": "tag-value",
"ports": { "api": 8080 },
"resolvedPort": "eval:number:funcs::port_of(\"api\")",
"resolvedTag": "eval:string:funcs::tag_value"
}