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
Maintainers
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 agenthandleAfter installing, agenthandle is on your PATH. Verify with agenthandle --help.
Tip: If
npm install -gfails with a permission error, either usesudo 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` CLIQuick 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 serverCLI 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 forserial.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 thecargotoolchain, the stdout of the running process).logs/test.log— written whenagenthandle testor 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 runwon't start unless tests pass) - monitor →
cargo run(long-lived process; stdout/stderr streams toserial.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-serviceImportant: When you see
UPLOAD_FAILEDinbuild.log, it's not a flash/port error — it meanscargo testfailed. 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,--releaseif 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 STM32F103C8If the board also logs over a UART/serial line (not RTT), you can point
monitorat the built-in serial reader or another tool viacommands.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-serviceThe 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:3000Each 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:5173Renders 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 dirThat 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 onceCredentials — 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=s3cretCLI 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
--watchmode 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 globalgradle) - upload →
adb install -r <apk>(APK path derived from module/variant) - monitor → built-in
android-runhelper: launch (viaam start -nifactivityis set, launcher intent otherwise) +adb logcat --pid=<app> - test →
gradle :app:test<Variant>UnitTest(host unit tests; for instrumented tests setcommands.test/--test-cmdtoconnectedAndroidTest)
{
"toolchain": "android",
"sketch": ".",
"appId": "com.example.app",
"activity": ".MainActivity"
}agenthandle --watch --toolchain android --sketch . --app-id com.example.appRequires 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
.appon the simulator (built-inxcode-simhelper; boots the simulator automatically whensimulatoris a device name) - monitor →
simctl launch --console— the app'sprint/os_log output streams intologs/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 toserial.log) · test →swift test
agenthandle --watch --toolchain swift --sketch ./my-vapor-app --web-url http://localhost:8080Optional: 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 DebugGenerated 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 -rstConfigurable 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
stm32cubeideandSTM32_Programmer_CLIaren't on PATH, provide full paths viaideandprogrammer. 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
sttyand reads it — no extra tool needed. On Windows define a tool viacommands.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:
- Create a bot with @BotFather and get the token.
- Send your bot a message, then grab the
chat.idvalue from the output ofhttps://api.telegram.org/bot<TOKEN>/getUpdates. - 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-telegramFine-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 --bridgeLines 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"+ onlycommands.uploadfor 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 tofs.watchif 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 agenthandleKurulumdan sonra agenthandle komutu PATH'te olur. Doğrulamak için: agenthandle --help.
İpucu:
npm install -gizin hatası verirse yasudo 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ğlarHı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ğlanCLI 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 (veyacargotoolchain'inde çalışan sürecin) seri/stdout çıktısı.logs/test.log—agenthandle testveya "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çmedencargo runbaşlamaz) - monitor →
cargo run(uzun ömürlü süreç; stdout/stderrserial.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'daUPLOAD_FAILEDgördüğünde bu bir flash/port hatası değil,cargo testbaş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 STM32F103C8Board'da ayrıca bir UART/serial hattı üzerinden log basılıyorsa (RTT değil),
monitor'ucommands.monitorile 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-serviceSonuç 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:3000Her 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:5173Bir 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ştururBir 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 gezKimlik 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=s3cretCLI 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:
--watchmodunda 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 globalgradle) - upload →
adb install -r <apk>(APK yolu module/variant'tan türetilir) - monitor → yerleşik
android-runyardımcısı: başlat (activityverildiyseam start -n, verilmediyse launcher intent) +adb logcat --pid=<uygulama> - test →
gradle :app:test<Variant>UnitTest(host unit testleri; instrumented test içincommands.test/--test-cmdileconnectedAndroidTesttanımla)
{
"toolchain": "android",
"sketch": ".",
"appId": "com.example.app",
"activity": ".MainActivity"
}agenthandle --watch --toolchain android --sketch . --app-id com.example.appadb 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şikxcode-simyardımcısı;simulatorbir cihaz adıysa simülatörü otomatik boot eder) - monitor →
simctl launch --console— uygulamanınprint/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 -rstAyarlanabilir 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ı:
stm32cubeideveSTM32_Programmer_CLIPATH'te değilseideveprogrammerile tam yolu ver. macOS'ta IDE genelde/Applications/STM32CubeIDE.app/Contents/MacOS/stm32cubeidealtındadır.Serial monitör: Linux/macOS'ta yerleşik okuyucu portu
sttyile ayarlayıp okur — ek araç gerekmez. Windows'tacommands.monitor/--monitor-cmdile 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:
- @BotFather ile bir bot oluştur, token'ı al.
- Botuna bir mesaj at, sonra
https://api.telegram.org/bot<TOKEN>/getUpdatesçıktısındakichat.iddeğerini al. - 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-telegramConfig 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. Örntoolchain: "arduino-cli"+ sadececommands.uploadile ö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ğilsefs.watchfallback'ine düşer. - Serial monitör portu tuttuğu için upload'tan önce otomatik durdurulur, sonra yeniden başlatılır.
