Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Project Management

Six tools handle project setup, scaffolding, chip selection, settings checking, and IDF version pinning. Together they’re enough to take an empty folder to “ready to build” without you ever opening menuconfig.

ToolWhat it does
project.initCreate .espctl.toml and the build folder for a new project.
project.createCreate a new ESP-IDF project from a template (hello_world, blink, empty).
project.create_componentAdd a new component to an existing project.
set_targetChange the chip target for an existing project.
validate_configCheck that a .espctl.toml file is valid.
idf_select_version (alias idf.select_version)Figure out which IDF version a build will use.

project.init

Sets up an espctl project in a folder by creating .espctl.toml and the standard build subfolders.

Input:

{
  "target": "esp32s3",
  "idf_version": "v5.3.1",
  "name": "my-project"
}
FieldRequiredNotes
targetYesChip — esp32, esp32s2, esp32s3, esp32c2, esp32c3, esp32c6, esp32h2, esp32p4.
idf_versionNoPin a specific IDF version. Defaults to the build server’s latest stable.
nameNoFriendly project name (saved into .espctl.toml).

Returns:

{
  "project_root": "/path/to/project",
  "config_path": "/path/to/project/.espctl.toml",
  "target": "esp32s3",
  "idf_version_resolved": "v5.3.1"
}

What it does to your project folder:

  • Creates .espctl.toml if it doesn’t exist (won’t overwrite).
  • Creates build/ if it doesn’t exist.
  • Writes a default .idf-version file pinning the IDF version (if you asked for one).

project.init is safe to run twice — the second run does nothing.


project.create

Creates a brand-new ESP-IDF project from a template. Generates CMakeLists.txt, main/main.c, and optionally sdkconfig.defaults and .idf-version.

Input:

{
  "name": "my-sensor",
  "target": "esp32s3",
  "template": "hello_world"
}
FieldRequiredNotes
nameYesProject name (used as directory name). Alphanumeric, underscore, hyphen, 1-64 chars.
targetNoChip target. Written to sdkconfig.defaults.
versionNoIDF version to pin in .idf-version.
templateNo"hello_world" (default), "blink", or "empty".

Returns:

{
  "project_dir": "/path/to/my-sensor",
  "files_created": ["CMakeLists.txt", "main/main.c", "main/CMakeLists.txt"],
  "target": "esp32s3",
  "idf_version": "v5.3.1"
}

The project is created at <project_root>/<name>.


project.create_component

Adds a new component to an existing ESP-IDF project. Creates components/<name>/ with CMakeLists.txt, a header, and a source file.

Input:

{
  "name": "my_driver",
  "project_path": "/path/to/project"
}
FieldRequiredNotes
nameYesComponent name. Alphanumeric and underscore, 1-64 chars.
project_pathNoProject directory. Defaults to the server’s project root.

Returns:

{
  "component_dir": "components/my_driver",
  "files_created": ["CMakeLists.txt", "include/my_driver.h", "my_driver.c"]
}

set_target

Changes the chip target for a project that’s already been set up. Updates .espctl.toml, regenerates sdkconfig.defaults, and clears the build cache.

Input:

{ "target": "esp32c6" }

Returns:

{
  "previous_target": "esp32s3",
  "new_target": "esp32c6",
  "rebuild_required": true
}

Heads up: Switching chips always clears the build cache. Your next build will be a full rebuild from scratch. There’s no shortcut.


CLI: espctl set-target

A local helper that creates build/<target>/ and validates the chip name. It does not call the build server or update .espctl.toml — for the server-side equivalent, use the MCP set_target.run tool.

espctl set-target <target>

Inputs

ArgumentNotes
<target> (positional)One of esp32, esp32s2, esp32s3, esp32c2, esp32c3, esp32c6, esp32h2, esp32p4. Anything else exits with code 2 (invalid target).

Output

Human mode:

Target set to esp32s3 (build dir: /path/to/build/esp32s3)

JSON (--json):

{
  "target": "esp32s3",
  "build_dir": "/path/to/build/esp32s3"
}

What it actually does

  • Validates <target> against the supported chip list.
  • Creates build/<target>/ if it doesn’t exist (idempotent).
  • Writes nothing to .espctl.toml. The next espctl build reads the directory layout to decide where to put output.

Examples

# Switch project to ESP32-C3 (creates build/esp32c3/)
espctl set-target esp32c3

# JSON output for scripting
espctl --json set-target esp32s3

validate_config

Checks a .espctl.toml file and returns either “valid” or a structured error.

Input:

{
  "content": "[project]\nname = \"my-app\"\ntarget = \"esp32s3\"\n..."
}

You can also pass a path:

{ "path": "/path/to/.espctl.toml" }

Returns:

{
  "valid": true,
  "warnings": [],
  "normalized": { ... }
}

…or, on failure:

{
  "valid": false,
  "errors": [
    {
      "line": 7,
      "column": 14,
      "message": "unknown field `targe` (did you mean `target`?)"
    }
  ]
}

This tool is read-only and safe to call as often as you like — many assistants run it after every edit to .espctl.toml for live checking.


idf_select_version / idf.select_version

Tells you which IDF version a build will use, given the project settings, what the build server has, and any explicit pin.

Input:

{ "version": "v5.3.1" }

version is optional. When you leave it out, the tool figures it out based on the project’s preferences:

  1. Explicit version argument
  2. Project’s .idf-version file
  3. [idf] section in .espctl.toml
  4. Build server’s default

Returns:

{
  "resolved": "v5.3.1",
  "source": "explicit-argument",
  "store_path": "/var/lib/aegis/espctl-store/idf/v5.3.1",
  "alternatives": ["v5.2.2", "v5.4.0"]
}

source tells you why this version was picked, which is handy when a build picks an unexpected version. alternatives lists every other IDF version the build server has, so your assistant can suggest upgrades or downgrades.


See also