Skip to main content
Glama

deploy_git

Deploys an app from a Git repository by cloning, building, and running it server-side, with dry-run validation and secure token references.

Instructions

Use when: the app lives in a Git repo. Asynchronous — follow with wait_for_service.

    Clones ``repo_url`` server-side (public GitHub by default), then builds
    and runs it like ``deploy``. The token reference is resolved server-side
    — a raw credential never passes through the tool.
    ``dry_run=True`` returns the build/config plan diff (env key names only,
    values never).

    If the repo's ``nerdit.toml`` declares ``[ai.*]`` bindings, each is
    injected at launch as ``NERDIT_AI_<NAME>_URL/_KEY/_MODEL``, and the
    ``default`` binding also sets ``OPENAI_BASE_URL/OPENAI_API_KEY/
    OPENAI_MODEL`` — point the app's OpenAI SDK at these; no code change
    needed.

    ``nerdit.toml`` ``[deploy]`` keys — anything else is IGNORED and
    reported back in the response ``hints``: ``name``, ``port``, ``gpus``,
    ``start``, ``health``, ``health_type`` (``http``|``tcp``),
    ``memory_limit``, ``cpu_limit``, ``volumes``, ``release``, ``cutover``,
    ``auto_deploy``, ``edge_auth``, ``build_settings``. Generated Node builds run
    ``scripts.build`` automatically;
    override it through ``[deploy.build_settings]`` or use a Dockerfile.

    ``release`` runs once inside the new image before traffic moves; if it
    fails the deploy settles ``failed`` and the image reverts, never the data —
    whatever the migration already committed stays, so write idempotent
    migrations. ``cutover`` null = zero-downtime swap
    when eligible, false = same-port swap.
    On a successful non-dry-run deploy the
    response carries ``summary`` (app/status/version/public_url), ``hints``
    (ordered one-liners, never empty) and ``next_step`` (the structured
    follow-up call); a ``dry_run`` plan carries none of the three — read a
    plan's advisories from its ``warnings``. On a node in ``path``
    proxy mode the app is served at ``/<name>/``, so a frontend must be
    built with that base path.

    ``build_settings`` overrides
    preset/install/build/start/node_version/package_manager/subdir/public_env.
    ``preset`` selects node/nextjs/python/dockerfile; null resets to
    repository/default detection.
    An existing Dockerfile retains precedence.
    Omit it to preserve saved overrides; a null field resets to repository/default,
    and ``build: false`` skips compilation.
    ``public_env`` passes public build-time variables (shown in clear in a dry
    run; secret references are refused). Secret mounts are unsupported;
    runtime env is unchanged.

    SANDBOX: by DEFAULT containers run with all Linux capabilities dropped
    (``cap_drop=["ALL"]``) and no-new-privileges — both are operator settings
    (``[containers].drop_all_caps`` / ``[containers].no_new_privileges``), so
    read the live profile in ``capabilities.sandbox`` rather than assuming: an
    operator may have relaxed it. Under that default, an image whose entrypoint
    does root work — ``chown``/``chmod`` of its own runtime dirs, dropping
    privileges via ``setuid``/``setgid``, writing ``/var/run`` — dies before
    your app ever starts. Stock ``nginx`` is the classic trap. Use a non-root
    image and a non-root ``USER`` that owns the files it writes: for a static
    site, ``nginxinc/nginx-unprivileged`` (listens on **8080**, so set
    ``port=8080``) or any tiny static server. A crash from this reports
    remediation code ``image_needs_privileges`` in ``diagnose_service``. PORT
    CONTRACT: the container MUST listen on the declared ``port`` (the tool
    argument, else ``nerdit.toml`` ``[deploy].port``, else **8000**) — that is
    the only port the daemon publishes and health-checks, so listening anywhere
    else fails the health probe with a healthy-looking container. A port below
    1024 is NOT the reason a root entrypoint is needed: every container runs on
    the docker bridge in its own network namespace (never host networking),
    where Docker sets ``net.ipv4.ip_unprivileged_port_start=0``, so binding 80
    needs no capability and no root — the chown/setuid work does.
    

Input Schema

NameRequiredDescriptionDefault
envNoRuntime env for the container: values are literal strings, never resolved (a ``${secrets.*}`` reference is passed through as text); a null value deletes that key on redeploy. Secrets go through ``set_secret``, which overrides an ``env`` key of the same name at launch.
refNoBranch or tag to clone. Omit for the repository's default branch. Recorded on the app, so ``redeploy_service`` re-clones this ref.
gpusNoGPUs to reserve for the container (0 = none). Omit to use ``[deploy].gpus``, else the count already recorded on a redeploy, else 0.
nameYesApp name (lowercase DNS label). A new name creates the app; an existing one redeploys it in place.
portNoPort the container listens on: the only port published and health-checked. Omit to use ``nerdit.toml`` ``[deploy].port``, else the port already recorded on a redeploy, else 8000.
startNoStart command run inside the built image (shell syntax). Omit to use ``[deploy].start`` or the buildpack default.
healthNoHTTP health path probed on ``port`` (e.g. ``/health``); the app is ``healthy`` once it answers 2xx. Omit to keep ``[deploy].health`` (or the existing app's probe on redeploy).
subdirNoSubdirectory of the repo to build (monorepo subtree). Omit to build from the repository root.
vendorNoGPU vendor to reserve when ``gpus`` > 0 (``nvidia`` or ``amd``); omit to let the daemon choose on a fresh deploy — a redeploy keeps the vendor already recorded.
dry_runNotrue = validate and return the plan (what would change) with zero writes; nothing is built, deployed or audited as a change.
repo_urlYes``https://`` clone URL, on a host the daemon allows (``capabilities.deploy.git_allowed_hosts``, ``github.com`` by default). A URL carrying credentials is refused — pass ``token_ref`` instead.
token_refNoPrivate-repo credential as a *reference*, never a raw token: ``${secrets.KEY}``, ``${secrets.shared.KEY}``, or the literal ``${github.installation}`` on a node linked to an account with the Nerdit GitHub App installed on that repo. Omit for a public repo.
build_settingsNoBuild overrides, same keys as ``[deploy.build_settings]`` in ``nerdit.toml``: ``preset`` (node/nextjs/python/dockerfile), ``install``, ``build`` (``false`` skips compilation), ``start``, ``node_version``, ``package_manager``, ``subdir``, ``public_env`` (build-time variables baked into the bundle, never secrets). Commands run inside the build container.
idempotency_keyNoCaller-chosen key: a retry with the same key replays the first result instead of acting twice. Omit and a fresh key is minted per call, so each call acts.

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.1.0

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With zero annotations the description carries the full burden and does so in depth: async lifecycle, release runs once before traffic with revert-the-image-never-the-data failure semantics, cutover null vs false, dry_run writing nothing, and the exact response fields (summary/hints/next_step vs dry_run warnings). It also discloses the sandbox default (cap_drop ALL, no-new-privileges), the operator-relaxable caveat, and the image_needs_privileges remediation code.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded well with 'Use when' and the async warning, but the body sprawls: the PORT CONTRACT material restates the port priority chain already in the schema, and the sandbox/root-entrypoint section is long enough to bury operational facts. Dense and mostly load-bearing, yet clearly over-budget for a tool description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 14-parameter, no-annotation mutation tool with no output schema, everything an agent needs is present: prerequisites, async follow-up, failure modes, response shape, port/privilege contract, and secret-handling boundaries. Nothing material is left for the caller to guess.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% so the baseline is 3; the description adds real meaning on top: which nerdit.toml [deploy] keys are honored and that everything else is IGNORED and echoed back in hints, how build_settings interacts with a repo Dockerfile, and that public_env values are shown in clear in a dry run while secret references are refused.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb chain and resource: clones repo_url server-side, then builds and runs it, i.e. deploy-from-Git. The opening 'Use when: the app lives in a Git repo' instantly separates it from the local-directory siblings like deploy / deploy_app / deploy_template.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit entry condition ('Use when: the app lives in a Git repo') and an explicit follow-up routing ('Asynchronous — follow with wait_for_service'), plus a clear dry_run branch for plan-only use. It never names the alternative sibling (deploy) as an exclusion, so the agent must infer when-not, keeping it a notch below 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.