{"id":50488568,"url":"https://github.com/joshuamumbere/lecc-daemon","last_synced_at":"2026-06-02T00:30:55.463Z","repository":{"id":359435189,"uuid":"1245957563","full_name":"joshuamumbere/lecc-daemon","owner":"joshuamumbere","description":"Local Environment Command Center","archived":false,"fork":false,"pushed_at":"2026-05-30T05:33:35.000Z","size":96,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-30T07:13:25.742Z","etag":null,"topics":["javascript","linux-shell","shell"],"latest_commit_sha":null,"homepage":"https://github.com/joshuamumbere/lecc-daemon","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/joshuamumbere.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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-21T18:21:01.000Z","updated_at":"2026-05-30T05:33:32.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/joshuamumbere/lecc-daemon","commit_stats":null,"previous_names":["joshuamumbere/lecc-daemon"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/joshuamumbere/lecc-daemon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuamumbere%2Flecc-daemon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuamumbere%2Flecc-daemon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuamumbere%2Flecc-daemon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuamumbere%2Flecc-daemon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joshuamumbere","download_url":"https://codeload.github.com/joshuamumbere/lecc-daemon/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuamumbere%2Flecc-daemon/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33800675,"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-01T02:00:06.963Z","response_time":115,"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":["javascript","linux-shell","shell"],"created_at":"2026-06-02T00:30:54.712Z","updated_at":"2026-06-02T00:30:55.452Z","avatar_url":"https://github.com/joshuamumbere.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Local Environment Command Center\n\nLECC is a local-only developer control surface made of two pieces:\n\n- A Node.js daemon bound to `127.0.0.1` that owns all host access.\n- A Manifest V3 browser extension that connects to the daemon over WebSocket.\n\nThis repository currently contains authenticated daemon messaging, editable port-based project context, safe log tailing, allow-listed cache actions, and a loadable extension popup.\n\n## Project Layout\n\n```text\n.\n├── src/\n│   ├── index.js              # WebSocket daemon entrypoint\n│   ├── config.js             # token/config helpers\n│   ├── router.js             # allow-listed daemon commands\n│   └── handlers/\n│       ├── cache.js          # allow-listed cache command execution\n│       ├── logs.js           # validated tail -f log streaming\n│       └── port-map.js       # project mapping load/save validation\n├── extension/\n│   ├── manifest.json\n│   ├── background/service-worker.js\n│   └── popup/\n│       ├── popup.html\n│       ├── popup.css\n│       └── popup.js\n├── scripts/\n│   ├── install.sh            # installs systemd --user service\n│   └── uninstall.sh          # removes systemd --user service\n├── services.json             # allow-listed systemd user services\n└── port-map.json             # maps localhost ports to project names/logs\n```\n\n## Run The Daemon\n\nInstall dependencies:\n\n```sh\nnpm install\n```\n\nStart the daemon:\n\n```sh\nnpm start\n```\n\nThe daemon binds to `ws://127.0.0.1:17324`, creates an auth token at `~/.config/lecc/token`, and prints the token on startup.\n\nUseful environment overrides:\n\n```sh\nLECC_PORT=17324\nLECC_TOKEN_PATH=/path/to/token\nLECC_PORT_MAP=/path/to/port-map.json\nLECC_SERVICES=/path/to/services.json\nLECC_ALLOWED_LOG_DIRS=/var/log,/tmp,/home/me/projects\nLECC_ALLOWED_PERMISSION_DIRS=/tmp,/home/me/projects\nLECC_ALLOWED_ORIGINS=chrome-extension://\u003cextension-id\u003e\n```\n\n## Install As A User Service\n\nInstall the daemon as a `systemd --user` service:\n\n```sh\nnpm run install:service\n```\n\nThis copies the app to `~/.local/share/lecc-daemon`, installs production dependencies there, writes `~/.config/systemd/user/lecc-daemon.service`, and copies the default `port-map.json` to `~/.config/lecc/port-map.json` if one does not already exist.\n\nStart it:\n\n```sh\nsystemctl --user enable --now lecc-daemon.service\n```\n\nInstall and start in one step:\n\n```sh\nscripts/install.sh --start\n```\n\nCheck status and logs:\n\n```sh\nsystemctl --user status lecc-daemon.service\njournalctl --user -u lecc-daemon.service -f\n```\n\nRemove the service and installed app files:\n\n```sh\nnpm run uninstall:service\n```\n\nRemove service, installed app files, and config:\n\n```sh\nscripts/uninstall.sh --purge-config\n```\n\n## Load The Extension\n\n1. Open `chrome://extensions`.\n2. Enable Developer Mode.\n3. Click **Load unpacked**.\n4. Select the `extension/` directory.\n5. Open the extension popup, paste the daemon token, and save.\n\nThe token is stored at `~/.config/lecc/token` by default. The popup Settings tab includes a token reveal toggle and a connection test button. The Controls tab shows connection diagnostics, including the daemon URL, WebSocket close code, and useful service commands when the daemon is unavailable.\n\nOpen a localhost tab such as `http://localhost:3000`. If the port exists in `port-map.json`, the extension sends that context to the daemon and streams the mapped log file.\n\nThe Logs tab supports pausing display updates, clearing the extension-side view, restarting the current stream, filtering lines, and highlighting common log levels.\n\nThe Controls tab also lists cache actions reported by the daemon. Each action maps to a fixed command and argument list in `src/handlers/cache.js`; the extension only sends an action ID.\n\nCache command runs use request IDs and are tracked in a recent command history. The popup persists the last 20 command runs in `chrome.storage.local`, including status, timestamps, exit code, and failure details.\n\nThe Permissions Repair section supports non-recursive `chmod` and `chown` operations on paths inside `LECC_ALLOWED_PERMISSION_DIRS`. Modes are restricted to a small safe set, and owner values must be plain `user` or `user:group` strings.\n\nPermission presets are daemon-owned allow-list entries. The extension sends a preset ID and target path; the daemon maps the preset to a fixed mode such as `775`, `664`, `755`, or `600`.\n\nService controls use `systemctl --user` and only operate on services listed in `services.json`. Service names must be valid `.service` unit names and are never executed through a shell.\n\nUse the Settings tab to edit the service allow-list without restarting the daemon. Saved services immediately refresh the Controls service dropdown.\n\nUse the Settings tab to edit project mappings without restarting the daemon. Ports must be numeric, project names are required, and log paths must resolve inside `LECC_ALLOWED_LOG_DIRS`.\n\n## Demo Log\n\nThe default `port-map.json` points to `/tmp/lecc-demo.log`. Create it before testing log streaming:\n\n```sh\ntouch /tmp/lecc-demo.log\nprintf 'INFO demo log ready\\n' \u003e\u003e /tmp/lecc-demo.log\n```\n\n## Security Baseline\n\n- The daemon listens only on `127.0.0.1`.\n- Every command must include the daemon token.\n- Commands are routed through a fixed allow-list in `src/router.js`.\n- Log paths are resolved and checked against allowed directories before `tail` is started.\n- The current extension command surface is intentionally small: connect, disconnect, context detection, log streaming, echo, cache action listing/execution, and validated project mapping edits.\n\n## Protocol\n\nThe daemon and extension speak `lecc.v1`. The daemon advertises protocol metadata in `hello` and `pong` messages:\n\n```json\n{\n  \"type\": \"hello\",\n  \"protocol\": \"lecc.v1\",\n  \"daemonVersion\": \"0.1.0\",\n  \"capabilities\": [\n    \"logs\",\n    \"cache_actions\",\n    \"permissions\",\n    \"permission_presets\",\n    \"process_controls\",\n    \"editable_port_map\",\n    \"editable_services\"\n  ]\n}\n```\n\nThe extension blocks command execution when the daemon protocol is incompatible. Unknown commands return structured `command_error` messages with an error code.\n\n## Checks\n\n```sh\nnpm run check\nnpm run build:extension\n```\n\n`npm run check` runs ESLint, JavaScript syntax checks, and the Node test suite.\n`npm run build:extension` creates a Chrome-compatible MV3 extension zip in `dist/`.\n\n## Contributing\n\nThis project is open source under the MIT License. Contributions are welcome through issues and pull requests.\n\nBefore opening a pull request:\n\n```sh\nnpm ci\nnpm run check\nnpm run build:extension\n```\n\nSee `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, and `SECURITY.md` for contribution expectations, security reporting, and release details.\n\n## Releases\n\nGitHub Actions runs CI checks on pushes and pull requests. Releases are separate: they are created only from a version tag or from the manual Release workflow.\n\nTo release from the command line, make sure `package.json` and `extension/manifest.json` have the same version, then create and push a `v*` tag:\n\n```sh\nnpm version patch\ngit push origin main --follow-tags\n```\n\nRelease tags must match `v*`, such as `v0.1.1`.\n\nYou can also open GitHub Actions, run the `Release` workflow manually, and provide a tag that exactly matches the package version, such as `v0.1.1`.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshuamumbere%2Flecc-daemon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoshuamumbere%2Flecc-daemon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshuamumbere%2Flecc-daemon/lists"}