Run code before or after run/2. Handy for setup, teardown, logging, and
sharing state across a command tree.
before_run
Runs after all parsing and validation, just before run/2. Receives the
args map, must return an args map.
command "migrate" do
option :target, type: :string
before_run fn args ->
IO.puts("Connecting to database...")
args
end
endUse it to inject derived state into args, open connections, or log start
events.
after_run
Runs after run/2 returns. Receives the return value, must return a value
(typically the same one).
after_run fn result ->
IO.puts("Done.")
result
endUseful for cleanup, timing, or unconditional logging.
persistent_before_run (inherited)
Like before_run, but inherited by every descendant command. Declared on
the root; runs for every subcommand invocation, before each command's own
before_run hooks.
command "my-tool" do
persistent_before_run fn args ->
Map.put(args, :start_time, System.monotonic_time(:millisecond))
end
subcommand MyTool.Server
subcommand MyTool.Db
endEvery leaf-command handler under my-tool sees args[:start_time].
Multiple hooks
Each hook macro can be called more than once. Hooks run in declaration order.
before_run &add_tracing/1
before_run &add_logger/1
before_run &add_timing/1Ordering
For a subcommand invocation, the full ordering is:
- Every ancestor's
persistent_before_runhooks, root-first. - This command's
before_runhooks, declaration order. run/2.- This command's
after_runhooks, declaration order.
There is no persistent_after_run -- parent cleanup typically belongs in
the root handler or in explicit supervision logic.
See also
- Subcommands for how persistent hooks flow through nested trees.