---
title: "Compile"
description: "Compile a symbol library from local folders, GitHub repos, docker images, Helm charts, and Artifactory. Waits inline for a quick compile, hands back a job_id for a long one."
icon: material/package-variant-closed
---

Compile source code and binaries into a [symbol library](../../../../compile/link/#symbol-library): a per-file `.10x.json` unit for each source file, plus a single linked `.10x.tar` that the 10x runtime later uses to assign hidden classes (TenXTemplates) to log events.

The call is bounded-synchronous. It waits inline up to `max_wait_ms` (default 45s), so a small compile, and every re-run, finishes inside the wait and returns the finished library plus the full scan and link diagnostics in one call.

A long first compile of a large tree overruns the wait and returns a running `job_id` to poll with [Status](compile-status.md). The run is detached and writes to a pinned output folder, so calling Compile again later with the same arguments collects the finished library near-instantly.

Set `max_wait_ms: 0` to return the `job_id` immediately for fire-and-forget.

Sources combine freely in one call:

- a local folder (`source_path`)
- [GitHub repositories](../../../../compile/pull/github/) (`github_repos`)
- [docker/OCI images](../../../../compile/pull/docker/) (`docker_images`)
- [Helm charts](../../../../compile/pull/helm/) (`helm_charts`, a meta-source that renders the chart and pulls the images it references)
- [Artifactory artifacts](../../../../compile/pull/artifactory/) (`artifactory_instance` + `artifactory_repo`)

Docker pulls are daemonless. GitHub and Artifactory pulls each need a token, even for public GitHub repos.

The [Compiler app](../../../compiler/) runs the Compiler flavor, docker-first via the `log10x/compiler-10x` image or a local Compiler-flavor `tenx`. It runs without Kubernetes, a deployed app, or a Log10x account.

## :material-code-braces: Example

!!! tenx-ask "You"

    build a symbol library from `./payments-svc` and the grafana image

!!! tenx-answer "Log10x"

    Compile done in 38s: 214 units → `/tmp/log10x-mcp-compile/symbols-9f2c1a/symbols/symbols.10x.tar` (4.2 MB). 3 files failed to scan (go 2, python 1). Symbols by type: class 1,840, log 612, exec 410, enum 96.

!!! tenx-ask "You"

    re-run it after I prune the units

!!! tenx-answer "Log10x"

    Same source set, so the pinned output is reused: collected in 4s, no cold scan.

## :material-chat-question-outline: More to ask

- *"compile `apache/commons-cli` from GitHub"*
- *"scan this Helm chart and the images it references"*
- *"kick off a compile of the whole monorepo and hand me the job_id"*

## :material-check-decagram-outline: Prerequisites

The Compiler flavor needs one of two things: Docker running so the `log10x/compiler-10x` image can be pulled (the default), or a local Compiler-flavor `tenx` with `mode: "local"`. The Runtime flavor is refused.

GitHub pull (`github_repos`) needs a token even for public repos, passed as `github_token` or set as `GH_TOKEN` in the MCP server environment. Artifactory pull needs `artifactory_token` or `ARTIFACTORY_TOKEN`.

`.jar` files are not scanned directly, so provide extracted `.class` files.

## :material-code-json: Schema and samples

??? tenx-input-example "Input example"

    A local folder plus a public docker image, with the inline wait left at the 45s default.

    ```json
    {
      "source_path": "/home/dev/payments-svc",
      "docker_images": ["docker.io/grafana/grafana:11.1.0"],
      "library_name": "payments",
      "max_wait_ms": 45000
    }
    ```

??? tenx-input-schema "Input schema"

    Agent-facing JSON Schema (the canonical shape the MCP server publishes via `tools/list`). At least one source is required; the sources combine freely.

    ```json
    {
      "type": "object",
      "properties": {
        "source_path": {
          "type": "string",
          "description": "Absolute path to a local folder of source code / binaries to scan. The compiler recursively traverses it for supported languages (Java, Go, Python, JS/TS, Scala, C/C++, C#) and binaries. Note: .jar files are not scanned directly; provide extracted .class files. Optional when github_repos is given; at least one source (source_path and/or github_repos) is required."
        },
        "github_repos": {
          "type": "array",
          "items": { "type": "string" },
          "description": "GitHub repositories to pull (via the GitHub REST API) and scan, each as owner/repo (e.g. [\"apache/commons-cli\"]). REQUIRES a GitHub token, even for public repos: pass github_token, or have GH_TOKEN / GITHUB_TOKEN set in the MCP server environment. Combines freely with source_path."
        },
        "github_branch": {
          "type": "string",
          "description": "Branch to pull for ALL github_repos. Omit to pull each repo's default branch."
        },
        "github_folders": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Folders within each GitHub repo to pull (e.g. [\"src/main/java\"]). Omit to pull entire repos. Narrowing this speeds up both the pull and the scan."
        },
        "github_token": {
          "type": "string",
          "description": "GitHub access token for github_repos (a fine-grained token with read-only Contents access to the target repos suffices). Falls back to GH_TOKEN / GITHUB_TOKEN from the MCP server environment. Reaches the compiler as process environment only; never written to disk or argv. When docker_images are given too, this same token additionally lets the compiler pull + scan each image's source repo (the org.opencontainers.image.source annotation); without it that extra scan is skipped silently."
        },
        "docker_images": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Docker/OCI images to pull and scan for symbols, as image refs, fully-qualified recommended (e.g. [\"docker.io/grafana/grafana:11.1.0\"]; a port-bearing host like \"harbor.corp:8443/team/app:2.1\" is fine, and a bare \"alpine\" resolves against the engine default registry). The pull is daemonless (podman inside the compiler-10x image, no host docker socket), and the tool automatically grants the compile container `--cap-add SYS_ADMIN` (needed by podman; only when this arg is used). Public images need no credentials. docker_username + docker_token `docker login` to the DEFAULT registry (Docker Hub), so they cover private Docker Hub repos; images on a different private registry must be pre-authenticated on the host/engine. In mode=local the host needs a docker/podman CLI with a working engine, and pulled images are left in its store (remove:false). Combines freely with source_path and github_repos."
        },
        "docker_username": {
          "type": "string",
          "description": "Registry username for docker_images login, also used for private images a Helm chart references (helm_pull_images). Authenticates the default registry (Docker Hub). Falls back to DOCKER_USERNAME from the MCP server environment. Omit for public images. The engine logs in only when BOTH username and token are non-blank. Reaches the compiler as process environment only."
        },
        "docker_token": {
          "type": "string",
          "description": "Registry token/password for docker_images (fed to `docker login --password-stdin` against the default registry, Docker Hub). Falls back to DOCKER_TOKEN from the MCP server environment. Omit for public images; pair with docker_username. Reaches the compiler as process environment only."
        },
        "helm_charts": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Helm charts to render and scan, as chart refs. A meta-source: the compiler runs `helm template` / `helm show chart` to extract the docker images and GitHub source repos the chart references, then (by default) pulls those too. OCI refs (e.g. \"oci://ghcr.io/nginxinc/charts/nginx-ingress\") and full URLs resolve standalone; a bare \"repo/chart\" (e.g. \"ingress-nginx/ingress-nginx\") needs a matching helm_repos entry. Combines freely with the other sources. In mode=local the host needs the helm CLI and must have the repos already `helm repo add`-ed."
        },
        "helm_repos": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Helm chart repositories to register before resolving helm_charts, each as \"name=url\" (e.g. [\"ingress-nginx=https://kubernetes.github.io/ingress-nginx\"]). Required for bare \"repo/chart\" names; unnecessary for OCI/URL refs. Added via `helm repo add` in pre-step containers (docker mode only; in mode=local the host helm config is used as-is). url must be an http(s):// chart-repo index URL; for an OCI registry, put the oci://… ref directly in helm_charts (`helm repo add` does not support oci://)."
        },
        "helm_pull_images": {
          "type": "boolean",
          "default": true,
          "description": "Whether to pull + scan the docker images a chart references (the richest symbol source for a chart). Default true. When true the tool grants the compile container `--cap-add SYS_ADMIN` (daemonless podman), same as docker_images. Set false to scan only the chart template/values text."
        },
        "helm_pull_repos": {
          "type": "boolean",
          "default": false,
          "description": "Whether to pull + scan the GitHub source repos a chart references (via org.opencontainers.image.source annotations). Default false because it REQUIRES a GitHub token (engine refuses an empty token); enabling it without github_token / GH_TOKEN returns not_configured."
        },
        "artifactory_instance": {
          "type": "string",
          "description": "Base URL of an Artifactory instance to pull artifacts (Java archives, .NET assemblies, etc.) from and scan, e.g. \"https://demo.jfrog.io/artifactory\". Requires artifactory_repo and a token (artifactory_token or ARTIFACTORY_TOKEN). Pull is via the Artifactory REST API, no extra host privilege. Combines freely with the other sources."
        },
        "artifactory_repo": {
          "type": "string",
          "description": "Artifactory repository key to pull from, e.g. \"libs-release-local\". Required when artifactory_instance is given. Scope the pull with artifactory_files and/or artifactory_folders."
        },
        "artifactory_files": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Specific files within artifactory_repo to pull, each a repo-relative path (e.g. [\"dist/app-1.0.0.tar.gz\"]). Combine with artifactory_folders; at least one of the two is required when pulling from Artifactory."
        },
        "artifactory_folders": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Folder paths within artifactory_repo to pull (e.g. [\"com/acme/app\"]). Traversed recursively unless artifactory_recursive is false. At least one of artifactory_files / artifactory_folders is required when pulling from Artifactory."
        },
        "artifactory_recursive": {
          "type": "boolean",
          "default": true,
          "description": "Whether artifactory_folders are pulled recursively (sub-folders too). Default true. Ignored when only artifactory_files are given."
        },
        "artifactory_token": {
          "type": "string",
          "description": "Artifactory API access token for artifactory_instance. Falls back to ARTIFACTORY_TOKEN from the MCP server environment. Required when pulling from Artifactory. Reaches the compiler as process environment only; never written to disk or argv."
        },
        "output_path": {
          "type": "string",
          "description": "Absolute path where the symbol library is written (the .10x.json units and the linked .10x.tar). Defaults to a fresh temp directory, returned in the result as data.payload.output.folder."
        },
        "library_name": {
          "type": "string",
          "default": "symbols",
          "description": "Base name for the linked .10x.tar library file and the compile runtimeName. Sanitized to [A-Za-z0-9_.-]."
        },
        "mode": {
          "type": "string",
          "enum": ["auto", "docker", "local"],
          "default": "auto",
          "description": "Execution backend. `auto` (default) prefers Docker (cloud image, guaranteed Compiler flavor) and falls back to a local Compiler-flavor tenx. `docker` forces the image (LOG10X_COMPILER_IMAGE or LOG10X_TENX_IMAGE, default log10x/compiler-10x:latest). `local` forces the binary (LOG10X_TENX_PATH or `tenx` on PATH) and refuses if it is not the Compiler flavor. With a local install, local-folder compilation and GitHub pull (REST API + token) work out of the box; docker_images pull additionally needs a container engine (podman or docker) on the host. The docker `compiler-10x` image bundles all of those (podman included, daemonless), which is why Docker is the default."
        },
        "timeout_ms": {
          "type": "integer",
          "minimum": 10000,
          "maximum": 3600000,
          "default": 1800000,
          "description": "Hard cap on compile wall time in milliseconds. Default 1,800,000 (30 min). The first compile of a large codebase typically runs 10–30 min; subsequent runs are near-instant via checksum reuse."
        },
        "max_wait_ms": {
          "type": "integer",
          "minimum": 0,
          "maximum": 300000,
          "default": 45000,
          "description": "How long to wait inline (ms) for the compile to finish before handing back a job_id to poll. Default 45,000 (45s): small compiles and re-runs (which reuse prior units) finish inside this and return the library + diagnostics in ONE call. A long first compile of a large tree returns a running job_id you poll with log10x_compile_status, or just call this tool again later, since the output is pinned and a finished run is collected near-instantly. 0 = fire-and-forget (return the job_id immediately)."
        }
      },
      "additionalProperties": false
    }
    ```

    Source: [`src/tools/compile-run.ts`](https://github.com/log-10x/log10x-mcp/blob/main/src/tools/compile-run.ts).

??? tenx-output-example "Output example"

    Representative envelope for a compile that finished inside the wait. On completion the call returns the same typed payload that [Status](compile-status.md) returns: `job_id`, `job_status`, the `output` (unit count + linked library), and the scan/link `diagnostics`. The scan-health and link-report blocks populate once the `compiler-10x` image carries the engine diagnostics change; on an older image they degrade to unit counts plus the log tail.

    Headline (the 1-line agent-facing answer):

    > _Compile job `9f2c1a3e-...` done: 214 units → /tmp/log10x-mcp-compile/payments-9f2c1a/symbols/payments.10x.tar (4.2 MB), 3 files failed to scan._

    ```json
    {
      "schema_version": "1.0",
      "schema_epoch": "2026-05-25",
      "tool": "log10x_compile",
      "generated_at": "2026-05-26T15:37:46.392Z",
      "view": "summary",
      "summary": {
        "headline": "Compile job `9f2c1a3e-...` done: 214 units → /tmp/log10x-mcp-compile/payments-9f2c1a/symbols/payments.10x.tar (4.2 MB), 3 files failed to scan."
      },
      "data": {
        "status": "success",
        "decisions": { "threshold_used": null, "threshold_basis": "default" },
        "source_disclosure": {},
        "scope": {
          "window": "payments_compile",
          "window_basis": "explicit",
          "candidates_count": 214,
          "candidates_usable": 1
        },
        "payload": {
          "job_id": "9f2c1a3e-7b4d-4e1a-9f0c-2a1b3c4d5e6f",
          "job_status": "completed",
          "mode": "docker",
          "image": "log10x/compiler-10x:latest",
          "exit_code": 0,
          "elapsed_ms": 38120,
          "timed_out": false,
          "sources": "/home/dev/payments-svc + images docker.io/grafana/grafana:11.1.0",
          "output": {
            "folder": "/tmp/log10x-mcp-compile/payments-9f2c1a/symbols",
            "unit_count": 214,
            "empty_unit_count": 6,
            "library_files": [
              {
                "path": "/tmp/log10x-mcp-compile/payments-9f2c1a/symbols/payments.10x.tar",
                "bytes": 4404019
              }
            ]
          },
          "diagnostics": {
            "results_available": true,
            "phases": [
              {
                "operation": "scan",
                "status": "ok",
                "traversed_files": 1902,
                "scanned_files": 1899,
                "output_files": 214,
                "warns": 3,
                "errors": 0
              },
              {
                "operation": "link",
                "status": "ok",
                "traversed_files": 214,
                "scanned_files": 214,
                "output_files": 1,
                "warns": 0,
                "errors": 0
              }
            ],
            "scan_health": {
              "files_failed": 3,
              "failed_by_language": { "go": 2, "python": 1 },
              "failure_samples": [
                {
                  "name": "internal/ledger/gen.go",
                  "language": "go",
                  "reason": "parse error at line 84: unexpected token"
                }
              ]
            },
            "link_report": {
              "merged_files": 214,
              "skipped_files": 0,
              "excluded_by_folder": 11,
              "excluded_by_file_name": 2,
              "merged_repos_count": 2,
              "non_merged_repos_count": 0,
              "symbols_by_type": { "class": 1840, "log": 612, "exec": 410, "enum": 96 },
              "symbols_excluded_by_type": 73
            }
          },
          "log_tail": [
            "[link] merged 214 unit files into payments.10x.tar",
            "[link] symbols by type: class 1840, log 612, exec 410, enum 96"
          ]
        },
        "human_summary": "Compile job 9f2c1a3e-... completed via docker in 38s: 214 symbol units, linked to /tmp/log10x-mcp-compile/payments-9f2c1a/symbols/payments.10x.tar (4.2 MB). 6 units were emitted empty: every symbol filtered out (the default symbol.types keeps class/enum/log/exec only). 3 files failed to scan (top: go 2, python 1). Example: internal/ledger/gen.go, parse error at line 84: unexpected token. Linked 214 unit files (13 excluded by folder/name filters); symbols by type: class 1840, log 612, exec 410, enum 96."
      },
      "actions": [
        {
          "tool": "log10x_validate",
          "args": { "extra_args": [["symbolPaths", "/tmp/log10x-mcp-compile/payments-9f2c1a/symbols"]] },
          "reason": "smoke-test the compiled library against a few sample event lines (supply input_lines)"
        }
      ],
      "truncated": false,
      "warnings": []
    }
    ```

    A long first compile of a large tree overruns `max_wait_ms` and returns `job_status: "running"` with the `job_id` instead. Poll it with [Status](compile-status.md), or call Compile again later with the same arguments to collect the pinned output.

??? tenx-output-schema "Output schema"

    The `data.payload` block inside the [StructuredOutput envelope](../index.md#json-by-default-output). On inline completion the shape matches [Status](compile-status.md); on overrun (or `max_wait_ms: 0`) the running handle carries `job_status: "running"` plus `job_id`, `mode`, `image`, `library_file`, `runtime_name`, `sources`, `started_at`, `timeout_ms`, `log_file`, and `output_folder`.

    ```typescript
    interface CompilePayload {
      job_id: string;
      job_status: 'running' | 'completed' | 'failed' | 'timed_out';
      mode: 'docker' | 'local';
      image: string | null;
      exit_code: number | null;
      elapsed_ms: number;
      timed_out: boolean;
      sources: string;
      output: {
        folder: string;
        unit_count: number;
        empty_unit_count: number;
        library_files: Array<{ path: string; bytes: number }>;
      };
      diagnostics: {
        results_available: boolean;
        phases: Array<{
          operation: string | null;
          status: string | null;
          traversed_files: number | null;
          scanned_files: number | null;
          output_files: number | null;
          warns: number | null;
          errors: number | null;
        }>;
        scan_health: {
          files_failed: number;
          failed_by_language: Record<string, number>;
          failure_samples: Array<{ name: string; language: string; reason: string }>;
        } | null;
        link_report: {
          merged_files: number;
          skipped_files: number;
          excluded_by_folder: number;
          excluded_by_file_name: number;
          merged_repos_count: number;
          non_merged_repos_count: number;
          symbols_by_type: Record<string, number>;
          symbols_excluded_by_type: number;
        } | null;
      };
      log_tail: string[];
    }
    ```

    Envelope-level fields the agent should also read: `summary.headline` (1-line answer), `data.status` (`success` / `partial` / `error`), `data.human_summary` (prose distillation for chat), `actions[]` (next-call chain hints as `{tool, args, reason}`), `truncated: boolean`, `schema_epoch` (engine-ID stability boundary).
