{"id":50499786,"url":"https://github.com/xuruiray/stackchan-local","last_synced_at":"2026-06-02T10:31:48.229Z","repository":{"id":360386435,"uuid":"1244272285","full_name":"xuruiray/stackchan-local","owner":"xuruiray","description":"Local-first desktop daemon and firmware overlay for a Codex-connected StackChan robot.","archived":false,"fork":false,"pushed_at":"2026-05-26T06:57:56.000Z","size":4073,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-26T08:29:20.969Z","etag":null,"topics":["esp32","m5stack","react","stackchan"],"latest_commit_sha":null,"homepage":"","language":"C++","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/xuruiray.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","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-05-20T05:48:24.000Z","updated_at":"2026-05-26T07:00:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/xuruiray/stackchan-local","commit_stats":null,"previous_names":["xuruiray/stackchan-local"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/xuruiray/stackchan-local","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xuruiray%2Fstackchan-local","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xuruiray%2Fstackchan-local/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xuruiray%2Fstackchan-local/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xuruiray%2Fstackchan-local/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xuruiray","download_url":"https://codeload.github.com/xuruiray/stackchan-local/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xuruiray%2Fstackchan-local/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33818565,"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-06-02T02:00:07.132Z","response_time":109,"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":["esp32","m5stack","react","stackchan"],"created_at":"2026-06-02T10:31:44.986Z","updated_at":"2026-06-02T10:31:48.216Z","avatar_url":"https://github.com/xuruiray.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# StackChan Local\n\n[English](README.md) | [Chinese](README_zh.md)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Runtime\" src=\"https://img.shields.io/badge/runtime-local--first-22c55e\"\u003e\n  \u003cimg alt=\"Target\" src=\"https://img.shields.io/badge/target-M5Stack%20StackChan%20%2F%20ESP32--S3-2563eb\"\u003e\n  \u003cimg alt=\"ESP-IDF\" src=\"https://img.shields.io/badge/ESP--IDF-5.5.4-e7352c\"\u003e\n  \u003cimg alt=\"Desktop\" src=\"https://img.shields.io/badge/desktop-TypeScript%20%2B%20React-3178c6\"\u003e\n  \u003cimg alt=\"WebUI\" src=\"https://img.shields.io/badge/WebUI-localhost%3A8788-8b5cf6\"\u003e\n  \u003cimg alt=\"License\" src=\"https://img.shields.io/badge/license-MIT-black\"\u003e\n\u003c/p\u003e\n\nStackChan Local is a local-first desktop daemon, WebUI, and ESP-IDF firmware for M5Stack StackChan on ESP32-S3. Its goal is to let users quickly verify from a desktop that every hardware sensor and onboard module is working normally, then try a small set of local applications such as Codex status alerts, hardware expression control, and face-position tracking. The hardware connects to a Mac on the LAN over WebSocket, while the browser console, Codex integration, and optional local vision services run on the desktop.\n\nThe current architecture has three explicit firmware layers:\n\n- `hardware`: board profile, buses, chip drivers, and device-facing IO.\n- `services`: hardware application behavior such as display, motion, sensors, power, audio, network, and local companion protocol handling.\n- `system`: boot, lifecycle, settings, diagnostics, and ESP-IDF platform adapters.\n\n## Visual Overview\n\n| Hardware target | Local hardware console |\n| --- | --- |\n| \u003cimg src=\"assets/stackchan-product.png\" alt=\"StackChan hardware\" width=\"420\"\u003e | \u003cimg src=\"assets/webui-console.jpg\" alt=\"StackChan Local hardware console\" width=\"520\"\u003e |\n| M5Stack StackChan on ESP32-S3 with GC0308 camera, touch, IMU, servos, RGB, audio, and power modules. | React + Vite console for modules, applications, raw snapshots, logs, and camera streams. |\n\n## Project Snapshot\n\n| Dimension | Current design |\n| --- | --- |\n| Project goal | Desktop-first hardware validation for all StackChan sensors and modules, plus simple local applications |\n| Hardware target | M5Stack StackChan / ESP32-S3 only |\n| Firmware stack | ESP-IDF 5.5.4 with `system`, `hardware`, and `services` layers |\n| Desktop stack | TypeScript daemon, React + Vite WebUI, local Python vision sidecar |\n| Transport | LAN WebSocket at `ws://\u003cmac-ip\u003e:8787/stackchan/local` plus HTTP/SSE/MJPEG on `8788` |\n| Control model | Structured safe commands; no raw JSON command console |\n| Vision and avatar model | Local face-position tracking, hardware expression presets, optional avatar JSON, and no identity recognition |\n| Hardware observability | Per-module pages, public snapshot, logs, I2C scan, stream metrics, and sensor availability reasons |\n\n## Contents\n\n- [What It Does](#what-it-does)\n- [Repository Layout](#repository-layout)\n- [Architecture](#architecture)\n- [Runtime Endpoints](#runtime-endpoints)\n- [Firmware Layering](#firmware-layering)\n- [WebUI](#webui)\n- [Capability Matrix](#capability-matrix)\n- [Quick Start](#quick-start)\n- [Development Commands](#development-commands)\n- [Testing](#testing)\n\n## What It Does\n\n- Provides a desktop console for quickly checking whether StackChan hardware sensors and modules are connected, available, and returning valid data.\n- Runs simple local applications on top of the verified hardware, including Codex status alerts, hardware expression control, optional completion TTS, RGB light alerts, and face-position tracking.\n- Runs StackChan locally over LAN with desktop-side control and application orchestration.\n- Mirrors Codex activity into hardware states such as idle, thinking, and speaking.\n- Streams camera frames to the desktop for local face-position tracking.\n- Exposes a componentized React console at `http://localhost:8788`.\n- Reports hardware telemetry for power, touch, IMU with BMM150 magnetometer data, camera, servos, audio, RTC, NFC, IR, LTR553, INA226, Wi-Fi, BLE, RGB, and IO expander state.\n- Provides MCP tools so Codex can query status, speak, move the head, capture images, set modes, and control face tracking.\n\nFace tracking uses local position detection only and does not perform identity recognition.\n\n## Repository Layout\n\n```text\n.\n├── assets/              README assets\n├── desktop/             TypeScript daemon, WebSocket server, MCP server, vision, TTS, WebUI server\n│   ├── src/\n│   │   ├── codex/       Codex session watcher\n│   │   ├── device/      Device registry and snapshots\n│   │   ├── mcp/         MCP tool server\n│   │   ├── preview/     8788 HTTP/SSE/MJPEG/API server\n│   │   ├── robot/       Command controller and motion arbitration\n│   │   ├── tts/         Completion announcer and provider integration\n│   │   ├── vision/      Face detector sidecar and tracking controller\n│   │   └── ws/          Firmware WebSocket protocol server\n│   └── preview-ui/      React + Vite hardware console\n├── firmware/            ESP-IDF firmware project for M5Stack StackChan / ESP32-S3\n│   └── main/\n│       ├── hardware/    Board profile, bus, driver, and sensor modules\n│       ├── services/    Display, sensors, motion, audio, power, network, local companion\n│       ├── system/      Boot, core context, lifecycle, diagnostics, ESP-IDF adapters\n│       ├── third_party/ Passive chip libraries\n│       └── app/         Local Companion UI entry\n├── protocol/            Shared TypeScript protocol types and JSON schema validation\n└── scripts/             Build, flash, and hygiene scripts\n```\n\n## Architecture\n\n### Runtime Topology\n\n```mermaid\nflowchart LR\n  Codex[\"Codex / MCP\"] --\u003e Desktop[\"desktop daemon\"]\n  Browser[\"React WebUI :8788\"] --\u003e Desktop\n  Desktop --\u003e Vision[\"Python OpenCV detector\"]\n  Desktop \u003c--\u003e|\"ws://\u003cmac-ip\u003e:8787/stackchan/local\"| Firmware[\"ESP32-S3 firmware\"]\n  Firmware --\u003e System[\"system\"]\n  Firmware --\u003e Services[\"services\"]\n  Firmware --\u003e Hardware[\"hardware\"]\n  Hardware --\u003e Devices[\"PMIC, display, touch, camera, audio, servos, sensors, network\"]\n```\n\n### Firmware Ownership\n\n```mermaid\nflowchart TB\n  AppMain[\"app_main\"] --\u003e Boot[\"system/boot\"]\n  Boot --\u003e Context[\"system/core/SystemContext\"]\n  Context --\u003e BoardProfile[\"hardware/board/m5stack_stackchan/BoardProfile\"]\n  BoardProfile --\u003e Registry[\"HardwareRegistry\"]\n  Registry --\u003e Bus[\"hardware/bus\"]\n  Registry --\u003e Drivers[\"hardware drivers\"]\n  Context --\u003e ServiceRegistry[\"ServiceRegistry\"]\n  ServiceRegistry --\u003e SensorService[\"services/sensors\"]\n  ServiceRegistry --\u003e MotionService[\"services/motion\"]\n  ServiceRegistry --\u003e DisplayService[\"services/display\"]\n  ServiceRegistry --\u003e CompanionService[\"services/local_companion\"]\n  CompanionService --\u003e Telemetry[\"snapshots, camera frames, logs\"]\n  SensorService --\u003e Telemetry\n  MotionService --\u003e Drivers\n  DisplayService --\u003e Drivers\n```\n\n### Command And Telemetry Loop\n\n```mermaid\nsequenceDiagram\n  participant UI as React WebUI\n  participant Desktop as Desktop daemon\n  participant Firmware as ESP32-S3 firmware\n  participant Service as Firmware service\n  participant Driver as Hardware driver\n\n  UI-\u003e\u003eDesktop: POST /api/* or SSE subscribe\n  Desktop-\u003e\u003eFirmware: structured robot command over WebSocket\n  Firmware-\u003e\u003eService: dispatch command\n  Service-\u003e\u003eDriver: read, write, or control\n  Driver--\u003e\u003eService: hardware result\n  Service--\u003e\u003eFirmware: snapshot or ACK\n  Firmware--\u003e\u003eDesktop: telemetry, camera frame, command ACK\n  Desktop--\u003e\u003eUI: /status, /events, /debug/*, MJPEG/JPEG\n```\n\n### Desktop Responsibilities\n\n- Listen for firmware WebSocket connections on `8787`.\n- Validate protocol messages with shared schemas from `protocol/`.\n- Maintain device sessions, heartbeat state, command ACKs, and public snapshots.\n- Expose the React WebUI, status APIs, debug logs, SSE updates, and raw/processed camera streams on `8788`.\n- Run MCP tools for Codex.\n- Watch Codex session state and dispatch companion mode changes.\n- Run optional completion TTS and RGB light alerts.\n- Run local face-position tracking through `desktop/scripts/face_detector.py`.\n\n### Firmware Responsibilities\n\n- Boot the M5Stack StackChan board profile and initialize hardware drivers.\n- Compose drivers into services for display, motion, sensors, power, audio, network, and local companion transport.\n- Connect to the desktop daemon using mDNS or saved fallback WebSocket URL.\n- Send heartbeat, state, hardware status, touch, IMU, battery, Wi-Fi, camera, and audio telemetry.\n- Execute commands for mode, audio playback, camera stream, RGB, servo motion, and face tracking.\n- Keep local avatar rendering, blinking, idle behavior, and power policy on-device.\n\n## Runtime Endpoints\n\n| Surface | Default | Owner | Purpose |\n| --- | --- | --- | --- |\n| Firmware WebSocket | `ws://\u003cmac-ip\u003e:8787/stackchan/local` | `desktop/src/ws` | Firmware session, heartbeat, telemetry, commands |\n| Preview WebUI | `http://localhost:8788/` | `desktop/src/preview` + `desktop/preview-ui` | Browser console for modules, applications, and debug pages |\n| Public status | `GET /status` | Preview server | Device/session summary consumed by the UI |\n| Public snapshot | `GET /debug/snapshot` | Preview server | Raw public JSON snapshot for diagnostics |\n| Logs | `GET /debug/logs`, `GET /debug/log-events` | Preview server | Daemon logs and streaming log updates |\n| Camera streams | `GET /frame.jpg`, `GET /stream.mjpg` | Preview server | Latest raw/processed camera frames |\n| Service discovery | `_stackchan-local._tcp` | Desktop daemon | mDNS discovery for firmware pairing |\n\n## Firmware Layering\n\n```text\nfirmware/main/\n  hardware/\n    board/m5stack_stackchan/   pinmap, hardware_config, BoardProfile\n    bus/                       I2C device/bus helpers\n    power/                     AXP2101 and backlight\n    display/                   ILI9342/LVGL driver boundary\n    touch/                     FT6336 screen touch\n    audio/                     ES7210/AW88298/CoreS3 codec surface\n    camera/                    GC0308 camera\n    motion/                    SCS servo driver surface\n    io_expander/               AW9523/PY32 IO expander\n    lighting/                  RGB strip driver boundary\n    sensors/                   SI12T, BMI270, BMM150, RTC, INA226, LTR553, NFC, IR, mic level\n    network/                   Wi-Fi, BLE, provisioning helpers\n\n  services/\n    display/                   LVGL runtime, avatar binding, status display, RGB behavior\n    sensors/                   Polling, snapshots, I2C diagnostics, sensor events\n    motion/                    Servo calibration and expression-motion output\n    power/                     Servo power and IO expander power policy\n    audio/                     Codec service, wake word/audio runtime, mic level\n    network/                   Wi-Fi, SNTP, BLE provisioning\n    expression_motion/         Avatar, animation, modifiers, StackChan motion engine\n    local_companion/           WebSocket session, command dispatch, telemetry, media streams\n\n  system/\n    boot/                      Startup sequence and runtime boot\n    core/                      SystemContext, settings, event bus, service registry, diagnostics\n    lifecycle/                 Reboot, power off, factory reset/runtime state\n    power_policy/              Idle power policy namespace\n    platform/esp_idf/          ESP-IDF adapters\n\n  third_party/                 Passive chip libraries only\n```\n\nCurrent firmware boundaries:\n\n- `hardware` drivers take bus/config dependencies and expose `begin`, `available`, `read`, `write`, or `control` style APIs.\n- `hardware` must not depend on LVGL app objects, Local Companion services, desktop protocol code, or `Board::GetInstance()`.\n- `services` compose drivers and publish application-level behavior, telemetry, and events.\n- `system` owns boot order, shared context, lifecycle, settings, diagnostics, and ESP-IDF adapters.\n- `third_party` contains passive chip libraries only.\n\n## WebUI\n\nThe WebUI is served by the desktop daemon at `http://localhost:8788`. It is a React + Vite app under `desktop/preview-ui/`.\n\nThe console is designed as the primary hardware validation surface. It has three groups:\n\n- **Modules**: one page per chip or hardware module: Power / PMIC, Display, Screen Touch, Head Touch, IMU, Camera, Servo, IO Expander, RGB LED, RTC, ALS/Proximity, NFC, IR, Audio, Wi-Fi/BLE. Power includes AXP2101 and INA226; IMU includes BMI270 and BMM150 magnetometer data.\n- **Applications**: simple app flows built on verified hardware, currently Codex announcer/light alert, hardware expression control, and face-position tracking.\n- **Debug**: system counters, raw public snapshot, and daemon logs.\n\nCamera pages expose separate raw and processed streams:\n\n- Raw preview: camera stream before face detection.\n- Face tracking: processed stream with face-position overlay.\n\n## Capability Matrix\n\n| Group | Pages or services | Data shown | Safe commands |\n| --- | --- | --- | --- |\n| Power | AXP2101, INA226, backlight policy | Battery, charge state, rail current/power, availability reasons | Read-only status |\n| Touch and motion sensors | FT6336, SI12T, BMI270, BMM150, LTR553 | Touch state, accel/gyro, fused attitude, magnetometer, ALS/proximity | Read-only status |\n| Camera and vision | GC0308 raw stream, face-position processed stream | FPS, frame interval, latency, JPEG size, face target | Stream on/off, capture, FPS selection |\n| Actuators | SCS servos, RGB LED, IO expander | Servo power, RGB state, expander availability | Move head, set RGB color/brightness |\n| Audio and time | ES7210, AW88298, RTC | Mic availability, codec status, RTC time | TTS/say through MCP |\n| Network | Wi-Fi, BLE provisioning, mDNS | Link state, SSID/IP, RSSI, reconnect counters | Provisioning and runtime network commands through services |\n| Applications | Codex announcer/light alert, hardware expression control, face-position tracking | App state, enabled flags, expression capability, tracking target and latency | Send expression presets/avatar JSON, toggle tracking, adjust FPS, companion mode commands |\n| Debug | System, raw snapshot, logs | Heap, counters, command ACKs, public JSON, daemon logs | Read-only diagnostics |\n\n## Quick Start\n\n### 1. Install Desktop Dependencies\n\n```bash\nnpm install\ncp .env.example .env\n```\n\nEdit `.env` before using real hardware. At minimum, change:\n\n```bash\nSTACKCHAN_PAIRING_TOKEN=dev-local-token\n```\n\n### 2. Start Desktop Daemon\n\n```bash\nnpm run dev\n```\n\nDefault endpoints:\n\n- Firmware WebSocket: `ws://\u003cmac-ip\u003e:8787/stackchan/local`\n- WebUI: `http://localhost:8788`\n- mDNS service: `_stackchan-local._tcp`\n\n### 3. Optional Face Tracking Setup\n\n```bash\nnpm run vision:install\nSTACKCHAN_FACE_TRACKING=1 npm run dev\n```\n\nFace tracking uses the local Python OpenCV YuNet sidecar and fixed 320 x 240 camera input. The WebUI exposes stream options and center-point PID controls.\n\n### 4. Build And Flash Firmware\n\nUse ESP-IDF 5.5.4 for the current firmware tree:\n\n```bash\nsource ~/esp/esp-idf-v5.5.4/export.sh\nnpm run firmware:build\nnpm run firmware:check-local-only\nnpm run firmware:flash\n```\n\nEquivalent raw ESP-IDF commands:\n\n```bash\ncd firmware\nidf.py set-target esp32s3\nidf.py build\nidf.py -p /dev/cu.usbmodem21301 flash monitor\n```\n\nIf the device has no saved Wi-Fi credentials, it starts a `StackChan-XXXX` provisioning AP. Connect to it and open `http://192.168.4.1`.\n\n## Configuration\n\nCommon settings live in [.env.example](.env.example).\n\nImportant defaults:\n\n- `STACKCHAN_LOCAL_PORT=8787`\n- `STACKCHAN_PREVIEW_PORT=8788`\n- `STACKCHAN_PAIRING_TOKEN=dev-local-token`\n- `STACKCHAN_FACE_TRACKING=0`\n- `STACKCHAN_FACE_TRACKING_CAMERA_PRESET=fast`\n- `STACKCHAN_FACE_TRACKING_SPEED=420`\n- `STACKCHAN_FACE_TRACKING_DEADBAND=0.045`\n- `STACKCHAN_FACE_TRACKING_TRACE_LOG=logs/face-tracking.ndjson`\n- `STACKCHAN_CODEX_STATUS=1`\n- `STACKCHAN_VOLCENGINE_TTS_ENABLED=0`\n\nDo not commit real pairing tokens or provider API keys.\n\n## MCP Tools\n\nRun MCP mode with:\n\n```bash\nnpm run mcp\n```\n\nAvailable tools:\n\n- `stackchan_status`\n- `stackchan_say`\n- `stackchan_react`\n- `stackchan_move_head`\n- `stackchan_play_animation`\n- `stackchan_capture_image`\n- `stackchan_set_mode`\n- `stackchan_face_tracking`\n\n## Development Commands\n\n| Goal | Command |\n| --- | --- |\n| Install workspace dependencies | `npm install` |\n| Start desktop daemon and WebUI | `npm run dev` |\n| Run MCP server mode | `npm run mcp` |\n| Type-check all TypeScript packages | `npm run typecheck` |\n| Run protocol and desktop tests | `npm test` |\n| Build preview UI and desktop TypeScript | `npm run build` |\n| Install local vision dependencies | `npm run vision:install` |\n| Build firmware | `source ~/esp/esp-idf-v5.5.4/export.sh \u0026\u0026 npm run firmware:build` |\n| Flash firmware | `source ~/esp/esp-idf-v5.5.4/export.sh \u0026\u0026 npm run firmware:flash` |\n| Check firmware local-only boundaries | `npm run firmware:check-local-only` |\n\n## Testing\n\nDesktop and protocol:\n\n```bash\nnpm run typecheck\nnpm test\nnpm run check\n```\n\nTargeted checks:\n\n```bash\nnpm test -w @stackchan-local/protocol\nnpm test -w @stackchan-local/desktop\nnpm run typecheck -w @stackchan-local/desktop\n```\n\nFirmware:\n\n```bash\nsource ~/esp/esp-idf-v5.5.4/export.sh\nnpm run firmware:build\nnpm run firmware:check-local-only\n```\n\nHardware acceptance after flashing:\n\n- `http://localhost:8788/`, `/status`, `/debug/snapshot`, and `/debug/logs` return 200.\n- Device shows online in the WebUI.\n- Module pages update for PMIC/battery, INA226 power monitor, touch, head touch, IMU with magnetometer, RTC, mic, camera, RGB/io expander, servos, NFC, IR, and LTR553.\n- Present hardware reports valid non-NaN values and reacts to touch, motion, light, sound, and camera stimuli.\n- Missing or unsupported modules report `available:false` with a clear reason.\n- `/frame.jpg` or `/stream.mjpg` returns a valid JPEG stream when camera streaming is enabled.\n- Firmware serial logs and desktop logs have no unexplained `ERROR`, no persistent `WARN` spam, no reconnect loop, and no repeated sensor init timeout.\n\n## Privacy And Safety\n\n- Camera frames stay on the LAN between the hardware and desktop daemon.\n- Face tracking is local position detection only, not identity recognition.\n- Cloud TTS is optional and disabled by default.\n- Pairing tokens and API keys belong in `.env`, not in Git.\n\n## Project Status\n\nThis is an experimental local hardware/software project for macOS plus M5Stack StackChan on ESP32-S3. The current focus is fast desktop-side validation of hardware sensors and modules, stable local control, simple companion applications, and a clean firmware layering model. Cross-platform desktop packaging and production-grade firmware release flow still need hardening.\n\n## License\n\nMIT for StackChan Local project code unless a subdirectory or managed dependency states otherwise.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxuruiray%2Fstackchan-local","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxuruiray%2Fstackchan-local","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxuruiray%2Fstackchan-local/lists"}