npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

agenthandle

v0.4.1

Published

Watch, compile, upload/run and log embedded (ESP/Arduino/STM32), Rust (cargo/probe-rs), Android (gradle/adb), iOS (xcodebuild/simctl) and Swift (SPM) projects — plus a background headless-Chrome web renderer for debugging frontends — so an AI agent can it

Readme

AgentHandle

English | Türkçe

An AI agent running in a sandbox (Claude etc.) cannot directly access physical devices connected over USB, like ESP/Arduino/STM32 boards — it can't compile, upload, or read serial output. It can't open a browser to look at a frontend, or drive an Android emulator / iOS Simulator either. AgentHandle is a small Node.js CLI bridge that closes this gap, running on the user's machine.

The agent edits code; AgentHandle detects the change, compiles it, uploads it to the device (or runs the process), listens to the serial port / process output, optionally renders the frontend in a background headless Chrome, and writes everything to plain log files. The agent reads those log files to assess the situation (compile error? what is the device printing? what does the page's console say, and what does it look like?) and keeps iterating.

 ┌──────────┐   code change   ┌──────────────┐   compile+upload  ┌─────────┐
 │  Agent   │ ───────────────▶│ AgentHandle  │ ─────────────────▶│ Device  │
 │ (Claude) │                 │  (--watch)   │◀──── serial ──────│ ESP/STM │
 └────┬─────┘                 └──┬───────┬───┘                   └─────────┘
      │   logs/build.log         │       │ render        ┌─────────────────┐
      │   logs/serial.log ◀──────┘       └──────────────▶│ headless Chrome │
      │   logs/web.log + web.png + web.html ◀────────────│   (frontend)    │
      └── reads & evaluates                              └─────────────────┘

Installation

Global (recommended)

To use the agenthandle command from anywhere:

# Global install from source, inside the project directory
npm install -g .

# (once published)  npm install -g agenthandle

After installing, agenthandle is on your PATH. Verify with agenthandle --help.

Tip: If npm install -g fails with a permission error, either use sudo npm install -g . or set a writable prefix:

npm config set prefix ~/.npm-global
export PATH="$HOME/.npm-global/bin:$PATH"   # add to .bashrc/.zshrc

Local (alternative)

npm install          # installs the chokidar dependency
npm link             # symlinks the 'agenthandle' command globally
# or run directly: node bin/agenthandle.js ...

Toolchain

The toolchain you use must also be installed on the machine. Built-in support: arduino-cli, platformio, esp-idf, stm32cubeide, cargo (Rust web/host), probe-rs (Rust embedded), android (Gradle + adb), xcode (iOS Simulator, macOS only), swift (Swift Package Manager) — or any tool via custom.

# Arduino / ESP
arduino-cli core install esp32:esp32     # example: ESP32 board package

# STM32CubeIDE: requires STM32CubeIDE + STM32CubeProgrammer (from ST)

# Rust: cargo ships with the Rust installation. For embedded flashing, also:
cargo install probe-rs-tools             # provides the `probe-rs` CLI

Quick start

# 1) Create a sample config + firmware in a new project directory
agenthandle init

# 2) Edit port / fqbn / sketch values in agenthandle.config.json

# 3a) Continuous watch mode — keep running while developing
agenthandle --watch --port /dev/ttyUSB0

# 3b) One-shot — ideal for agents: compile, upload, capture ~8s of serial, exit
agenthandle --once --port /dev/ttyUSB0

# 3c) Frontend debugging — render the page in a background headless Chrome
#     (console/JS errors → logs/web.log, screenshot → logs/web.png)
agenthandle --watch --toolchain cargo --sketch ./svc --web-url http://localhost:3000
agenthandle web --url http://localhost:5173      # attach to an already-running dev server

CLI arguments always override the config file.

Modes

  • --watch : Watches files. On every change it stops the serial monitor → compiles → uploads → restarts the monitor. Runs until Ctrl+C. The config file is watched too — save it and the settings reload in place, then the cycle re-runs with them (an invalid edit is reported and the previous settings keep running).
  • --once : Runs a single cycle, captures serial output for serial.captureMs (default 8000ms), then exits. Designed for deterministic invocation by an agent.

Options

| Flag | Description | |---|---| | --config <path> | Config file path (default ./agenthandle.config.json) | | --toolchain <name> | arduino-cli | platformio | esp-idf | stm32cubeide | cargo | probe-rs | android | xcode | swift | custom | | --port <port> | USB port (/dev/ttyUSB0, COM5, ...) | | --baud <n> | Serial baud (default 115200) | | --sketch <path> | Project/sketch directory | | --fqbn <fqbn> | arduino-cli board, e.g. esp32:esp32:esp32 | | --build-log <path> | Build log path | | --serial-log <path> | Serial log path | | --no-serial | Disable the serial monitor | | --capture-ms <n> | Serial capture duration in --once mode, ms (default 8000; 0 = indefinite, until Ctrl+C or the monitor process exits) | | --web-url <url> | Enable the background web renderer for this page — see Background web renderer for all --web-* flags | | --help, -h | Help | | --version, -v | Print the installed version (agenthandle v0.4.0) — handy for checking whether a global reinstall actually took |

Log files

Three separate files, reset on every cycle (the agent always sees the latest state):

  • logs/build.log — commands executed, compiler/upload output, and a status line at the end:
    • === STATUS: SUCCESS ===
    • === STATUS: COMPILE_FAILED (code N) ===
    • === STATUS: UPLOAD_FAILED (code N) ===
  • logs/serial.log — the device's serial output after upload (or, with the cargo toolchain, the stdout of the running process).
  • logs/test.log — written when agenthandle test or the "test" phase runs:
    • === STATUS: TEST_PASSED ===
    • === STATUS: TEST_FAILED (code N) ===

With the web renderer enabled there are three more: logs/web.log (console/JS errors/network, STATUS: RENDER_OK / RENDER_FAILED), logs/web.png (screenshot) and logs/web.html (DOM dump) — see Background web renderer.

Rust projects (cargo / probe-rs)

Two toolchains cover two different Rust scenarios.

cargo — web/host Rust projects (server, CLI, etc.)

No physical port/device; you don't need to set port. The three phases map as:

  • compile → cargo build
  • upload → cargo test (a "deploy gate" instead of flashing: cargo run won't start unless tests pass)
  • monitor → cargo run (long-lived process; stdout/stderr streams to serial.log)
{
  "toolchain": "cargo",
  "sketch": "./my-web-service",
  "logs": { "build": "./logs/build.log", "serial": "./logs/serial.log", "test": "./logs/test.log" }
}
agenthandle --watch --toolchain cargo --sketch ./my-web-service

Important: When you see UPLOAD_FAILED in build.log, it's not a flash/port error — it means cargo test failed. The command line ($ cargo test ...) makes this clear.

probe-rs — embedded Rust (flash to MCU)

chip is required (for probe-rs probe/MCU selection). No port needed.

  • compile → cargo build (with --target, --release if set)
  • upload → probe-rs download --chip <chip> <binary>
  • monitor → probe-rs attach --chip <chip> <binary> (RTT output)
{
  "toolchain": "probe-rs",
  "sketch": "./firmware-rs",
  "chip": "STM32F103C8",
  "target": "thumbv7m-none-eabi",
  "release": true
}
agenthandle --watch --toolchain probe-rs --sketch ./firmware-rs --chip STM32F103C8

If the board also logs over a UART/serial line (not RTT), you can point monitor at the built-in serial reader or another tool via commands.monitor.

Standalone test phase: agenthandle test

Both Rust toolchains also expose cargo test as an independent phase — a quick test run without waiting for the full build+run cycle:

agenthandle test --toolchain cargo --sketch ./my-web-service

The result is written to logs/test.log; flash requirements like port/fqbn are not checked. Other toolchains (arduino-cli, platformio, ...) have no test phase — define a command with commands.test or --test-cmd if you want one.

Background web renderer (frontend debugging)

The same log-file bridge, but for the browser: a headless Chrome running in the background loads your frontend so the agent can debug it without ever touching a browser. After every successful build cycle (and on demand) it produces:

  • logs/web.log — the page's console output ([console.log], [console.error], ...), JavaScript errors ([pageerror] with stack trace), failed/4xx-5xx requests ([request-failed], [http 404]), and a status line:

    • === STATUS: RENDER_OK ===
    • === STATUS: RENDER_FAILED (reason) ===

    In watch mode the page stays open, so console output keeps streaming into the file live after the STATUS line.

  • logs/web.png — a full-page screenshot (agents can read it as an image and see the UI).

  • logs/web.html — a DOM dump taken after the page settled.

Engine: puppeteer-core + the Chrome/Chromium/Edge already installed on your machine — no browser download. It's a regular dependency, so npm install (and the global npm install -g .) brings it in. If it's missing from AgentHandle's install, the renderer also resolves puppeteer-core from the watched project's node_modules before giving up. The Chrome executable is auto-detected; override with web.browser in the config or the AGENTHANDLE_CHROME env variable.

Tied to the build cycle

Pairs naturally with the cargo toolchain (the monitor phase is your web server) or any custom toolchain that starts a dev server. The renderer waits for the server to answer (up to readyTimeoutMs) before loading, so slow boots are fine:

{
  "toolchain": "cargo",
  "sketch": "./my-web-service",
  "web": { "enabled": true, "url": "http://localhost:3000" }
}
agenthandle --watch --toolchain cargo --sketch ./my-web-service --web-url http://localhost:3000
# or one-shot for agents:
agenthandle --once  --toolchain cargo --sketch ./my-web-service --web-url http://localhost:3000

Each cycle: compile → test → server starts → page (re)loads → logs + screenshot + DOM refresh. web.log is reset per cycle like the other logs.

Standalone: agenthandle web

Attach to an already-running dev server (vite, next dev, cargo run, ...) without the build cycle:

agenthandle web --url http://localhost:5173

Renders once, streams live console output for --web-capture-ms (default 8000ms; 0 = until Ctrl+C), then exits — deterministic, agent-friendly. Exit code is 0 on RENDER_OK, 1 otherwise.

URL list crawl with auto-login (web.pages)

Give the renderer a list of URLs instead of a single one and it walks them in order. If a page redirects to a login screen (detected by a visible password field, or a web.login.detect URL regex), it signs in with the configured username/password and returns to the target URL — session cookies persist across the rest of the list, so login happens once. For every page it writes a --- [i/N] url --- block into logs/web.log (console, JS errors, failed requests, [page-status] OK/FAILED), a PNG or JPEG screenshot logs/web-shots/NN-<name>.png|jpg and a DOM dump NN-<name>.html. The final line reads === STATUS: RENDER_OK (N/N pages) === (or RENDER_FAILED (k/N pages failed)).

{
  "web": {
    "enabled": true,
    "pages": [
      "http://localhost:3000/dashboard",
      "http://localhost:3000/reports",
      { "url": "http://localhost:3000/settings", "name": "settings" }
    ],
    "imageFormat": "jpeg",
    "login": { "userSelector": "#username" }
  }
}
export AGENTHANDLE_WEB_USER=admin AGENTHANDLE_WEB_PASS=...
agenthandle web --web-pages "http://localhost:3000/dashboard,http://localhost:3000/reports"

Ready-made config: agenthandle init --web

agenthandle init --web      # creates agenthandle.web.config.json in the current dir

That writes a complete, editable example for a web/frontend project — build commands, watch patterns, the URL list, login and screenshot settings:

{
  "toolchain": "custom",
  "sketch": ".",
  "commands": {
    "compile": ["npm", "run", "build"],
    "upload":  ["npm", "test"],
    "monitor": ["npm", "start"]
  },
  "watch": ["app/**/*.js", "app/**/*.html", "public/js/**/*.js", "public/css/**/*.css"],
  "ignore": ["**/node_modules/**", "**/logs/**", "**/.git/**", "**/build/**"],
  "logs": { "build": "./logs/build.log", "serial": "./logs/serial.log", "test": "./logs/test.log" },
  "serial": { "enabled": true, "captureMs": 8000 },

  "web": {
    "enabled": true,

    "pages": [
      "http://localhost:3000/",
      { "url": "http://localhost:3000/dashboard", "name": "dashboard" },
      { "url": "http://localhost:3000/reports?range=today", "name": "reports-today" },
      { "url": "http://localhost:3000/settings", "name": "settings" }
    ],

    "login": {
      "user": null,
      "pass": null,
      "userSelector": null,
      "passSelector": null,
      "submitSelector": null,
      "detect": "/login",
      "waitMs": 8000
    },

    "shotDir": "./logs/web-shots",
    "imageFormat": "png",
    "imageQuality": 80,
    "pageHtml": true,

    "log": "./logs/web.log",
    "viewport": { "width": 1440, "height": 900 },
    "waitUntil": "networkidle2",
    "readyTimeoutMs": 30000,
    "navTimeoutMs": 30000,
    "settleMs": 1000,
    "captureMs": 8000,
    "browser": null,
    "args": []
  }
}

Then:

agenthandle --config agenthandle.web.config.json --watch     # build + serve + crawl on every change
agenthandle --config agenthandle.web.config.json web         # just walk the pages once

Credentials — three places, in this order of precedence:

// 1. In the config file (simplest — keep the file out of git):
"login": { "user": "admin", "pass": "s3cret" }
# 2. On the command line:
agenthandle web --web-user admin --web-pass s3cret

# 3. Or env variables, leaving "user"/"pass" null in the config (safest for shared repos):
export AGENTHANDLE_WEB_USER=admin AGENTHANDLE_WEB_PASS=s3cret

CLI beats the config file, and the config file beats the env variables. If you do put the password in the config, add that file to .gitignore (or keep a credential-free agenthandle.web.config.json in git and a local copy with the password).

Config hot-reload: in --watch mode the config file itself is watched too. Save it and AgentHandle reloads the settings and re-runs the cycle with them — new pages, new credentials, new commands all take effect without restarting. If the edited file is invalid (broken JSON or a missing required field) it says so and keeps running with the previous settings.

What each web key does: pages is the list to walk (a bare URL, or {url, name} where name becomes the screenshot filename); login.detect is a URL regex that marks a page as the login screen (a visible password field is detected anyway, so this is optional); the three *Selector fields stay null unless auto-detection misses your form; shotDir + imageFormat control where and in what format the screenshots land; viewport sets the window size the pages are rendered at.

Credentials come from web.login.user/pass or (recommended) the AGENTHANDLE_WEB_USER / AGENTHANDLE_WEB_PASS env variables. Form fields are auto-detected (the password input, the first text/email input in its form, the submit button); override with web.login.userSelector / passSelector / submitSelector when auto-detection misses. To protect against account lockouts, at most one login attempt per cycle is made — after a rejected login the remaining pages are skipped with FAILED (login). The crawl also runs after every successful build cycle in --watch mode, and old NN-* files in the shots dir are cleaned at the start of each cycle.

Web options

| Flag / config | Description | |---|---| | --web-url <url> / web.url | Page to load; setting it enables the renderer | | --web / --no-web | Enable/disable using the config's url | | --web-log <path> / web.log | Log path (default ./logs/web.log) | | --web-screenshot <p> / web.screenshot | Screenshot path (--no-web-screenshot disables) | | --web-html <path> / web.html | DOM dump path (--no-web-html disables) | | --web-browser <path> / web.browser | Chrome executable (default: auto-detect) | | --web-ready-ms <n> / web.readyTimeoutMs | Max wait for the server to come up (default 30000) | | --web-nav-ms <n> / web.navTimeoutMs | Page-load timeout (default 30000) | | --web-settle-ms <n> / web.settleMs | Wait after load before the screenshot (default 1000) | | --web-capture-ms <n> / web.captureMs | Live capture window in agenthandle web (default 8000; 0 = Ctrl+C) | | web.viewport | { "width": 1280, "height": 800 } | | web.waitUntil | load | domcontentloaded | networkidle0 | networkidle2 (default) | | web.args | Extra Chrome args, e.g. ["--no-sandbox"] for containers | | --version, -v | Print the version and exit (agenthandle v0.4.0) | | --web-pages <l> / web.pages | Crawl mode: comma-separated URL list (config: array of strings or {url, name}) | | --web-user / --web-pass | Login credentials (prefer AGENTHANDLE_WEB_USER / AGENTHANDLE_WEB_PASS env) | | --web-login-detect <regex> / web.login.detect | Login-page URL pattern (default detection: visible password field) | | web.login.userSelector etc. | CSS selectors for the login form when auto-detection misses | | --web-shot-dir <p> / web.shotDir | Crawl screenshots/dumps dir (default ./logs/web-shots) | | --web-image-format <f> / web.imageFormat | png (default) | jpg | | --web-image-quality <n> / web.imageQuality | JPEG quality 1-100 (default 80) | | web.pageHtml | Also write a DOM dump per crawled page (default true) |

Android apps

Gradle build + adb install + auto-launch with pid-filtered logcat: after every cycle the built-in runner clears logcat, force-stops and relaunches your app on the connected device/emulator, then streams only your app's log lines into logs/serial.log — no system noise for the agent to dig through.

  • compile → <gradlew> :app:assembleDebug (the project's Gradle wrapper is auto-detected; falls back to global gradle)
  • upload → adb install -r <apk> (APK path derived from module/variant)
  • monitor → built-in android-run helper: launch (via am start -n if activity is set, launcher intent otherwise) + adb logcat --pid=<app>
  • test → gradle :app:test<Variant>UnitTest (host unit tests; for instrumented tests set commands.test / --test-cmd to connectedAndroidTest)
{
  "toolchain": "android",
  "sketch": ".",
  "appId": "com.example.app",
  "activity": ".MainActivity"
}
agenthandle --watch --toolchain android --sketch . --app-id com.example.app

Requires adb on PATH and a connected device or running emulator (adb devices). Optional fields (all with sane defaults): module (app), variant (debug), apk, device (adb serial, only needed with multiple devices), adb, gradle. Crashes show up in serial.log as FATAL EXCEPTION; a failing adb install usually means no device/emulator is connected.

Swift apps

Two toolchains for two scenarios — same split as Rust's cargo/probe-rs.

xcode — iOS Simulator (macOS only)

  • compile → xcodebuild build (into a project-local derived-data dir)
  • upload → install the .app on the simulator (built-in xcode-sim helper; boots the simulator automatically when simulator is a device name)
  • monitor → simctl launch --console — the app's print/os_log output streams into logs/serial.log
  • test → xcodebuild test
{
  "toolchain": "xcode",
  "sketch": ".",
  "scheme": "MyApp",
  "bundleId": "com.example.MyApp",
  "simulator": "iPhone 16"
}
agenthandle --once --toolchain xcode --sketch . --scheme MyApp \
  --bundle-id com.example.MyApp --simulator "iPhone 16"

scheme and bundleId are required. With simulator unset, the currently booted simulator is used (boot one first: xcrun simctl boot "iPhone 16"). Optional: configuration (Debug), xcworkspace/xcodeproj, derivedData, appName, binary (explicit .app path).

swift — Swift Package Manager (CLI/server, e.g. Vapor)

The Swift twin of the cargo toolchain — no simulator, no port:

  • compile → swift build · upload → swift test (deploy gate) · monitor → swift run (long-lived; output streams to serial.log) · test → swift test
agenthandle --watch --toolchain swift --sketch ./my-vapor-app --web-url http://localhost:8080

Optional: packagePath (defaults to sketch), --release, binaryName (pick a specific executable for swift run). If it serves a frontend, pair it with the web renderer as above.

STM32CubeIDE projects

Built-in toolchain for STM32CubeIDE projects: headless build (STM32CubeIDE CLI) + flash (STM32CubeProgrammer CLI) + built-in serial monitor (dependency-free).

{
  "toolchain": "stm32cubeide",
  "port": "/dev/ttyACM0",
  "baud": 115200,
  "sketch": "/path/to/MyProject",
  "buildConfig": "Debug",
  "interface": "SWD",
  "logs": { "build": "./logs/build.log", "serial": "./logs/serial.log" }
}
agenthandle --watch --toolchain stm32cubeide --port /dev/ttyACM0 \
  --project /path/to/MyProject --build-config Debug

Generated commands:

# build (headless managed build)
stm32cubeide --launcher.suppressErrors -nosplash \
  -application org.eclipse.cdt.managedbuilder.core.headlessbuild \
  -data <workspace> -import <project> -build <projectName>/<buildConfig>

# flash
STM32_Programmer_CLI -c port=SWD -w <project>/<buildConfig>/<projectName>.elf -rst

Configurable fields (all have defaults): project (defaults to sketch), projectName (directory name), buildConfig (Debug), workspace (auto-derived), binary (<proj>/<config>/<name>.elf), ide, programmer, interface (SWD/JTAG).

Tool paths: If stm32cubeide and STM32_Programmer_CLI aren't on PATH, provide full paths via ide and programmer. On macOS the IDE is usually at /Applications/STM32CubeIDE.app/Contents/MacOS/stm32cubeide.

Serial monitor: On Linux/macOS the built-in reader configures the port with stty and reads it — no extra tool needed. On Windows define a tool via commands.monitor / --monitor-cmd (e.g. pyserial-miniterm {port} {baud}).

Telegram notifications

Sends the build/upload result (success / compile error / upload error) to your phone as a Telegram message. Dependency-free (Node https).

Setup:

  1. Create a bot with @BotFather and get the token.
  2. Send your bot a message, then grab the chat.id value from the output of https://api.telegram.org/bot<TOKEN>/getUpdates.
  3. Keeping the token in an env variable is recommended over putting it in the config:
export AGENTHANDLE_TELEGRAM_TOKEN="123456:ABC..."
export AGENTHANDLE_TELEGRAM_CHAT_ID="987654321"
agenthandle test-telegram            # verify the setup
agenthandle --watch --port /dev/ttyUSB0 --notify-telegram

Fine-tuning via config:

{
  "notify": {
    "telegram": {
      "enabled": true,
      "on": ["success", "compile_failed", "upload_failed"],
      "includeSerial": false
    }
  }
}

Failure notifications include the last lines of build.log; with includeSerial: true, success notifications include the tail of serial.log.

Two-way chat bridge (TelegramMessages.txt)

AgentHandle can bridge a file and Telegram in both directions:

  • File → Telegram: When a new line is appended to TelegramMessages.txt (e.g. by the agent), that line is forwarded to you on Telegram.
  • Telegram → File: When you send a message on Telegram, it's appended to the file as [user] ..., so the agent can read your reply.
# Bridge on its own
agenthandle bridge

# or together with watch
agenthandle --watch --port /dev/ttyUSB0 --notify-telegram --bridge

Lines starting with [user] come from Telegram and are not forwarded back (loop protection). Existing history in the file isn't sent when the bridge starts; only new lines go out. File path: notify.telegram.bridge.file or --telegram-file.

Driving any tool (custom commands)

AgentHandle isn't limited to the built-in toolchains — the commands themselves are parameters. With commands you can drive any compile/upload/monitor tool (make, cmake, avrdude, openocd, st-flash, dfu-util, a shell script, ...) without code changes. When commands is defined it overrides the selected toolchain for that phase.

Via config:

{
  "toolchain": "custom",
  "port": "/dev/ttyACM0",
  "baud": 115200,
  "sketch": "./fw",
  "vars": { "addr": "0x08000000", "bin": "build/fw.bin" },
  "commands": {
    "compile": ["make", "-C", "{sketch}"],
    "upload":  ["st-flash", "write", "{bin}", "{addr}"],
    "monitor": ["pyserial-miniterm", "{port}", "{baud}"]
  }
}

Via CLI (quick override):

agenthandle --once --port /dev/ttyACM0 \
  --compile-cmd "make" \
  --upload-cmd  "st-flash write build/fw.bin 0x8000000" \
  --monitor-cmd "pyserial-miniterm {port} {baud}"

Placeholders

{port} {baud} {fqbn} {sketch} {buildDir} are always available. Every key you put under vars is also usable as {key} (or {vars.key}). A command template can be an array (recommended, no quoting headaches) or a string.

To override just one phase, keep the named toolchain and put only that phase in commands. E.g. toolchain: "arduino-cli" + only commands.upload for a custom flasher.

Adding a built-in toolchain

To make a frequently used toolchain built-in, add a new adapter returning compile / upload / monitor to the REGISTRY in src/toolchains.js. Skeletons exist for platformio and esp-idf; arduino-cli is fully implemented.

Notes

  • Single external dependency: chokidar (file watching). Falls back to fs.watch if not installed.
  • The serial monitor holds the port, so it's automatically stopped before upload and restarted after.

AgentHandle (Türkçe)

English | Türkçe

Sandbox içinde çalışan bir AI agent (Claude vb.) ESP/Arduino/STM32 gibi USB'ye bağlı fiziksel cihazlara doğrudan erişemez — derleyemez, upload edemez, seri çıktıyı okuyamaz. Bir frontend'e bakmak için tarayıcı, Android emülatörü veya iOS Simulator da açamaz. AgentHandle bu boşluğu kapatan, kullanıcının makinesinde çalışan küçük bir Node.js CLI köprüsüdür.

Agent kodu değiştirir; AgentHandle değişikliği yakalar, derler, cihaza upload eder (veya süreci çalıştırır), seri portu / süreç çıktısını dinler, istenirse frontend'i arkaplanda headless bir Chrome ile render eder ve her şeyi düz log dosyalarına yazar. Agent bu log dosyalarını okuyup durumu (derleme hatası mı, cihaz ne basıyor, sayfanın console'u ne diyor, arayüz nasıl görünüyor) değerlendirir ve iterasyona devam eder.

 ┌──────────┐   kod değişir   ┌──────────────┐   derle+upload    ┌─────────┐
 │  Agent   │ ───────────────▶│ AgentHandle  │ ─────────────────▶│  Cihaz  │
 │ (Claude) │                 │  (--watch)   │◀──── serial ──────│ ESP/STM │
 └────┬─────┘                 └──┬───────┬───┘                   └─────────┘
      │   logs/build.log         │       │ render        ┌─────────────────┐
      │   logs/serial.log ◀──────┘       └──────────────▶│ headless Chrome │
      │   logs/web.log + web.png + web.html ◀────────────│   (frontend)    │
      └── okur & değerlendirir                           └─────────────────┘

Kurulum

Global (önerilen)

agenthandle komutunu her yerden kullanmak için:

# Proje dizininden, kaynaktan global kurulum
npm install -g .

# (yayınlandıktan sonra)  npm install -g agenthandle

Kurulumdan sonra agenthandle komutu PATH'te olur. Doğrulamak için: agenthandle --help.

İpucu: npm install -g izin hatası verirse ya sudo npm install -g . kullan ya da yazılabilir bir prefix ayarla:

npm config set prefix ~/.npm-global
export PATH="$HOME/.npm-global/bin:$PATH"   # .bashrc/.zshrc'ye ekle

Yerel (alternatif)

npm install          # chokidar bağımlılığını kurar
npm link             # 'agenthandle' komutunu global sembolik linkler
# veya doğrudan: node bin/agenthandle.js ...

Toolchain

Kullanacağın toolchain'in ayrıca makinede kurulu olması gerekir. Yerleşik destek: arduino-cli, platformio, esp-idf, stm32cubeide, cargo (Rust web/host), probe-rs (Rust embedded), android (Gradle + adb), xcode (iOS Simulator, yalnız macOS), swift (Swift Package Manager) — ya da custom ile herhangi bir araç.

# Arduino / ESP
arduino-cli core install esp32:esp32     # örnek: ESP32 board paketi

# STM32CubeIDE: STM32CubeIDE + STM32CubeProgrammer kurulu olmalı (ST'den)

# Rust: cargo zaten Rust kurulumuyla gelir. Embedded flash için ayrıca:
cargo install probe-rs-tools             # `probe-rs` CLI'ı sağlar

Hızlı başlangıç

# 1) Yeni bir proje dizininde örnek config + firmware oluştur
agenthandle init

# 2) agenthandle.config.json içindeki port / fqbn / sketch değerlerini düzenle

# 3a) Sürekli izleme modu — geliştirirken açık bırak
agenthandle --watch --port /dev/ttyUSB0

# 3b) Tek seferlik — agent için ideal: derle, upload, ~8sn serial yakala, çık
agenthandle --once --port /dev/ttyUSB0

# 3c) Frontend debug — sayfayı arkaplanda headless Chrome ile render et
#     (console/JS hataları → logs/web.log, ekran görüntüsü → logs/web.png)
agenthandle --watch --toolchain cargo --sketch ./svc --web-url http://localhost:3000
agenthandle web --url http://localhost:5173      # zaten çalışan dev server'a bağlan

CLI argümanları her zaman config dosyasını override eder.

Modlar

  • --watch : Dosyaları izler. Her değişiklikte serial monitörü durdurur → derler → upload eder → monitörü yeniden başlatır. Ctrl+C'ye kadar çalışır. Config dosyası da izlenir — kaydettiğin anda ayarlar yeniden yüklenir ve döngü yeni ayarlarla çalışır (geçersiz düzenleme bildirilir, önceki ayarlarla devam edilir).
  • --once : Tek döngü çalıştırır, seri çıktıyı serial.captureMs (varsayılan 8000ms) boyunca yakalar ve çıkar. Agent'ın deterministik şekilde çağırması için tasarlandı.

Seçenekler

| Bayrak | Açıklama | |---|---| | --config <path> | Config dosyası yolu (varsayılan ./agenthandle.config.json) | | --toolchain <name> | arduino-cli | platformio | esp-idf | stm32cubeide | cargo | probe-rs | android | xcode | swift | custom | | --port <port> | USB portu (/dev/ttyUSB0, COM5, ...) | | --baud <n> | Serial baud (varsayılan 115200) | | --sketch <path> | Proje/sketch dizini | | --fqbn <fqbn> | arduino-cli board, örn esp32:esp32:esp32 | | --build-log <path> | Build log yolu | | --serial-log <path> | Serial log yolu | | --no-serial | Serial monitörü kapat | | --capture-ms <n> | --once'ta serial yakalama süresi, ms (varsayılan 8000; 0 = süresiz, Ctrl+C'ye veya monitör süreci çıkana kadar) | | --web-url <url> | Arkaplan web renderer'ı bu sayfa için aç — tüm --web-* bayrakları için bkz. Arkaplan web renderer | | --help, -h | Yardım | | --version, -v | Kurulu sürümü yazar (agenthandle v0.4.0) — global kurulumun gerçekten güncellenip güncellenmediğini kontrol etmek için |

Log dosyaları

Her döngüde sıfırlanan üç ayrı dosya (agent her zaman en güncel durumu görür):

  • logs/build.log — çalıştırılan komutlar, derleyici/upload çıktısı ve sonda durum satırı:
    • === STATUS: SUCCESS ===
    • === STATUS: COMPILE_FAILED (code N) ===
    • === STATUS: UPLOAD_FAILED (code N) ===
  • logs/serial.log — upload sonrası cihazın (veya cargo toolchain'inde çalışan sürecin) seri/stdout çıktısı.
  • logs/test.log — agenthandle test veya "test" fazı çalıştığında yazılır:
    • === STATUS: TEST_PASSED ===
    • === STATUS: TEST_FAILED (code N) ===

Web renderer açıksa üç dosya daha eklenir: logs/web.log (console/JS hatası/network, STATUS: RENDER_OK / RENDER_FAILED), logs/web.png (ekran görüntüsü) ve logs/web.html (DOM dökümü) — bkz. Arkaplan web renderer.

Rust projeleri (cargo / probe-rs)

İki farklı Rust senaryosu için iki toolchain var.

cargo — web/host Rust projeleri (server, CLI, vb.)

Fiziksel port/cihaz yok; port belirtmen gerekmez. Üç faz şu şekilde eşlenir:

  • compile → cargo build
  • upload → cargo test (flash yerine bir "deploy kapısı": testler geçmeden cargo run başlamaz)
  • monitor → cargo run (uzun ömürlü süreç; stdout/stderr serial.log'a akar)
{
  "toolchain": "cargo",
  "sketch": "./my-web-service",
  "logs": { "build": "./logs/build.log", "serial": "./logs/serial.log", "test": "./logs/test.log" }
}
agenthandle --watch --toolchain cargo --sketch ./my-web-service

Önemli: build.log'da UPLOAD_FAILED gördüğünde bu bir flash/port hatası değil, cargo test başarısız oldu demektir — komut satırı ($ cargo test ...) bunu gösterir.

probe-rs — embedded Rust (MCU'ya flash)

chip zorunlu (probe-rs'in probe/MCU seçimi için). port gerekmez.

  • compile → cargo build (varsa --target, --release)
  • upload → probe-rs download --chip <chip> <binary>
  • monitor → probe-rs attach --chip <chip> <binary> (RTT çıktısı)
{
  "toolchain": "probe-rs",
  "sketch": "./firmware-rs",
  "chip": "STM32F103C8",
  "target": "thumbv7m-none-eabi",
  "release": true
}
agenthandle --watch --toolchain probe-rs --sketch ./firmware-rs --chip STM32F103C8

Board'da ayrıca bir UART/serial hattı üzerinden log basılıyorsa (RTT değil), monitor'u commands.monitor ile yerleşik serial okuyucuya veya başka bir araca yönlendirebilirsin.

Bağımsız test fazı: agenthandle test

Her iki Rust toolchain'i de cargo test'i ayrıca bağımsız bir faz olarak sağlar — tam build+run döngüsünü beklemeden hızlı bir test çalıştırması için:

agenthandle test --toolchain cargo --sketch ./my-web-service

Sonuç logs/test.log'a yazılır; port/fqbn gibi flash gereksinimleri aranmaz. Diğer toolchain'lerde (arduino-cli, platformio, ...) test fazı tanımlı değildir — kullanmak istersen commands.test veya --test-cmd ile bir komut tanımlaman gerekir.

Arkaplan web renderer (frontend debug)

Aynı log-dosyası köprüsü, bu kez tarayıcı için: arkaplanda çalışan headless bir Chrome frontend'ini yükler; agent tarayıcıya hiç dokunmadan frontend'i debug edebilir. Her başarılı build döngüsünden sonra (ve istendiğinde) üç dosya üretilir:

  • logs/web.log — sayfanın console çıktısı ([console.log], [console.error], ...), JavaScript hataları ([pageerror] + stack trace), başarısız/4xx-5xx istekler ([request-failed], [http 404]) ve durum satırı:

    • === STATUS: RENDER_OK ===
    • === STATUS: RENDER_FAILED (sebep) ===

    Watch modunda sayfa açık kalır; STATUS satırından sonra console çıktısı dosyaya canlı akmaya devam eder.

  • logs/web.png — tam sayfa ekran görüntüsü (agent görüntü olarak okuyup arayüzü görebilir).

  • logs/web.html — sayfa oturduktan sonra alınan DOM dökümü.

Motor: puppeteer-core + makinede zaten kurulu olan Chrome/Chromium/Edge — browser indirmez. Normal bir bağımlılıktır; npm install (ve global npm install -g .) onu da kurar. AgentHandle kurulumunda yoksa renderer, pes etmeden önce puppeteer-core'u izlenen projenin node_modules'ünden de çözmeyi dener. Chrome çalıştırılabiliri otomatik bulunur; config'te web.browser veya AGENTHANDLE_CHROME env ile override et.

Build döngüsüne bağlı

cargo toolchain'iyle doğal eşleşir (monitor fazı zaten web server'ındır) ya da dev server başlatan herhangi bir custom toolchain'le kullanılır. Renderer sayfayı yüklemeden önce server'ın cevap vermesini bekler (en çok readyTimeoutMs), yavaş boot sorun değil:

{
  "toolchain": "cargo",
  "sketch": "./my-web-service",
  "web": { "enabled": true, "url": "http://localhost:3000" }
}
agenthandle --watch --toolchain cargo --sketch ./my-web-service --web-url http://localhost:3000
# veya agent için tek seferlik:
agenthandle --once  --toolchain cargo --sketch ./my-web-service --web-url http://localhost:3000

Her döngü: derle → test → server başlar → sayfa (yeniden) yüklenir → log + screenshot + DOM tazelenir. web.log diğer loglar gibi her döngüde sıfırlanır.

Bağımsız: agenthandle web

Zaten çalışan bir dev server'a (vite, next dev, cargo run, ...) build döngüsü olmadan bağlan:

agenthandle web --url http://localhost:5173

Bir kez render eder, --web-capture-ms süresince canlı console çıktısı toplar (varsayılan 8000ms; 0 = Ctrl+C'ye kadar) ve çıkar — deterministik, agent dostu. Çıkış kodu RENDER_OK'ta 0, aksi halde 1.

URL listesi crawl + otomatik login (web.pages)

Renderer'a tek URL yerine URL listesi ver, sırayla gezsin. Bir sayfa login ekranına yönlendirilirse (görünür password alanı ya da web.login.detect URL regex'i ile tespit edilir) tanımlı kullanıcı adı/şifreyle giriş yapar ve hedef URL'ye geri döner — oturum çerezleri listenin geri kalanında korunur, yani login bir kez yapılır. Her sayfa için logs/web.log'a --- [i/N] url --- bloğu (console, JS hataları, başarısız istekler, [page-status] OK/FAILED), PNG veya JPEG ekran görüntüsü logs/web-shots/NN-<isim>.png|jpg ve DOM dökümü NN-<isim>.html yazılır. Son satır: === STATUS: RENDER_OK (N/N pages) === (veya RENDER_FAILED (k/N pages failed)).

{
  "web": {
    "enabled": true,
    "pages": [
      "http://localhost:3000/dashboard",
      "http://localhost:3000/reports",
      { "url": "http://localhost:3000/settings", "name": "ayarlar" }
    ],
    "imageFormat": "jpeg",
    "login": { "userSelector": "#username" }
  }
}
export AGENTHANDLE_WEB_USER=admin AGENTHANDLE_WEB_PASS=...
agenthandle web --web-pages "http://localhost:3000/dashboard,http://localhost:3000/reports"

Hazır config: agenthandle init --web

agenthandle init --web      # bulunduğun dizinde agenthandle.web.config.json oluşturur

Bir web/frontend projesi için eksiksiz, düzenlenebilir bir örnek yazar — build komutları, izlenecek dosyalar, URL listesi, login ve ekran görüntüsü ayarları:

{
  "toolchain": "custom",
  "sketch": ".",
  "commands": {
    "compile": ["npm", "run", "build"],
    "upload":  ["npm", "test"],
    "monitor": ["npm", "start"]
  },
  "watch": ["app/**/*.js", "app/**/*.html", "public/js/**/*.js", "public/css/**/*.css"],
  "ignore": ["**/node_modules/**", "**/logs/**", "**/.git/**", "**/build/**"],
  "logs": { "build": "./logs/build.log", "serial": "./logs/serial.log", "test": "./logs/test.log" },
  "serial": { "enabled": true, "captureMs": 8000 },

  "web": {
    "enabled": true,

    "pages": [
      "http://localhost:3000/",
      { "url": "http://localhost:3000/dashboard", "name": "dashboard" },
      { "url": "http://localhost:3000/reports?range=today", "name": "reports-today" },
      { "url": "http://localhost:3000/settings", "name": "settings" }
    ],

    "login": {
      "user": null,
      "pass": null,
      "userSelector": null,
      "passSelector": null,
      "submitSelector": null,
      "detect": "/login",
      "waitMs": 8000
    },

    "shotDir": "./logs/web-shots",
    "imageFormat": "png",
    "imageQuality": 80,
    "pageHtml": true,

    "log": "./logs/web.log",
    "viewport": { "width": 1440, "height": 900 },
    "waitUntil": "networkidle2",
    "readyTimeoutMs": 30000,
    "navTimeoutMs": 30000,
    "settleMs": 1000,
    "captureMs": 8000,
    "browser": null,
    "args": []
  }
}

Sonra:

agenthandle --config agenthandle.web.config.json --watch     # her değişimde build + server + crawl
agenthandle --config agenthandle.web.config.json web         # sadece sayfaları bir kez gez

Kimlik bilgileri — üç yer, şu öncelik sırasıyla:

// 1. Doğrudan config dosyasında (en pratik — dosyayı git'e koyma):
"login": { "user": "admin", "pass": "s3cret" }
# 2. Komut satırında:
agenthandle web --web-user admin --web-pass s3cret

# 3. Ya da config'te "user"/"pass" null bırakıp env'de (paylaşılan repo için en güvenlisi):
export AGENTHANDLE_WEB_USER=admin AGENTHANDLE_WEB_PASS=s3cret

CLI config'i, config de env'i ezer. Şifreyi config'e yazacaksan o dosyayı .gitignore'a ekle (ya da git'te kimliksiz bir agenthandle.web.config.json, yanında yerel şifreli bir kopya tut).

Config hot-reload: --watch modunda config dosyasının kendisi de izlenir. Kaydettiğin anda ayarlar yeniden yüklenir ve döngü yeni ayarlarla çalışır — yeni sayfalar, yeni kimlik bilgileri, yeni komutlar; yeniden başlatmaya gerek yok. Düzenlediğin dosya geçersizse (bozuk JSON ya da eksik zorunlu alan) uyarır ve önceki ayarlarla çalışmaya devam eder.

Web anahtarlarının işlevi: pages gezilecek liste (düz URL ya da {url, name} — name ekran görüntüsünün dosya adı olur); login.detect bir sayfayı login ekranı sayan URL regex'i (görünür password alanı zaten tespit edildiği için opsiyoneldir); üç *Selector alanı otomatik tespit formunu bulamazsa doldurulur, aksi halde null kalır; shotDir + imageFormat görüntülerin nereye ve hangi biçimde yazılacağını, viewport sayfaların hangi pencere boyutunda render edileceğini belirler.

Kimlik bilgileri web.login.user/pass'ten ya da (önerilen) AGENTHANDLE_WEB_USER / AGENTHANDLE_WEB_PASS env değişkenlerinden okunur. Form alanları otomatik bulunur (password input'u, formundaki ilk text/email input, submit butonu); otomatik tespit tutmazsa web.login.userSelector / passSelector / submitSelector ile belirt. Hesap kilitlenmesine karşı tur başına en fazla 1 giriş denemesi yapılır — giriş reddedilirse kalan sayfalar FAILED (login) ile atlanır. Crawl --watch modunda her başarılı build döngüsünden sonra da çalışır; shots dizinindeki eski NN-* dosyaları her turun başında temizlenir.

Web seçenekleri

| Bayrak / config | Açıklama | |---|---| | --web-url <url> / web.url | Yüklenecek sayfa; verilince renderer açılır | | --web / --no-web | Config'teki url ile aç/kapat | | --web-log <path> / web.log | Log yolu (varsayılan ./logs/web.log) | | --web-screenshot <p> / web.screenshot | Ekran görüntüsü yolu (--no-web-screenshot kapatır) | | --web-html <path> / web.html | DOM dökümü yolu (--no-web-html kapatır) | | --web-browser <path> / web.browser | Chrome yolu (varsayılan: otomatik bul) | | --web-ready-ms <n> / web.readyTimeoutMs | Server'ın ayağa kalkmasını bekleme (varsayılan 30000) | | --web-nav-ms <n> / web.navTimeoutMs | Sayfa yükleme zaman aşımı (varsayılan 30000) | | --web-settle-ms <n> / web.settleMs | Yükleme sonrası screenshot öncesi bekleme (varsayılan 1000) | | --web-capture-ms <n> / web.captureMs | agenthandle web'de canlı izleme süresi (varsayılan 8000; 0 = Ctrl+C) | | web.viewport | { "width": 1280, "height": 800 } | | web.waitUntil | load | domcontentloaded | networkidle0 | networkidle2 (varsayılan) | | web.args | Ek Chrome argümanları, örn container için ["--no-sandbox"] | | --version, -v | Sürümü yazar ve çıkar (agenthandle v0.4.0) | | --web-pages <l> / web.pages | Crawl modu: virgülle ayrık URL listesi (config: string veya {url, name} dizisi) | | --web-user / --web-pass | Login kimlik bilgileri (önerilen: AGENTHANDLE_WEB_USER / AGENTHANDLE_WEB_PASS env) | | --web-login-detect <regex> / web.login.detect | Login sayfası URL deseni (varsayılan tespit: görünür password alanı) | | web.login.userSelector vb. | Otomatik tespit tutmazsa login formu CSS seçicileri | | --web-shot-dir <p> / web.shotDir | Crawl görüntü/döküm dizini (varsayılan ./logs/web-shots) | | --web-image-format <f> / web.imageFormat | png (varsayılan) | jpg | | --web-image-quality <n> / web.imageQuality | JPEG kalitesi 1-100 (varsayılan 80) | | web.pageHtml | Gezilen her sayfa için DOM dökümü de yaz (varsayılan true) |

Android uygulamaları

Gradle build + adb install + otomatik başlatma ve pid-filtreli logcat: her döngüde yerleşik koşucu logcat'i temizler, uygulamayı bağlı cihaz/emülatörde force-stop edip yeniden başlatır ve logs/serial.log'a yalnızca senin uygulamanın log satırlarını akıtır — agent'ın sistem gürültüsü içinde kaybolması gerekmez.

  • compile → <gradlew> :app:assembleDebug (projedeki Gradle wrapper otomatik bulunur; yoksa global gradle)
  • upload → adb install -r <apk> (APK yolu module/variant'tan türetilir)
  • monitor → yerleşik android-run yardımcısı: başlat (activity verildiyse am start -n, verilmediyse launcher intent) + adb logcat --pid=<uygulama>
  • test → gradle :app:test<Variant>UnitTest (host unit testleri; instrumented test için commands.test / --test-cmd ile connectedAndroidTest tanımla)
{
  "toolchain": "android",
  "sketch": ".",
  "appId": "com.example.app",
  "activity": ".MainActivity"
}
agenthandle --watch --toolchain android --sketch . --app-id com.example.app

adb PATH'te olmalı ve bir cihaz bağlı ya da emülatör açık olmalı (adb devices). İsteğe bağlı alanlar (hepsinin makul varsayılanı var): module (app), variant (debug), apk, device (adb serial; yalnız birden çok cihazda gerekir), adb, gradle. Crash'ler serial.log'da FATAL EXCEPTION olarak görünür; adb install hatası genelde cihaz/emülatör bağlı değil demektir.

Swift uygulamaları

İki senaryo için iki toolchain — Rust'taki cargo/probe-rs ayrımının aynısı.

xcode — iOS Simulator (yalnız macOS)

  • compile → xcodebuild build (proje içi derived-data dizinine)
  • upload → .app'i simülatöre kur (yerleşik xcode-sim yardımcısı; simulator bir cihaz adıysa simülatörü otomatik boot eder)
  • monitor → simctl launch --console — uygulamanın print/os_log çıktısı logs/serial.log'a akar
  • test → xcodebuild test
{
  "toolchain": "xcode",
  "sketch": ".",
  "scheme": "MyApp",
  "bundleId": "com.example.MyApp",
  "simulator": "iPhone 16"
}
agenthandle --once --toolchain xcode --sketch . --scheme MyApp \
  --bundle-id com.example.MyApp --simulator "iPhone 16"

scheme ve bundleId zorunlu. simulator verilmezse o an açık (booted) simülatör kullanılır (önce boot et: xcrun simctl boot "iPhone 16"). İsteğe bağlı: configuration (Debug), xcworkspace/xcodeproj, derivedData, appName, binary (açık .app yolu).

swift — Swift Package Manager (CLI/server, örn Vapor)

cargo toolchain'inin Swift ikizi — simülatör yok, port yok:

  • compile → swift build · upload → swift test (deploy kapısı) · monitor → swift run (uzun ömürlü; çıktısı serial.log'a akar) · test → swift test
agenthandle --watch --toolchain swift --sketch ./my-vapor-app --web-url http://localhost:8080

İsteğe bağlı: packagePath (varsayılan: sketch), --release, binaryName (swift run için belirli bir executable seç). Bir frontend servis ediyorsa yukarıdaki gibi web renderer ile eşleştir.

STM32CubeIDE projeleri

STM32CubeIDE projeleri için yerleşik toolchain hazır: headless build (STM32CubeIDE CLI) + flash (STM32CubeProgrammer CLI) + yerleşik serial monitör (bağımlılıksız).

{
  "toolchain": "stm32cubeide",
  "port": "/dev/ttyACM0",
  "baud": 115200,
  "sketch": "/path/to/MyProject",
  "buildConfig": "Debug",
  "interface": "SWD",
  "logs": { "build": "./logs/build.log", "serial": "./logs/serial.log" }
}
agenthandle --watch --toolchain stm32cubeide --port /dev/ttyACM0 \
  --project /path/to/MyProject --build-config Debug

Üretilen komutlar:

# derleme (headless managed build)
stm32cubeide --launcher.suppressErrors -nosplash \
  -application org.eclipse.cdt.managedbuilder.core.headlessbuild \
  -data <workspace> -import <project> -build <projectName>/<buildConfig>

# flash
STM32_Programmer_CLI -c port=SWD -w <project>/<buildConfig>/<projectName>.elf -rst

Ayarlanabilir alanlar (hepsinin varsayılanı var): project (varsayılan sketch), projectName (dizin adı), buildConfig (Debug), workspace (otomatik türetilir), binary (<proj>/<config>/<ad>.elf), ide, programmer, interface (SWD/JTAG).

Araç yolları: stm32cubeide ve STM32_Programmer_CLI PATH'te değilse ide ve programmer ile tam yolu ver. macOS'ta IDE genelde /Applications/STM32CubeIDE.app/Contents/MacOS/stm32cubeide altındadır.

Serial monitör: Linux/macOS'ta yerleşik okuyucu portu stty ile ayarlayıp okur — ek araç gerekmez. Windows'ta commands.monitor / --monitor-cmd ile bir araç tanımla (örn. pyserial-miniterm {port} {baud}).

Telegram bildirimleri

Build/upload sonucunu (başarılı / derleme hatası / upload hatası) telefonuna Telegram mesajı olarak gönderir. Bağımlılıksız (Node https).

Kurulum:

  1. @BotFather ile bir bot oluştur, token'ı al.
  2. Botuna bir mesaj at, sonra https://api.telegram.org/bot<TOKEN>/getUpdates çıktısındaki chat.id değerini al.
  3. Token'ı config'e koymak yerine env değişkeninde tutman önerilir:
export AGENTHANDLE_TELEGRAM_TOKEN="123456:ABC..."
export AGENTHANDLE_TELEGRAM_CHAT_ID="987654321"
agenthandle test-telegram            # kurulumu doğrula
agenthandle --watch --port /dev/ttyUSB0 --notify-telegram

Config ile ince ayar:

{
  "notify": {
    "telegram": {
      "enabled": true,
      "on": ["success", "compile_failed", "upload_failed"],
      "includeSerial": false
    }
  }
}

Hata bildirimlerine build.log'un son satırları, includeSerial: true ise başarıda serial.log kuyruğu eklenir.

İki yönlü sohbet köprüsü (TelegramMessages.txt)

AgentHandle, bir dosya ile Telegram arasında iki yönlü köprü kurabilir:

  • Dosya → Telegram: TelegramMessages.txt'ye yeni bir satır eklenince (örn. agent yazar) o satır sana Telegram'dan iletilir.
  • Telegram → Dosya: Sen Telegram'dan mesaj yazınca dosyaya [user] ... olarak eklenir; böylece agent senin cevabını okuyabilir.
# Tek başına köprü
agenthandle bridge

# veya watch ile birlikte
agenthandle --watch --port /dev/ttyUSB0 --notify-telegram --bridge

[user] ile başlayan satırlar Telegram'dan geldiği için tekrar Telegram'a iletilmez (döngü koruması). Köprü başladığında dosyadaki mevcut geçmiş iletilmez; yalnızca yeni eklenenler gider. Dosya yolu: notify.telegram.bridge.file veya --telegram-file.

Herhangi bir aracı sürme (custom komutlar)

AgentHandle sadece üç hazır toolchain ile sınırlı değil — komutların kendisi parametredir. commands ile herhangi bir derleme/upload/monitör aracını (make, cmake, avrdude, openocd, st-flash, dfu-util, bir shell script, ...) kod değiştirmeden sürebilirsin. commands tanımlandığında ilgili faz için seçili toolchain'i override eder.

Config ile:

{
  "toolchain": "custom",
  "port": "/dev/ttyACM0",
  "baud": 115200,
  "sketch": "./fw",
  "vars": { "addr": "0x08000000", "bin": "build/fw.bin" },
  "commands": {
    "compile": ["make", "-C", "{sketch}"],
    "upload":  ["st-flash", "write", "{bin}", "{addr}"],
    "monitor": ["pyserial-miniterm", "{port}", "{baud}"]
  }
}

CLI ile (hızlı override):

agenthandle --once --port /dev/ttyACM0 \
  --compile-cmd "make" \
  --upload-cmd  "st-flash write build/fw.bin 0x8000000" \
  --monitor-cmd "pyserial-miniterm {port} {baud}"

Placeholder'lar

{port} {baud} {fqbn} {sketch} {buildDir} her zaman vardır. vars altına koyduğun her anahtar da {key} (veya {vars.key}) olarak kullanılabilir. Komut şablonu dizi (önerilen, tırnak derdi yok) veya string olabilir.

Sadece bir fazı override etmek istersen named toolchain'i tutup yalnız o fazı commands'a koyabilirsin. Örn toolchain: "arduino-cli" + sadece commands.upload ile özel flasher.

Yerleşik toolchain ekleme

Sık kullanılan bir toolchain'i hazır hale getirmek istersen src/toolchains.js içindeki REGISTRY'ye compile / upload / monitor döndüren yeni bir adapter ekle. platformio ve esp-idf için iskelet hazır; arduino-cli tam implemente.

Notlar

  • Tek harici bağımlılık: chokidar (dosya izleme). Kurulu değilse fs.watch fallback'ine düşer.
  • Serial monitör portu tuttuğu için upload'tan önce otomatik durdurulur, sonra yeniden başlatılır.