Marea can be used in two ways: as a number of Mix tasks or as a self-contained executable

As a Mix task

As a mix task, you only new to add it to your project:

# mix.exs
defp deps do
  [
    {:marea, "~> 1.0", runtime: false, only: :dev}
  ]
end
mix deps.get
mix compile

You can now use it as a mix task

mix marea help

The trade-off is the missing TTY. Commands that hand the parent shell to an interactive program — mix marea k8s console — needs a full TTY, but the child process sees a pipe instead of a real terminal. Line editing, arrow-key history, password prompts and other TTY-dependent features will misbehave. For interactive sessions, use method bellow.

As an script

You can also build it once from source and symlink it into each project that needs it. This allows all real-time capabilities of Marea, and allows for the MCP server to work.

git clone https://github.com/kalta/marea
cd marea
mix deps.get
mix marea.build       # produces ./marea (a shell-wrapped escript)

This is what happens:

  1. Runs mix escript.build to produce a regular escript named marea.
  2. Prepends a small shell header to the file. The header makes the script executable as a normal binary and, after the escript exits, runs .marea/next_cmd if one was written. This is how interactive commands like marea run local take over the parent shell.
  3. Copies the wrapped binary to priv/marea and replaces ./marea with a symlink to it. priv/marea is what gets shipped via the :marea dependency.

The binary is fully self-contained. To run it:

Then symlink marea escript into the root of your project

ln -s /path/to/marea .
./marea help

First run

The first time you invoke marea in a project that has no marea.yaml, Marea looks for one at marea.yaml, config/marea.yaml and marea.d/marea.yaml. If none exist, any non-setup command stops and points you at the bootstrap command:

> marea

No marea.yaml found (tried: marea.yaml, config/marea.yaml, marea.d/marea.yaml).
Run `marea setup init-marea` to create one.

Run it to scaffold a marea.d/ directory with configs/, secrets/ and a stub marea.d/marea.yaml:

> marea setup init-marea
Created marea.d/marea.yaml and subdirs (configs/, secrets/)

Then edit marea.d/marea.yaml to start describing your deploys. The setup commands (init, init-umbrella, init-release) are the only ones that run without an existing config; the scaffolding commands also remind you to run marea setup init-marea when they finish.

Bootstrapping a release in an existing app

Marea expects a standard umbrella Elixir application configured with releases. If your project is already release-configured (a working rel/env.sh.eex and a releases/0 in mix.exs), this step is not needed — skip ahead to writing marea.yaml.

If you don't have a release set up yet, marea setup init-release scaffolds one. For greenfield projects, marea setup init-umbrella creates the whole umbrella with Marea pre-wired. Both commands are documented in detail in the Setup Plugin guide.

Verifying the install

./marea --help
./marea build show-docker-versions   # introspects the alpine image used for builds

If ./marea --help prints the top-level command tree (setup, build, run, mcp, plus anything contributed by plugins listed in your marea.yaml), you're ready to move on to the quick-start guide.

Registering Marea as an MCP server

Marea can also run as a Model Context Protocol server, so AI assistants (Claude Code and any other MCP client) can drive builds, deploys, Helm and AWS operations through structured tool calls. Every leaf subcommand becomes a tool; the JSON Schema is auto-derived from the same plugin metadata that drives the CLI.

The fastest way to register Marea with Claude Code is:

claude mcp add marea -- /absolute/path/to/marea mcp serve

Use the built binary, not mix marea, for mcp serve. The MCP protocol is newline-delimited JSON-RPC on stdout; any other byte on stdout breaks the client. mix marea mcp serve dispatches to the same server, but Mix is free to print compile/boot messages (Compiling…, Generated marea app, deps output) to stdout before the loop starts, which corrupts the stream. The escript has no compile phase and a clean stdio. The one-shot debug commands (mix marea mcp tools, mix marea mcp call …) are fine over Mix — they print to your own terminal, not to an MCP client.

Run that from a project directory that already has a working marea.yaml — the server reads it at startup to discover which plugins (and therefore which tools) to expose. Then allowlist the read-only tools in ~/.claude/settings.json (or per-project .claude/settings.json):

{
  "permissions": {
    "allow": [
      "mcp__marea__helm_list",
      "mcp__marea__helm_history",
      "mcp__marea__helm_values",
      "mcp__marea__aws_ecr_list",
      "mcp__marea__aws_route53_list"
    ]
  }
}

Destructive tools (mcp__marea__helm_delete, mcp__marea__helm_rollback, mcp__marea__aws_*_delete) carry destructiveHint: true in their descriptors and will prompt for confirmation on every call, so they don't need an allowlist entry.

For inspection without a real MCP client:

marea mcp tools                                            # JSON descriptors for every tool
marea mcp call --tool helm_list --json '{"deploy":"staging"}'  # invoke a tool by hand

See the MCP Plugin guide for the full mapping of Optimus options to JSON Schema, the execution model, and the stdio discipline.