{"id":51681066,"url":"https://github.com/abdullahwaqar/esp-workbench","last_synced_at":"2026-07-15T13:33:31.112Z","repository":{"id":369344176,"uuid":"1285244476","full_name":"abdullahwaqar/esp-workbench","owner":"abdullahwaqar","description":"TUI for ESP32 development with ESP-IDF. Auto-detect devices, build, flash, monitor, and manage partitions all in one terminal UI.","archived":false,"fork":false,"pushed_at":"2026-07-04T19:11:57.000Z","size":8081,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-07-04T21:07:05.412Z","etag":null,"topics":["development-tools","esp32","espidf","esptool","firmware-tools","terminal-ui","tui"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/abdullahwaqar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-30T16:03:12.000Z","updated_at":"2026-07-04T19:13:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/abdullahwaqar/esp-workbench","commit_stats":null,"previous_names":["abdullahwaqar/esp-workbench"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/abdullahwaqar/esp-workbench","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abdullahwaqar%2Fesp-workbench","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abdullahwaqar%2Fesp-workbench/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abdullahwaqar%2Fesp-workbench/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abdullahwaqar%2Fesp-workbench/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/abdullahwaqar","download_url":"https://codeload.github.com/abdullahwaqar/esp-workbench/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abdullahwaqar%2Fesp-workbench/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35507792,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-15T02:00:06.706Z","response_time":131,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["development-tools","esp32","espidf","esptool","firmware-tools","terminal-ui","tui"],"created_at":"2026-07-15T13:33:30.539Z","updated_at":"2026-07-15T13:33:31.105Z","avatar_url":"https://github.com/abdullahwaqar.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# esp-workbench\n\nTUI for ESP32 development with ESP-IDF.\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"docs/demo.gif\" alt=\"Demo\"\u003e\n\u003c/div\u003e\n\n## Features\n\n- Auto-scans connected ESP32 devices on Linux, macOS, Windows\n- Live streaming logs with color-coded severity (error / warn / success / system)\n- One-key operations: build, flash, build+flash, monitor, erase\n- Serial monitor streams directly into the log panel — no terminal handoff, so build/flash/monitor output all live in one continuous, scrollable history\n- Tab navigation between panels\n- Chip detection via `esptool.py` — shows chip model and MAC address\n- Project context awareness — reads CMakeLists.txt, sdkconfig, components\n- Automatic serial permission handling on Linux (dialout group check + temporary fix)\n- Single binary\n\n## Prerequisites\n\n- Go 1.21+\n- ESP-IDF installed with `idf.py` in `$PATH`\n- `esptool.py` in `$PATH` (bundled with ESP-IDF)\n- Linux or macOS (the serial monitor uses a pseudo-terminal via `github.com/creack/pty`, which has no Windows implementation — build/flash/erase still work on Windows, monitor does not)\n\n## Building\n\n```bash\n# build the binary\nmake build\n\n# run directly\nmake run\n\n# install globally to $GOPATH/bin\nmake install\n\n# format, lint, test, and build\nmake all\n\n# development mode with race detector\nmake dev\n\n# see all targets\nmake help\n```\n\nManual build:\n\n```bash\ngo build -o esp-workbench ./cmd/app\n./esp-workbench\n```\n\n## Usage\n\n```bash\n# default: use current directory as project\nesp-workbench\n\n# specify a project path\nesp-workbench /path/to/my-esp32-app\nesp-workbench --project ~/projects/weather-station\n\n# show version\nesp-workbench --version\n```\n\n## Keybindings\n\n| Key                    | Action                                          |\n| ---------------------- | ----------------------------------------------- |\n| `Tab` / `Shift+Tab`    | Cycle between panels                            |\n| `up` / `down` or `j/k` | Navigate device list                            |\n| `enter`                | Select device as active port                    |\n| `b`                    | Build (`idf.py build`)                          |\n| `f`                    | Flash (`idf.py -p \u003cport\u003e flash`)                |\n| `a`                    | Build + Flash in one shot                       |\n| `m`                    | Start serial monitor; press again to stop       |\n| `e`                    | Erase entire flash                              |\n| `x`                    | Browse and flash an existing binary             |\n| `p`                    | Read and visualize the device's partition table |\n| `r`                    | Rescan devices                                  |\n| `l`                    | Clear log pane                                  |\n| `q` / `Ctrl+C`         | Quit                                            |\n\n### Serial monitor (`m`)\n\nRuns `idf.py monitor` attached to a pseudo-terminal and streams its output\nstraight into the log panel, colorized the same way as every other command.\nPress `m` again to stop — this sends the same Ctrl+] byte `idf_monitor`\nlistens for on a real terminal, so it exits through its own cleanup path\n(closing the serial port cleanly) rather than being killed.\n\nBecause the monitor owns the serial port for as long as it's running,\nautomatic device rescanning is paused while any operation (build, flash,\nmonitor, erase) is active, and resumes once you're back to idle. This\navoids intermittent chip-detection probes contending with the monitor (or\nflasher) for exclusive access to the port.\n\nNote: the monitor's own interactive shortcuts (Ctrl+T menu, etc.) aren't\nforwarded, since keyboard input isn't wired into the pty — only its output\nis captured. `m` to stop is the supported way to end a session.\n\n### Flash an existing binary (`x`)\n\nOpens a file browser starting in the project's `build/` directory (or the\nproject root if no build exists yet). Navigate with `up/down`, descend into\na directory with `enter`, go back up with `backspace`. If `flasher_args.json`\nis present in the current directory, a `[full flash]` entry appears at the\ntop — selecting it flashes every component at the exact addresses idf.py\ncomputed, in one shot. Selecting any `.bin` file or `[full flash]` does not\nflash immediately: it opens a confirmation screen showing the file, the\nflash address, and the target device, requiring a second deliberate `enter`\nbefore anything is written. `esc` cancels at any point.\n\n### Visualize partitions (`p`)\n\nReads the partition table directly off the connected device — not from your\nproject files, from the chip itself — and renders it as a proportional usage\nbar plus a detail list (name, type, offset, size, percentage of flash). Also\ndetects the physical flash chip size via `esptool.py flash_id` so the bar\nreflects real usage, including free space. Press `r` inside this view to\nre-read, `esc` to go back.\n\n## Project Detection\n\nesp-workbench reads the project directory at startup and displays:\n\n- **target chip** — from `sdkconfig` `CONFIG_IDF_TARGET` (most reliable), falling back to `CMakeLists.txt`\n- **configured / not configured** — whether `sdkconfig` exists (i.e. `idf.py menuconfig` has been run)\n- **component count** — number of subdirectories in `components/` that contain a `CMakeLists.txt`\n- **partition table** — name of any `*partition*.csv` found in the project root\n- **version** — from `project(...VERSION x.y.z)` in CMakeLists, or `CONFIG_APP_PROJECT_VER` in sdkconfig\n\nIf the directory is not a valid ESP-IDF project (missing `CMakeLists.txt` or `main/`), the header shows what is missing.\n\nNote: the `partitions: *.csv` field above only names a custom partition CSV\nchecked into the project — it does not read the device. For the actual,\ncurrently-flashed partition layout on the chip, use `p` (see Keybindings).\n\n## Permission Handling (Linux)\n\nIf a device is not readable, esp-workbench:\n\n1. Diagnoses the problem (not in dialout group vs wrong device permissions)\n2. Attempts an automatic temporary fix via `pkexec chmod a+rw \u003cport\u003e`\n3. Falls back to `sudo chmod a+rw \u003cport\u003e`\n4. If all automatic fixes fail, prints the exact command to run manually\n\nThis same flow runs automatically before starting the serial monitor, not\njust build/flash/erase.\n\nPermanent fix (run once, then log out and back in):\n\n```bash\nsudo usermod -aG dialout $USER\n```\n\n## Troubleshooting\n\n**No devices found**\n\n- Press `r` to manually trigger a scan\n- Ensure `esptool.py` is in `$PATH`\n- Check the USB cable and device connection\n\n**Build fails with missing imports**\n\n```bash\ngo mod tidy\ngo mod download\n```\n\n**Monitor fails with \"Could not exclusively lock port\"**\n\nThis means something else briefly held the port open while `idf_monitor`\nwas starting. Auto-rescan is paused during active operations specifically\nto prevent this — if you still see it, make sure you're on a build that\nincludes the idle-only rescan gate (rescanning should only ever happen\nwhile the app is idle, never mid-build/flash/monitor).\n\n**Terminal rendering issues**\n\n- Ensure the terminal supports ANSI colors\n- Try resizing the window (layout reflows on resize)\n- On Windows, use Windows Terminal rather than cmd.exe\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabdullahwaqar%2Fesp-workbench","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabdullahwaqar%2Fesp-workbench","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabdullahwaqar%2Fesp-workbench/lists"}