The base plugin defines the callbacks every other plugin can implement and ships the global options/flags that apply to every command. It is always loaded.

The other always-loaded plugins — Setup, Build, Run, Mcp — sit on top of Base and form the @base_plugins set defined in lib/marea.ex. Note that the MCP Plugin re-exposes every leaf subcommand contributed by any other loaded plugin as a typed MCP tool, with no extra work on the contributing plugin's side.

When it's loaded

Marea.Plugins.Base is always part of @base_plugins in lib/marea.ex, so you don't list it in plugins:.

Callbacks defined

Implementations are no-ops; their job is to define the chain entry points other plugins implement. See 06-plugin-development.md for the intended return values.

CallbackPurpose
Marea.Plugins.Base.marea_config_schema/1Plugins enrich the Zoi schema for marea.yaml.
Marea.Plugins.Base.marea_config_args/1Plugins enrich the CLI subcommand tree.
Marea.Plugins.Base.marea_cmd/2Plugins handle parsed commands.
Marea.Plugins.Base.marea_release_vsn/0Plugins compute a release version string.
Marea.Plugins.Base.marea_init_release_file/1Plugins return content for files written by setup init-release.
Marea.Plugins.Base.marea_deploy_types/1Plugins contribute values to the deploys.<d>.type: enum (e.g. Marea.Plugins.Helm adds :helm).
Marea.Plugins.Base.marea_release_types/1Plugins contribute values to the deploys.<d>.releases.<r>.type: enum (e.g. Marea.Plugins.Docker adds :elixir and :dockerfile_dir).

Marea.Plugins.Docker declares one additional callback, Marea.Plugins.Docker.marea_dockerfile_assigns/2, for plugins that want to enrich the EEx assigns Marea passes to the rendered Dockerfile (docker.python uses it to inject a Python build stage).

Global options and flags

These are declared in Marea.Config.Args.base_args/0 and tagged global: true. The args builder injects them into every leaf subcommand, so they're available everywhere:

NameLongShortDefaultDescription
marea_dir--marea-dirmarea.dDirectory holding configs/, secrets/, deploys/, templates/.
state_dir--state-dir.mareaRuntime/build state directory.
help--help-hShow help for this command. Marea normalises positional --help so marea aws --help works as expected.
nopause--nopausefalseSkip "press enter to continue" prompts before destructive commands. Useful in CI.

Reusable option specs

Marea.Config.Args ships a few helpers other plugins use to keep CLI surface consistent:

HelperLongDescription
deploy_option/0--deploy / -dPick the deploy from marea.yaml. Defaults to last value.
release_option/0--release / -rPick the release inside the chosen deploy.
cookie_option/0--cookieErlang cookie for run commands. Default: marea_cookie.
pos_option/0--posInteger offset; used by run to start multiple nodes side by side, and by helm rollback to choose a revision.
mix_env_option/1--mix-envMIX_ENV for build-time and local-run commands.

Command-handling helpers

The Base plugin also documents the conventional return values from Marea.Plugins.Base.marea_cmd/2. Implementations in other plugins should:

  • match their command prefix (e.g. [:helm | rest]);

  • return :cont for everything else, so the chain continues to the next plugin;
  • return :usage for an unrecognised subcommand to print help.
defcb marea_cmd([:my_cmd | rest], %Config{} = config), do: my_cmd(rest, config)
defcb marea_cmd(_cmds, _config), do: :cont

Built-in commands

Base also ships one user-facing command for inspecting the live, plugin-enriched schema:

marea schema
 show    [--json]

marea schema show

Prints a readable, indented tree of every field in the plugin-enriched schema, with type, required/default, and description.

The schema is rebuilt on every invocation by running the Marea.Plugins.Base.marea_config_schema/1 plugin chain, so any fields contributed by plugins listed in marea.yaml (e.g. Marea.Plugins.Aws adding aws:) appear in the output.

Sample output (trimmed):

:plugins (array<string>) = []
:marea_dir (string) = "marea.d"
:state_dir (string) = ".marea"
:cmd_prefix (map)
  :build (string)
      Shell prefix wrapping every command tagged `prefix: :build` 
:deploys (map<string, map>)
  :<string> (map)
    :type (enum(:helm)) = :helm
        Deploy type
    :releases (map<string, map>)
      :<string> (map)
        :type (enum(:elixir | :dockerfile_dir)) = :elixir
            Build strategy. :elixir auto-generates a Dockerfile 
        

Conventions in the tree:

  • key (type) — the field name and a compact type label.
  • = <value> — the field has a default; the value is shown verbatim.
  • (required) — the field has no default and must be set.
  • :<string> / :<any> — the parent is a dynamic-key map (e.g. one entry per deploy / release / aws-id); the inner schema applies to every key.
  • The first indented line under a field is its description, when the schema declared one.

Flags

FlagDefaultPurpose
--jsonoffEmit the JSON Schema produced by Zoi.to_json_schema/1 instead of the tree view.

The --json form is meant for machine consumption: piping into jq, generating editor completions, or feeding tools that already speak JSON Schema.

marea schema show --json | jq '.properties.deploys'

Implementation notes

  • The tree formatter walks Zoi type structs directly (the internal Map / Default / Array / Enum types) and unwraps Default to surface the default value while still reporting the inner type.
  • Zoi.optional/1 doesn't wrap — it just sets meta.required = false on the inner node — so the formatter checks meta.required to decide whether to print (required).
  • Dynamic-key maps (Zoi.map(key_type, value_type)) are rendered as map<key, value> with a single placeholder child key; this matches how the schema is defined for deploys, releases, aws, and route53 zones.