{"id":15061540,"url":"https://github.com/webreflection/micro-repl","last_synced_at":"2025-10-29T17:45:34.205Z","repository":{"id":237022441,"uuid":"793512581","full_name":"WebReflection/micro-repl","owner":"WebReflection","description":"An easy, SerialPort based, MicroPython REPL for micro controllers.","archived":false,"fork":false,"pushed_at":"2025-01-29T13:06:35.000Z","size":134,"stargazers_count":15,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-24T08:21:17.279Z","etag":null,"topics":["micropython","repl","serialport","web","webserial"],"latest_commit_sha":null,"homepage":"https://webreflection.github.io/micro-repl/","language":"JavaScript","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/WebReflection.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}},"created_at":"2024-04-29T11:12:44.000Z","updated_at":"2025-02-22T04:51:10.000Z","dependencies_parsed_at":"2024-11-21T16:23:05.919Z","dependency_job_id":"b1368a9c-4473-42bc-83ad-137bf4fa6fbb","html_url":"https://github.com/WebReflection/micro-repl","commit_stats":{"total_commits":114,"total_committers":1,"mean_commits":114.0,"dds":0.0,"last_synced_commit":"d7f6fffe59dc56efaf716d4f06756f58ef8cfe50"},"previous_names":["webreflection/spike3","webreflection/micro-repl"],"tags_count":63,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebReflection%2Fmicro-repl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebReflection%2Fmicro-repl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebReflection%2Fmicro-repl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebReflection%2Fmicro-repl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WebReflection","download_url":"https://codeload.github.com/WebReflection/micro-repl/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248191049,"owners_count":21062411,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["micropython","repl","serialport","web","webserial"],"created_at":"2024-09-24T23:21:01.001Z","updated_at":"2025-10-29T17:45:34.120Z","avatar_url":"https://github.com/WebReflection.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# micro-repl\n\n\u003csup\u003e**Social Media Photo by [Luca J](https://unsplash.com/@lucajns) on [Unsplash](https://unsplash.com/)**\u003c/sup\u003e\n\nAn easy, SerialPort based, MicroPython REPL for micro controllers.\n\n  * **[Live Serial Demo](https://webreflection.github.io/micro-repl/board/)**\n  * **[Live PyScript Demo](https://webreflection.github.io/micro-repl/mpy/)** which uses *MicroPython* on the browser to communicate with the boards 🤯\n\n### Supported Serials\n\nIt is very likely that your *MicroPython* based board works too but these have been manually, and personally, tested during the development of this module:\n\n  * [Spike Prime](https://spike.legoeducation.com/prime/lobby/)\n  * [Raspberry Pi Pico and Pico W](https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html)\n  * [Adafruit PyPortal - CircuitPython](https://www.adafruit.com/product/4116)\n  * [Arduino Nano ESP32](https://store.arduino.cc/products/nano-esp32)\u003cbr\u003e\n    \u003csup\u003eI used `dfu-util -a 0 -d 0x2341:0x0070 -D ./ARDUINO_NANO_ESP32-X.app-bin` to install *MicroPython* on it: [app-bin download](https://micropython.org/download/ARDUINO_NANO_ESP32/)\u003c/sup\u003e\n\n- - -\n\n## Features\n\nThe currently maintained and developed export is `micro-repl/serial` (*previously known as board*) which supports the following features:\n\n  * board `name` showed as soon as connected and associated to the *board* instance\n  * fully interactive *REPL* mode out of the box\n  * tab completion works out of the box too\n  * every *Control+X* combination just works\n  * stopping running code via *Control+C* also works\n  * uploading data (text or binary files) works too\n  * pasting code also works\n  * paste mode never overflows the writes (big files copy pasted with ease)\n  * safe (after prompt) reboot on *Control-D* when not inside a *paste mode* session\n  * `ondata(buffer:Uint8Array)` passes along, while interacting, every single char the user is asking for\n  * *AutoFit* and *WebLinks* plugins available out of the box\n  * all imports are dynamic so it's size is still minimal before its usage\n  * `eval` method, if awaited and the end of the code has a reference or an expression, will return that value, if any, beside evaluating code without showing it on *REPL* shell. If the extra `options` reference `hidden` value is `false`, it also shows the evaluated code while streaming it to the board.\n  * `paste` method to pass along code in \"*paste mode*\" with ease, where `raw: true` is also available\n\nThe `micro-repl/board` alias still exists but it's now `micro-repl/serial` instead, to eventually allow `micro-repl/bt` and others within the same ease of use.\n\n## How To / Documentation\n\nThe easiest way to use `micro-repl/serial` is via *CDN*:\n\n```html\n\u003cscript type=\"module\"\u003e\n  import Serial from 'https://esm.run/micro-repl/serial';\n\n  // either Serial(...) or new Serial(...)\n  const board = Serial({\n    // all optionals\n    baudRate: 9600, // defaults to 115200\n    onconnect() { console.info('connected') },\n    ondisconnect() { console.warn('disconnected') },\n    onerror(error) { console.error(error) },\n    ondata(buffer) { },\n    // pass a different JSON parser if needed: json.loads,\n    // as example, would return directly Python references\n    onresult: JSON.parse,\n  });\n\n  // to connect a board a user action/gesture is needed\n  document.getElementById('repl').onclick = async event =\u003e {\n    event.preventDefault();\n\n    // connect the board to a DOM element to show the terminal\n    await board.connect(event.target);\n  };\n\u003c/script\u003e\n\u003cdiv id=\"repl\"\u003e\u003c/div\u003e\n```\n\n### micr-repl/serial TS signature\n\nDocumented via JSDoc TS, these are all explicit TS details around this module's API.\n\n#### options\n\nThese are all optional fields that can be passed when creating a new *Serial*.\n\n```ts\ntype MicroREPLOptions = {\n  // default: 115200\n  baudRate?: number | undefined;\n  // default: 'buffer'\n  dataType?: 'buffer' | 'string';\n  // default: console.error\n  onerror?: ((error: Error) =\u003e void) | undefined;\n  // default: () =\u003e void - notifies when the board is connected\n  onconnect?: (() =\u003e void) | undefined;\n  // default: () =\u003e void - notifies when the board is disconnected/lost\n  ondisconnect?: (() =\u003e void) | undefined;\n  // default: () =\u003e void - receives all data from the terminal\n  ondata?: ((buffer: Uint8Array) =\u003e void) | undefined;\n  // allow terminal easy-theme setup - if values are \"infer\"\n  // these are retrieved via computed style / CSS values\n  // for background (or background-color) and color (as foreground)\n  // default: { background: \"#191A19\", foreground: \"#F5F2E7\" }\n  theme?: {\n        background: string;\n        foreground: string;\n    } | undefined;\n}\n```\n\n#### serial board\n\nA *serial board* can be created via `new Serial(options)` or just direct `Serial(options)` ( \u003csup\u003ewhich is more Pythonic\u003c/sup\u003e ) and its returned reference is always an `instanceof Serial`.\n\n```ts\ntype MicroREPLSerialBoard = {\n  // `true` when connected, `false` otherwise\n  readonly connected: boolean;\n  // the passed `baudRate` option\n  readonly baudRate: number;\n  // the connected board name\n  readonly name: string;\n  // the Terminal reference once connected\n  readonly terminal: xterm.Terminal;\n  // ⚠️ must be done on user action !!!\n  // connects the board and show the REPL in the specified `target`\n  // `target` can be either a DOM Element or an element ID or a CSS selector.\n  connect: (target: Element | string) =\u003e Promise\u003cMicroREPLSerialBoard | void\u003e;\n  // disconnect the board and invoke ondisconnect\n  disconnect: () =\u003e Promise\u003cvoid\u003e;\n  // soft-reset the board and put it back into REPL mode\n  reset: () =\u003e Promise\u003cvoid\u003e;\n  // write any string directly to the board\n  write: (code: string) =\u003e Promise\u003cvoid\u003e;\n  // eval any code (no output while processing)\n  // if the end of the `code` is a reference, it tries\n  // to json serialize it and parse it back as result.\n  // if the options.hidden is `false` it shows the input\n  // while evaluating code.\n  eval: (code: string, options?: { hidden:boolean }) =\u003e Promise\u003cany\u003e;\n  // enter paste mode, write all code, then exit from paste mode\n  paste: (code: string, options?: { hidden:boolean, raw:boolean }) =\u003e Promise\u003cvoid\u003e;\n  // upload content as text or `File` and save it as `path` name\n  upload: (path: string, content: string | File, on_progress?: (current:number, total:number) =\u003e void) =\u003e Promise\u003cvoid\u003e;\n}\n```\n\nPlease note that `board.write(code)` requires `\\r\\n` at the end if you want your code to be executed.\n\nPlease also note this is not the same as `board.terminal.write(...)` because the terminal depends on writes on the board, not vice-versa.\n\n- - -\n\n\u003csup\u003e\u003csub\u003e**WARNING**\u003c/sub\u003e\u003c/sup\u003e\n\nPlease note this module is experimental. The current exports might change if actually the *board* reference is the best option this module offers (and I am definitively leading toward this conclusion).\n\n- - -\n\n### Troubleshooting\n\nIf you are on Linux and you can't see your *Prime* you can try to force-enable it by writing the following content into `/etc/udev/rules.d/50-myusb.rules`:\n\n```\nKERNEL==\"ttyACM[0-9]*\",MODE=\"0666\"\n```\n\nAfter a reboot, this instruction should enable it and you should see it selectable.\n\n![ttyACM0 selectable](./css/spike.png)\n\n### Credits\n\nThis project has been inspired by [pyrepl-js](https://github.com/gabrielsessions/pyrepl-js) but because I think *React* and *TypeScript*, plus the rest of the logic, was a bit too much for a basic core *REPL*, I've decided to create a minimal *JS* standard module able to do pretty much the same in way less code to maintain. Feel free to use that project if you want a more rich *UI* around the connection, events instead of just promises to deal with unbuffered data as sent by the controller, and everything else in there which I didn't need to create those live demoes.\n\n#### micro-repl TS signature\n\n**deprecated**\n\nOnce a `repl` has been successfully initialized, it offers this *API*:\n\n```ts\n// The default export TS signature\n({ baudRate, onceClosed, }?: {\n    baudRate: number; // default: 115200\n    onceClosed(error: Error | null): void;\n}) =\u003e Promise\u003c{\n    readonly active: boolean;\n    readonly result: Promise\u003cstring\u003e;\n    readonly output: Promise\u003cstring\u003e;\n    write: (code: string) =\u003e Promise\u003c...\u003e;\n    close: () =\u003e Promise\u003c...\u003e;\n}\u003e\n```\n\n#### Signature description\n\n  * **repl.active** as `boolean` - it's `true` when the *REPL* is active and running, `false` otherwise.\n  * **repl.result** as `Promise\u003cstring\u003e` - it contains the last line produced by the last executed code.\n  * **repl.output** as `Promise\u003cstring\u003e` - it awaits for the last executed code to execute and returns whatever that code produced, including the written code itself. Please note this throws an error if the `active` state is not `true`.\n  * **repl.write(code)** as `(code:string) =\u003e Promise\u003cvoid\u003e` - it writes code to the boards' *REPL* and it fulfills after all code has been sent. Please note this throws an error if the `active` state is not `true`.\n  * **repl.close()** as `() =\u003e Promise\u003cvoid\u003e` - it detaches all streams and gracefully clean up the `repl` state right before disconnecting it.\n\n### Example\n\n```js\n// check the board status\nrepl.active; // true\n\n// write code into the REPL\nawait repl.write('print(\"Hello MicroPython\")');\n\n// wait/check the produced REPL outcome\nawait repl.output;\n/**\n * \u003e\u003e\u003e print(\"Hello MicroPython\")\n * Hello MicroPython\n */\n\n// check the result (last printed line of the REPL)\nawait repl.result;  // \"Hello MicroPython\"\n\n// disconnect the board\nawait repl.close();\n\n// check the board status again\nrepl.active; // false\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebreflection%2Fmicro-repl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebreflection%2Fmicro-repl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebreflection%2Fmicro-repl/lists"}