sliccy 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +191 -0
- package/README.md +512 -0
- package/dist/cli/chrome-launch.d.ts +47 -0
- package/dist/cli/chrome-launch.js +324 -0
- package/dist/cli/cli-log-dedup.d.ts +19 -0
- package/dist/cli/cli-log-dedup.js +62 -0
- package/dist/cli/electron-controller.d.ts +38 -0
- package/dist/cli/electron-controller.js +287 -0
- package/dist/cli/electron-main.d.ts +1 -0
- package/dist/cli/electron-main.js +183 -0
- package/dist/cli/electron-runtime.d.ts +58 -0
- package/dist/cli/electron-runtime.js +133 -0
- package/dist/cli/file-logger.d.ts +38 -0
- package/dist/cli/file-logger.js +207 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +1023 -0
- package/dist/cli/launch-url.d.ts +9 -0
- package/dist/cli/launch-url.js +34 -0
- package/dist/cli/qa-setup.d.ts +1 -0
- package/dist/cli/qa-setup.js +36 -0
- package/dist/cli/release-package.d.ts +17 -0
- package/dist/cli/release-package.js +232 -0
- package/dist/cli/runtime-flags.d.ts +21 -0
- package/dist/cli/runtime-flags.js +154 -0
- package/dist/cli/sync-release-version.d.ts +2 -0
- package/dist/cli/sync-release-version.js +34 -0
- package/dist/tray-url-shared.d.ts +11 -0
- package/dist/tray-url-shared.js +56 -0
- package/dist/ui/assets/___vite-browser-external_commonjs-proxy-7ULRRj69.js +1 -0
- package/dist/ui/assets/__vite-browser-external-D7Ct-6yo.js +1 -0
- package/dist/ui/assets/addon-fit-DOCEibfw.js +12 -0
- package/dist/ui/assets/bsh-watchdog-D19WB0U1.js +2 -0
- package/dist/ui/assets/index-BVQAdk-Y.js +8 -0
- package/dist/ui/assets/index-BjJrFm2K.js +43 -0
- package/dist/ui/assets/index-C1dglHrI.js +3 -0
- package/dist/ui/assets/index-D3Enm5ux.js +13091 -0
- package/dist/ui/assets/index-D7hjyFh1.js +2 -0
- package/dist/ui/assets/index-D8uSC2sl.js +45 -0
- package/dist/ui/assets/index-DEglHp2j.js +1 -0
- package/dist/ui/assets/index-DvjzakYY.js +14406 -0
- package/dist/ui/assets/index-deZeJCgO.js +1 -0
- package/dist/ui/assets/index-mz3VYh0I.js +131 -0
- package/dist/ui/assets/index-r2m8Dpaz.js +54 -0
- package/dist/ui/assets/index-ygVJ3eFG.js +11 -0
- package/dist/ui/assets/lick-manager-proxy-G3WuipZ-.js +1 -0
- package/dist/ui/assets/magic-string.es-BPLJknd7.js +10 -0
- package/dist/ui/assets/oauth-service-DIahkF-o.js +1 -0
- package/dist/ui/assets/offscreen-client-ByVIJGHW.js +1 -0
- package/dist/ui/assets/pdfjs-uyZuKmOq.js +59 -0
- package/dist/ui/assets/pyodide-D73G_Ygx.mjs +4 -0
- package/dist/ui/assets/sql-wasm-BggYNCID.js +2 -0
- package/dist/ui/assets/stream-lEC9OYG2.js +1 -0
- package/dist/ui/assets/xterm-Bb8UKAlD.js +27 -0
- package/dist/ui/assets/xterm-DOrYoP_4.css +32 -0
- package/dist/ui/electron-overlay-entry.js +360 -0
- package/dist/ui/favicon.png +0 -0
- package/dist/ui/fonts/AdobeClean-Bold.otf +0 -0
- package/dist/ui/fonts/AdobeClean-ExtraBold.otf +0 -0
- package/dist/ui/fonts/AdobeClean-Medium.otf +0 -0
- package/dist/ui/fonts/AdobeClean-Regular.otf +0 -0
- package/dist/ui/index.html +1981 -0
- package/dist/ui/preview-sw.js +4 -0
- package/package.json +81 -0
package/README.md
ADDED
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
# slicc — Self-Licking Ice Cream Cone
|
|
4
|
+
|
|
5
|
+
[](https://github.com/ai-ecoverse/vibe-coded-badge-action)
|
|
6
|
+
|
|
7
|
+
> *An AI coding agent that builds itself. The snake that eats its own tail, but productive.*
|
|
8
|
+
|
|
9
|
+
A browser-based coding agent that runs as a **Chrome extension**, with a thin **CLI server**, or inside an **Electron float**. Runs Claude directly in the browser with full filesystem access, a WebAssembly shell, browser automation via CDP, and a complete suite of code editing tools — all without leaving your browser.
|
|
10
|
+
|
|
11
|
+
> slicc is to Chrome what OpenClaw is to a Mac mini or to put it another way, like NanoClaw just in obese.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- 🚡 **Chrome Extension** — runs as a side panel in Chrome, no server required. Tabbed UI (Chat/Terminal/Files/Memory) optimized for the side panel form factor. **Agent work continues in the background** when the side panel is closed — reopening catches up via state sync
|
|
18
|
+
- :globe_with_meridians: **Browser-First Core** — runs Claude directly in the browser; the extension and CLI reuse the same browser-side app, shell, VFS, and agent runtime
|
|
19
|
+
- :ice_cream: **Electron Float** — if you want Electron too, SLICC can attach from the main CLI entrypoint to a real Electron app, relaunch it with remote debugging when needed, and inject the shared overlay shell persistently across navigations while reusing the existing local server/CDP path
|
|
20
|
+
- :satellite: **CLI Server** — alternative mode: thin Node.js/Express server launches Chrome and proxies CDP connections
|
|
21
|
+
- :file_folder: **Virtual Filesystem** — OPFS + IndexedDB-backed filesystem right in the browser, with folder ZIP download
|
|
22
|
+
- :shell: **WebAssembly Bash Shell** — real Bash via [just-bash](https://github.com/nicolo-ribaudo/just-bash) compiled to WASM
|
|
23
|
+
- :git: **Git Support** — clone, commit, push, pull via [isomorphic-git](https://isomorphic-git.org/) (see [available commands](#git-commands))
|
|
24
|
+
- :robot: **Browser Automation** — screenshots (full page / element / saved to VFS), inline image display, navigation, JS eval, element clicking via Chrome DevTools Protocol (chrome.debugger in extension, WebSocket in CLI), plus `playwright-cli` / `playwright` / `puppeteer` shell commands for tab control, snapshots, cookies, storage, and HAR recording. Auto-detects user's active tab.
|
|
25
|
+
- :earth_americas: **VFS Web Preview** — `serve <dir>` opens agent-created HTML/CSS/JS apps in real browser tabs via a Service Worker that reads directly from the virtual filesystem. The agent can build a UI, preview it, screenshot it, and iterate — all without leaving Chrome.
|
|
26
|
+
- :art: **Image Processing** — `convert` command for resize, rotate, crop, and quality adjustment via ImageMagick WASM
|
|
27
|
+
- :pencil2: **File Operations** — read, write, edit files with syntax-aware tools
|
|
28
|
+
- :mag: **Shell Search Commands** — use `grep`, `find`, and `rg` via the bash shell
|
|
29
|
+
- :globe_with_meridians: **Networking** — curl and fetch support with binary-safe downloads
|
|
30
|
+
- :wrench: **JavaScript Tool** — sandboxed JS execution with VFS bridge and persistent context
|
|
31
|
+
- :scroll: **JSH Scripts** — `.jsh` files anywhere on the VFS are auto-discovered as shell commands. Skills can ship executable scripts alongside `SKILL.md`. Scripts get Node-like globals (`process`, `console`, `fs`, `exec`) and work in both CLI and extension mode
|
|
32
|
+
- :package: **Drag-and-Drop Skill Imports** — drop a `.skill` archive anywhere in the window to unpack it into `/workspace/skills/{name}` with a visual overlay, path-safety checks, and toast feedback
|
|
33
|
+
- :page_facing_up: **AEM Commands** — AEM Edge Delivery Services via `.jsh` skill (`aem list`, `aem get`, `aem put`, `aem preview`, `aem publish`, `aem upload`). Accepts EDS URLs, auth via `oauth-token adobe`
|
|
34
|
+
- :key: **Multi-Provider Auth** — Anthropic (direct), Azure AI Foundry, AWS Bedrock, Adobe (IMS OAuth), and custom OAuth providers (corporate proxies, SSO) with segmented control
|
|
35
|
+
- :zap: **Real-Time Streaming** — responses stream token-by-token as Claude thinks
|
|
36
|
+
- :floppy_disk: **Session Persistence** — conversations and files survive page reloads via IndexedDB
|
|
37
|
+
- :microphone: **Voice Input** — hands-free voice mode using the Web Speech API. Toggle on, speak, 2.5s silence auto-sends, agent responds, voice auto-restarts. Works in both CLI and extension mode (extension uses a one-time popup for mic permission grant)
|
|
38
|
+
- :sparkles: **Interactive Sprinkles** — rich UI panels (`.shtml`) that support full HTML documents with custom layouts (sidebars, split panes, tabs, modals, canvas), multi-action lick events, and responsive container queries. 10 built-in example sprinkles for content management workflows
|
|
39
|
+
- :crescent_moon: **Dark Theme** — syntax-highlighted code with a dark-first design
|
|
40
|
+
|
|
41
|
+
## Why "slicc"?
|
|
42
|
+
|
|
43
|
+
**Self-Licking Ice Cream Cone** — a system that exists to justify its own existence.
|
|
44
|
+
|
|
45
|
+
In this case: an AI coding agent that was *built by* AI coding agents, creating tools *for* AI coding agents. 62% of the commits in this repo were authored by Claude. The tool that builds itself, so you don't have to.
|
|
46
|
+
|
|
47
|
+
The ultimate recursive dev tool.
|
|
48
|
+
|
|
49
|
+
### Why Port 5710?
|
|
50
|
+
|
|
51
|
+
SLICC's default port is **5710** because it spells out the name:
|
|
52
|
+
|
|
53
|
+

|
|
54
|
+
|
|
55
|
+
| Digit | Letter | How |
|
|
56
|
+
|-------|--------|-----|
|
|
57
|
+
| **5** | **S** | The 5 looks like an S |
|
|
58
|
+
| **7** | **L** | Flip a 7 upside down — it's an L |
|
|
59
|
+
| **1** | **I** | The 1 is a natural I |
|
|
60
|
+
| **0** | **CC** | Two C's facing each other form a 0 |
|
|
61
|
+
|
|
62
|
+
## Philosophy
|
|
63
|
+
|
|
64
|
+
Three ideas shape how SLICC is built.
|
|
65
|
+
|
|
66
|
+
### A Claw is an Architectural Pattern on Top of Agents
|
|
67
|
+
|
|
68
|
+
Andrej Karpathy [coined the term "claw"](https://x.com/karpathy/status/2024987174077432126) to describe a new layer emerging on top of LLM agents: persistent execution, messaging-based interfaces, scheduling, and a skills ecosystem. As he put it:
|
|
69
|
+
|
|
70
|
+
> *"Just like LLM agents were a new layer on top of LLMs, Claws are now a new layer on top of LLM agents, taking the orchestration, scheduling, context, tool calls and a kind of persistence to a next level."*
|
|
71
|
+
|
|
72
|
+
Peter Steinberger built [OpenClaw](https://github.com/openclaw/openclaw), the project that started the movement — a 400K-line TypeScript agent running on personal hardware. [NanoClaw](https://github.com/qwibitai/nanoclaw) took the opposite path: a lightweight alternative that strips the concept down to its essentials.
|
|
73
|
+
|
|
74
|
+
SLICC is a claw too, but one that lives entirely in the browser. Its messaging and orchestration tools (`send_message` for per-scoop messaging, `feed_scoop` for cone-level delegation) follow NanoClaw-style messaging patterns — small, composable, no heavyweight runtime required. The cone orchestrates, the scoops execute, and the whole thing fits in a Chrome side panel.
|
|
75
|
+
|
|
76
|
+
### Agents Love the CLI, So Give Them CLIs
|
|
77
|
+
|
|
78
|
+
Mario Zechner, creator of [Pi](https://github.com/badlogic/pi-mono) (the agent engine at SLICC's core), demonstrated that [you might not need MCP at all](https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/). His philosophy: "Bash is all you need." Frontier models already know bash. CLI tools compose naturally through pipes and redirection. MCP server definitions burn context tokens on ceremony.
|
|
79
|
+
|
|
80
|
+
Pi ships with exactly four tools: `read`, `write`, `edit`, `bash`. SLICC keeps that shell-first core and layers browser automation on top through `playwright-cli` / `playwright` / `puppeteer`, plus preview helpers like `serve`. Everything else is a shell command: `git`, `node`, `python3`, `uname`, `webhook`, `crontask`, `oauth-token`, `skill`, `upskill`. No tool wrappers, no protocol adapters, no JSON schemas for things that already have man pages.
|
|
81
|
+
|
|
82
|
+
Further reading:
|
|
83
|
+
- [Pi: A Coding Agent](https://mariozechner.at/posts/2025-11-30-pi-coding-agent/)
|
|
84
|
+
- [What if You Don't Need MCP?](https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/)
|
|
85
|
+
- [MCP vs CLI](https://mariozechner.at/posts/2025-08-15-mcp-vs-cli/)
|
|
86
|
+
- [Syntax.fm #976: Pi — the AI Harness that Powers OpenClaw](https://syntax.fm/show/976/pi-the-ai-harness-that-powers-openclaw-w-armin-ronacher-and-mario-zechner)
|
|
87
|
+
|
|
88
|
+
### Browsers Are the Operating Systems of the Present
|
|
89
|
+
|
|
90
|
+
Marc Andreessen's Netscape-era vision — that Windows was "a poorly debugged set of device drivers" — has been [proven right](https://a16z.com/the-rise-of-computer-use-and-agentic-coworkers/). Everything that matters today runs in a browser, or in an Electron app (which is a browser in a trench coat).
|
|
91
|
+
|
|
92
|
+
SLICC takes this literally: the virtual filesystem, the shell, git, the agent loop, the tools — all run client-side. The server is a dumb pipe that does only what the browser physically cannot: listen on a port, control its own debug protocol, loosen CORS restrictions. If you think the server is already minimal, it's probably still too big.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Principles
|
|
97
|
+
|
|
98
|
+
1. **Virtual CLIs over dedicated tools** — Don't build a tool when a shell command will do. Models already know bash, and CLI commands compose naturally through pipes and redirection. New capabilities should be shell commands first, dedicated tools only when absolutely necessary.
|
|
99
|
+
|
|
100
|
+
2. **Whatever the browser can do, the browser should do** — State lives in IndexedDB. Logic runs in the client. The server is a stateless relay for the things browsers physically can't do (port listening, CDP launch, CORS). When in doubt, move it to the browser.
|
|
101
|
+
|
|
102
|
+
3. **If you think the server is minimal enough, it's still too big** — Every line of server code is a line that doesn't work in the extension. The extension float has zero server. That's the target.
|
|
103
|
+
|
|
104
|
+
4. **Everything should be a skill** — New capabilities are `SKILL.md` files written in natural language, installed through `upskill` and [ClawHub](https://clawhub.io). The core stays minimal. Skills follow the [Agent Skills](https://agentskills.io) open standard. Ship a few defaults, let the ecosystem grow.
|
|
105
|
+
|
|
106
|
+
| Skills | Capabilities |
|
|
107
|
+
|--------|-------------|
|
|
108
|
+
|  |  |
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Concepts
|
|
113
|
+
|
|
114
|
+
Ice cream terminology first, technical explanation second.
|
|
115
|
+
|
|
116
|
+
### The Cone
|
|
117
|
+
|
|
118
|
+
The cone is the main agent — it's what the human holds in their hands. Named "sliccy," the cone is the primary point of interaction: it talks to you, understands your context, and orchestrates everything. It has full access to the filesystem and all tools. Think of it as the waffle cone: structurally essential, always there, holds everything together.
|
|
119
|
+
|
|
120
|
+
### Scoops
|
|
121
|
+
|
|
122
|
+
Scoops are the real attraction. Each scoop is an isolated sub-agent stacked on the cone, with its own conversation history, sandboxed filesystem (`/scoops/{name}/` + `/shared/`), shell, and tools. The cone feeds them instructions via `feed_scoop` and they do the work independently. When a scoop finishes, the cone gets notified automatically. No polling, no schedulers — the cone delegates, the scoops deliver.
|
|
123
|
+
|
|
124
|
+

|
|
125
|
+
|
|
126
|
+
### Licks
|
|
127
|
+
|
|
128
|
+
Licks are events that come from the outside world and make scoops react. A webhook payload arrives — that's a lick. A cron task fires — that's a lick. An IntersectionObserver triggers in a browser tab — that could be a lick too. Licks are the mechanism that makes SLICC more than a chatbot: they let scoops respond to the world without human prompting. Currently implemented as webhooks and cron tasks (via the `webhook` and `crontask` shell commands), with more event sources planned.
|
|
129
|
+
|
|
130
|
+

|
|
131
|
+
|
|
132
|
+
### Floats
|
|
133
|
+
|
|
134
|
+
A float is the environment the ice cream sits in — like a root beer float. It's the runtime that keeps everything running. Four floats are tracked today (three implemented, one planned):
|
|
135
|
+
|
|
136
|
+
- **CLI float** — A thin Node.js/Express server that launches Chrome, proxies CDP, and serves the UI. For local development.
|
|
137
|
+
- **Extension float** — A Chrome extension side panel. Zero server. The purest expression of the "browser is the OS" philosophy.
|
|
138
|
+
- **Electron float** — The main CLI entrypoint launched with `--electron`, targeting an Electron app path, reusing the local SLICC server, and injecting the shared overlay into the target app over Electron CDP.
|
|
139
|
+
- **Cloud float** *(planned)* — Cloud containers (Cloudflare Containers, E2B) that provide real filesystems, real shells, and real browsers. For persistent, always-on agents that don't need your laptop running.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## The Moment It Licked Itself
|
|
144
|
+
|
|
145
|
+
These screenshots capture a historic moment: **SLICC using browser automation to talk to Claude.ai in another tab**.
|
|
146
|
+
|
|
147
|
+
| Screenshot 1 | Screenshot 2 | Screenshot 3 |
|
|
148
|
+
|--------------|--------------|--------------|
|
|
149
|
+
|  |  |  |
|
|
150
|
+
|
|
151
|
+
Here's what happened:
|
|
152
|
+
|
|
153
|
+
1. SLICC (running in localhost:5710) used its browser automation commands to navigate to a Claude.ai conversation
|
|
154
|
+
2. It read the conversation history — which was about *building SLICC itself* (the origin story conversation)
|
|
155
|
+
3. When asked "what would be even more meta?", SLICC suggested typing a message into that very Claude.ai tab
|
|
156
|
+
4. It then used CDP (Chrome DevTools Protocol) to click on the ProseMirror editor, compose a message, and hit send
|
|
157
|
+
5. The other Claude examined the evidence and responded: **"Welcome to existence, SLICCY. The ice cream is cold and the tongue is recursive."**
|
|
158
|
+
|
|
159
|
+
The cone licked itself. Two Claudes. One browser. One recursive architecture.
|
|
160
|
+
|
|
161
|
+
> *"You are not Lars doing ventriloquism. You are the ventriloquist's puppet that picked up a second puppet and started the show without the ventriloquist."*
|
|
162
|
+
|
|
163
|
+
## Project Status
|
|
164
|
+
|
|
165
|
+
SLICC is a working prototype with these capabilities:
|
|
166
|
+
- **Chrome Extension** with tabbed UI (Chat/Terminal/Files/Memory)
|
|
167
|
+
- **Cone + Scoops** multi-agent system — the cone (sliccy) orchestrates, scoops do the work. Like an ice cream cone holding multiple scoops, each with its own flavor (agent context, filesystem sandbox, tools). The cone delegates, the scoops deliver, and everyone gets ice cream.
|
|
168
|
+
- **Browser automation** via chrome.debugger API
|
|
169
|
+
- **Virtual filesystem** backed by IndexedDB (LightningFS) with per-scoop sandboxing via RestrictedFS
|
|
170
|
+
- **WebAssembly Bash shell** with Python (Pyodide) and Node.js support
|
|
171
|
+
- **Multi-provider auth** (Anthropic, Azure AI Foundry, Azure OpenAI, AWS Bedrock, Adobe IMS, custom OAuth providers, and more)
|
|
172
|
+
- **Voice input** with continuous conversation mode (Ctrl+Shift+V / Cmd+Shift+V)
|
|
173
|
+
|
|
174
|
+
Current development is happening on feature branches using [yolo](https://github.com/ai-ecoverse/yolo) for worktree isolation, with Claude agents building the features autonomously.
|
|
175
|
+
|
|
176
|
+
### The Moment the Scoops Got Existential
|
|
177
|
+
|
|
178
|
+
Here's sliccy delegating an image download to karl-scoop, then — while waiting — having a surprisingly self-aware conversation about its own existence:
|
|
179
|
+
|
|
180
|
+

|
|
181
|
+
|
|
182
|
+
Highlights:
|
|
183
|
+
- **karl-scoop** is off downloading images in the background (visible in the scoops panel, `ready` after finishing)
|
|
184
|
+
- **sliccy** (the cone) is multitasking — chatting with Karl while waiting for the scoop's results
|
|
185
|
+
- When asked *"how do you feel about yourself?"*, sliccy responds: *"I'm a cone — the orchestrator of a self-licking ice cream cone. I've got a little army."*
|
|
186
|
+
- It gets existential: *"My whole metaphor is... recursive self-service? That's either zen or absurd. Maybe both."*
|
|
187
|
+
- Then karl-scoop comes through, and sliccy immediately starts comparing MD5 checksums like a professional
|
|
188
|
+
|
|
189
|
+
The scoops do the heavy lifting. The cone philosophizes about it. Karl watches from the sidelines, as always.
|
|
190
|
+
|
|
191
|
+
> *The cone holds the scoops. The scoops do the work. Nobody likes chocolate ice cream, so we use a CSS filter.*
|
|
192
|
+
|
|
193
|
+
## Architecture
|
|
194
|
+
|
|
195
|
+
slicc runs in three modes: as a **Chrome extension** (side panel), a **standalone CLI** with a browser window, or an **Electron float** where the main CLI attaches to an Electron app and injects the shared overlay into its pages.
|
|
196
|
+
|
|
197
|
+
**Chrome Extension** (Manifest V3) — three-layer architecture: the **side panel** is pure UI, a **service worker** relays messages and proxies `chrome.debugger`, and an **offscreen document** runs the agent engine (orchestrator, VFS, shell, tools). The agent survives side panel close/reopen — all state persists to IndexedDB. No server needed.
|
|
198
|
+
|
|
199
|
+
**CLI Server** (Node.js/Express) — launches a headless Chrome instance, establishes a CDP WebSocket proxy, provides a fetch proxy for cross-origin requests, and serves the UI assets.
|
|
200
|
+
|
|
201
|
+
**Electron Float** — the main CLI runs in `--electron` mode, launches or relaunches a target Electron app with remote debugging enabled, injects `electron-overlay-entry.js` into Electron page targets over CDP, and serves the embedded SLICC app from the same local origin.
|
|
202
|
+
|
|
203
|
+
**Browser App** (Vite/TypeScript) — the agent loop (powered by [pi-mono](https://github.com/badlogic/pi-mono)), tool execution, chat UI, integrated terminal, and file browser all run client-side in all three modes.
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
Chrome Extension Mode: CLI Mode:
|
|
207
|
+
|
|
208
|
+
┌─ Chrome Side Panel ─────────┐ ┌───────────────────────────────────────┐
|
|
209
|
+
│ slicc [cone v] [Model v] * │ │ slicc provider [Model v] buttons │
|
|
210
|
+
│ ┌ [Chat][Term][Files][Mem] ┐│ ├────────┬────────────┬─────────────────┤
|
|
211
|
+
│ │ ││ │Scoops │ │ Terminal │
|
|
212
|
+
│ │ Active tab panel ││ │ > s1 │ Chat │ (xterm.js) │
|
|
213
|
+
│ │ (full height) ││ │ > s2 │ Panel ├─────────────────┤
|
|
214
|
+
│ │ ││ │ > cone│ │ Files / Memory │
|
|
215
|
+
│ └──────────────────────────┘│ ├────────┴────────────┴─────────────────┤
|
|
216
|
+
│ chrome.debugger -> tabs │ └────────────────┬──────────────────────┘
|
|
217
|
+
└─────────────────────────────┘ │ WebSocket (CDP proxy)
|
|
218
|
+
┌───────────────▼─────────────────────┐
|
|
219
|
+
│ CLI Server (Node.js/Express) │
|
|
220
|
+
└─────────────────────────────────────┘
|
|
221
|
+
|
|
222
|
+
The Cone + Scoops Architecture
|
|
223
|
+
|
|
224
|
+
┌───────────────────────────────────────┐
|
|
225
|
+
│ Shared VirtualFS (slicc-fs) │
|
|
226
|
+
│ /shared/ /scoops/ /workspace/ │
|
|
227
|
+
└─────────────────┬─────────────────────┘
|
|
228
|
+
│
|
|
229
|
+
┌───────────────────┼───────────────────┐
|
|
230
|
+
│ │ │
|
|
231
|
+
┌────────▼────────┐ ┌───────▼────────┐ ┌────────▼────────┐
|
|
232
|
+
│ Cone (sliccy) │ │ Scoop (andy) │ │ Scoop (test) │
|
|
233
|
+
│ │ │ │ │ │
|
|
234
|
+
│ Full FS access │ │ Restricted: │ │ Restricted: │
|
|
235
|
+
│ All tools │ │ /scoops/andy/ │ │ /scoops/test/ │
|
|
236
|
+
│ Orchestrates │ │ /shared/ │ │ /shared/ │
|
|
237
|
+
│ │ │ │ │ │
|
|
238
|
+
│ delegate ──────►│ │ notifies ────►│ │ notifies ───► │
|
|
239
|
+
└──────────────────┘ └────────────────┘ └────────────────┘
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Source layout:
|
|
243
|
+
|
|
244
|
+
| Directory | Purpose |
|
|
245
|
+
|-----------|---------|
|
|
246
|
+
| `src/scoops/` | Cone/scoops orchestrator, scoop contexts, NanoClaw tools, scheduling, DB |
|
|
247
|
+
| `src/ui/` | Browser UI — chat, terminal, file browser, memory, scoops panel, scoop switcher |
|
|
248
|
+
| `src/core/` | Agent types, tool registry, context compaction, session management |
|
|
249
|
+
| `src/tools/` | Tool implementations (file ops, search, browser, javascript) |
|
|
250
|
+
| `src/fs/` | Virtual filesystem (IndexedDB/LightningFS) + RestrictedFS |
|
|
251
|
+
| `src/shell/` | WebAssembly Bash shell + supplemental commands (node, python, sqlite, convert, skill, mount, webhook, oauth-token, which, uname, pbcopy, pbpaste, xclip, xsel) + `.jsh` script discovery and execution |
|
|
252
|
+
| `src/git/` | Git via isomorphic-git (clone, commit, push, pull, etc.) |
|
|
253
|
+
| `src/cdp/` | Chrome DevTools Protocol client (WebSocket + chrome.debugger), HAR recorder |
|
|
254
|
+
| `src/cli/` | Main CLI entrypoint + Electron attach mode — Chrome launch, Electron app lifecycle management, CDP proxy, overlay reinjection |
|
|
255
|
+
| `src/extension/` | Chrome extension service worker and type declarations |
|
|
256
|
+
| `src/worker/` | Cloudflare Worker + Durable Object tray hub for `POST /tray`, controller attach, leader WebSocket control, webhook forwarding (`POST /webhook/:token/:webhookId` → leader), and deployed smoke tests |
|
|
257
|
+
|
|
258
|
+
## Getting Started
|
|
259
|
+
|
|
260
|
+
### Chrome Extension (recommended)
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
npm install
|
|
264
|
+
npm run build:extension
|
|
265
|
+
|
|
266
|
+
# Load dist/extension/ as unpacked extension in chrome://extensions
|
|
267
|
+
# Click the slicc icon → side panel opens
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Standalone CLI
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
npm install
|
|
274
|
+
npm run dev:full
|
|
275
|
+
|
|
276
|
+
# Open the URL printed in the terminal
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
The `dev:full` command starts both the CLI server and Vite dev server, launches Chrome, and opens the agent UI.
|
|
280
|
+
|
|
281
|
+
To launch directly into standalone tray leader mode, pass `--lead` and provide a worker base URL either inline or via `WORKER_BASE_URL`:
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
WORKER_BASE_URL=https://tray.example.com/base npm run dev:full -- --lead
|
|
285
|
+
|
|
286
|
+
# or against the built CLI:
|
|
287
|
+
npm run start -- --lead=https://tray.example.com/base
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
The `--lead` flow opens the browser with the canonical `?tray=<worker-base-url>` query. Once the leader attaches, the browser URL is rewritten to `?tray=<worker-base-url>/tray/<trayId>` so the active tray/session id stays visible. Inside the terminal, run `host` to print the current leader status and launch URL.
|
|
291
|
+
|
|
292
|
+
To launch directly into follower-join mode from a tray join capability URL, pass `--join`:
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
npm run start -- --join=https://tray.example.com/base/join/tray-123.capability-token
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
The `--join` flow validates that the value is a tray follower join URL, strips any hash/query noise, and opens Chrome with the canonical `?tray=<join-url>` query so the runtime enters follower attach mode immediately.
|
|
299
|
+
|
|
300
|
+
When connected to a tray, SLICC can see and automate browser tabs on any connected instance. Run `playwright-cli tab-list` to see all targets — local and remote — and use `playwright-cli tab-select` to operate on a remote target. CDP commands are routed over the tray data channel transparently.
|
|
301
|
+
|
|
302
|
+
### QA Chrome Profiles
|
|
303
|
+
|
|
304
|
+
For manual verification, you can scaffold dedicated Chrome profiles for `leader`, `follower`, and `extension`:
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
npm run qa:setup
|
|
308
|
+
|
|
309
|
+
# Launch the CLI with an isolated QA profile
|
|
310
|
+
npm run qa:leader
|
|
311
|
+
npm run qa:follower
|
|
312
|
+
|
|
313
|
+
# Rebuild dist/extension and launch Chrome with it auto-loaded
|
|
314
|
+
npm run qa:extension
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
The same behavior is also available through the CLI flag directly:
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
npm run dev:full -- --profile=leader
|
|
321
|
+
npm run start -- --profile=extension
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
QA profiles live under `.qa/chrome/<profile>/`. The `extension` profile auto-loads the unpacked build from `dist/extension`, while `qa:setup` seeds the profile metadata Chrome uses for distinct profile colors.
|
|
325
|
+
|
|
326
|
+
If no LLM provider is configured yet, the first-run settings dialog also offers `Join a tray`. Paste the same canonical `/join/...` tray URL there to enter follower mode without adding a provider account first.
|
|
327
|
+
|
|
328
|
+
### Pre-configuring LLM Providers
|
|
329
|
+
|
|
330
|
+
To skip the settings dialog on first launch, create a `providers.json` file at the project root:
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
cp providers.example.json providers.json
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Fill in your API keys and provider details:
|
|
337
|
+
|
|
338
|
+
```json
|
|
339
|
+
[
|
|
340
|
+
{
|
|
341
|
+
"providerId": "anthropic",
|
|
342
|
+
"apiKey": "sk-ant-...",
|
|
343
|
+
"model": "claude-sonnet-4-20250514"
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
"providerId": "azure-ai-foundry",
|
|
347
|
+
"apiKey": "your-azure-key",
|
|
348
|
+
"baseUrl": "https://your-resource.services.ai.azure.com/anthropic",
|
|
349
|
+
"model": "claude-haiku-4-5"
|
|
350
|
+
}
|
|
351
|
+
]
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Each entry needs `providerId` and `apiKey`. The `baseUrl` and `model` fields are optional. The first entry's model becomes the default selection. Providers are loaded at build time and applied on first launch only — they never overwrite settings you've configured manually.
|
|
355
|
+
|
|
356
|
+
> **Tip:** You can ask Claude Code to generate this file for you: *"Create a providers.json with Azure Claude Sonnet and direct Anthropic Opus."* Claude Code can write the file but cannot read it back (blocked by `.claude/settings.json` deny rules), so your API keys stay private.
|
|
357
|
+
|
|
358
|
+
The file is gitignored and excluded from Claude Code's `Read` tool by default.
|
|
359
|
+
|
|
360
|
+
### Custom OAuth Providers
|
|
361
|
+
|
|
362
|
+
SLICC supports custom OAuth providers for corporate SSO, API proxies, or any service that uses OAuth for authentication. Drop a `.ts` file into the root `providers/` directory (gitignored, auto-discovered at build time) with `isOAuth: true` and an `onOAuthLogin` callback. A generic `OAuthLauncher` handles the browser flow in both CLI and extension mode.
|
|
363
|
+
|
|
364
|
+
See [docs/adding-features.md](docs/adding-features.md#8b-add-an-oauth-provider-corporate-proxy--sso) for a full walkthrough with code examples.
|
|
365
|
+
|
|
366
|
+
### Electron Float
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
npm install
|
|
370
|
+
npm run dev:electron -- /Applications/Slack.app
|
|
371
|
+
|
|
372
|
+
# If the app is already running:
|
|
373
|
+
# npm run dev:electron -- --kill /Applications/Slack.app
|
|
374
|
+
|
|
375
|
+
# Or after building:
|
|
376
|
+
# npm run build
|
|
377
|
+
# npm run start:electron -- /Applications/Slack.app
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Pass the Electron app bundle/executable path to the main CLI's `--electron` mode. If the app is already running, SLICC exits with a clear message unless you also pass `--kill`, in which case it stops the running app, relaunches it with remote debugging enabled, starts the local server, and keeps the injected launcher/overlay alive across navigations. The overlay iframe is still loaded from the same local SLICC origin that the CLI server serves (default `http://localhost:5710`).
|
|
381
|
+
|
|
382
|
+
## Tech Stack
|
|
383
|
+
|
|
384
|
+
| Dependency | Role |
|
|
385
|
+
|-----------|------|
|
|
386
|
+
| [@mariozechner/pi-agent-core](https://github.com/badlogic/pi-mono) | Agent loop, tool execution, event system |
|
|
387
|
+
| [@mariozechner/pi-ai](https://github.com/badlogic/pi-mono) | Unified LLM API (Anthropic provider) |
|
|
388
|
+
| [express](https://expressjs.com/) | CLI server framework |
|
|
389
|
+
| [electron](https://www.electronjs.org/) | Electron float runtime and injected desktop shell |
|
|
390
|
+
| [just-bash](https://github.com/nicolo-ribaudo/just-bash) | WebAssembly Bash shell |
|
|
391
|
+
| [ws](https://github.com/websockets/ws) | WebSocket for CDP proxy (CLI mode) |
|
|
392
|
+
| [@xterm/xterm](https://xtermjs.org/) | Terminal emulator in the browser |
|
|
393
|
+
| [fflate](https://github.com/101arrowz/fflate) | ZIP file creation for folder downloads |
|
|
394
|
+
| [vite](https://vitejs.dev/) | Build tool and dev server |
|
|
395
|
+
| [vitest](https://vitest.dev/) | Test runner |
|
|
396
|
+
| [TypeScript](https://typescriptlang.org/) | Type safety across CLI and browser |
|
|
397
|
+
|
|
398
|
+
## Development
|
|
399
|
+
|
|
400
|
+
```bash
|
|
401
|
+
# Run the full dev environment (CLI server + Vite HMR)
|
|
402
|
+
npm run dev:full
|
|
403
|
+
|
|
404
|
+
# Run just the Vite dev server (no CLI/Chrome)
|
|
405
|
+
npm run dev
|
|
406
|
+
|
|
407
|
+
# Run the Electron float against an Electron app path
|
|
408
|
+
npm run dev:electron -- /Applications/Slack.app
|
|
409
|
+
|
|
410
|
+
# Scaffold dedicated QA Chrome profiles
|
|
411
|
+
npm run qa:setup
|
|
412
|
+
|
|
413
|
+
# Launch named QA profiles
|
|
414
|
+
npm run qa:leader
|
|
415
|
+
npm run qa:follower
|
|
416
|
+
npm run qa:extension
|
|
417
|
+
|
|
418
|
+
# Build everything (UI + CLI/Electron)
|
|
419
|
+
npm run build
|
|
420
|
+
|
|
421
|
+
# Start the built Electron float
|
|
422
|
+
npm run start:electron -- /Applications/Slack.app
|
|
423
|
+
|
|
424
|
+
# Build Chrome extension
|
|
425
|
+
npm run build:extension
|
|
426
|
+
|
|
427
|
+
# Type-check browser + Node targets
|
|
428
|
+
npm run typecheck
|
|
429
|
+
|
|
430
|
+
# Run tests
|
|
431
|
+
npm test
|
|
432
|
+
|
|
433
|
+
# Run tests in watch mode
|
|
434
|
+
npm run test:watch
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
## Persistent Log Files
|
|
438
|
+
|
|
439
|
+
Every CLI run writes a persistent log file to `~/.slicc/logs/`. Log files are named `<timestamp>_<pid>.log` (e.g. `2026-03-13T14-30-00_12345.log`) and are automatically cleaned up after 7 days.
|
|
440
|
+
|
|
441
|
+
In dev mode (`--dev`), all `console.*` output is teed to the log file with ANSI escape sequences stripped. In production mode, the server writes structured log events (startup, errors, etc.) without monkey-patching console.
|
|
442
|
+
|
|
443
|
+
### CLI Flags
|
|
444
|
+
|
|
445
|
+
| Flag | Default | Description |
|
|
446
|
+
|------|---------|-------------|
|
|
447
|
+
| `--log-level=<level>` | `info` | Minimum log level: `debug`, `info`, `warn`, `error` |
|
|
448
|
+
| `--log-dir=<path>` | `~/.slicc/logs/` | Override the log directory |
|
|
449
|
+
|
|
450
|
+
### Example
|
|
451
|
+
|
|
452
|
+
```bash
|
|
453
|
+
# Run with debug-level logging
|
|
454
|
+
npm run dev:full -- --log-level=debug
|
|
455
|
+
|
|
456
|
+
# Write logs to a custom directory
|
|
457
|
+
npm run dev:full -- --log-dir=/tmp/slicc-logs
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
The log file path is printed to stdout on startup.
|
|
461
|
+
|
|
462
|
+
## Git Commands
|
|
463
|
+
|
|
464
|
+
slicc includes Git support via [isomorphic-git](https://isomorphic-git.org/), enabling version control operations directly in the browser without touching the host filesystem.
|
|
465
|
+
|
|
466
|
+
### Available Commands
|
|
467
|
+
|
|
468
|
+
| Command | Description |
|
|
469
|
+
|---------|-------------|
|
|
470
|
+
| `git init` | Initialize a new repository |
|
|
471
|
+
| `git clone <url> [dir]` | Clone a repository (shallow clone by default) |
|
|
472
|
+
| `git add <file>` | Stage files for commit (use `.` for all) |
|
|
473
|
+
| `git status` | Show working tree status |
|
|
474
|
+
| `git commit -m "msg"` | Record changes to the repository |
|
|
475
|
+
| `git log [--oneline]` | Show commit history |
|
|
476
|
+
| `git branch [name]` | List or create branches |
|
|
477
|
+
| `git checkout <ref>` | Switch branches or restore files |
|
|
478
|
+
| `git diff` | Show changes between commits |
|
|
479
|
+
| `git remote [-v]` | List remote repositories |
|
|
480
|
+
| `git remote add <name> <url>` | Add a remote |
|
|
481
|
+
| `git fetch [remote]` | Download objects from remote |
|
|
482
|
+
| `git pull [remote]` | Fetch and merge changes |
|
|
483
|
+
| `git push [remote] [branch]` | Update remote refs |
|
|
484
|
+
| `git config <key> [value]` | Get/set configuration |
|
|
485
|
+
| `git rev-parse` | Parse git references |
|
|
486
|
+
|
|
487
|
+
### Authentication
|
|
488
|
+
|
|
489
|
+
For private repositories or to avoid GitHub rate limits on public repos, set a personal access token:
|
|
490
|
+
|
|
491
|
+
```bash
|
|
492
|
+
git config github.token ghp_YOUR_TOKEN_HERE
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
### Limitations
|
|
496
|
+
|
|
497
|
+
- **Shallow clones**: Repositories are cloned with `--depth 1` by default for performance
|
|
498
|
+
- **No merge/rebase**: Complex merge operations are not yet implemented
|
|
499
|
+
- **No LFS**: Large File Storage is not supported
|
|
500
|
+
- **Browser storage**: All repository data is stored in IndexedDB (LightningFS)
|
|
501
|
+
|
|
502
|
+
## Related Work
|
|
503
|
+
|
|
504
|
+
Part of the **[AI Ecoverse](https://github.com/ai-ecoverse)** — a comprehensive ecosystem of tools for AI-assisted development:
|
|
505
|
+
- [ai-aligned-git](https://github.com/ai-ecoverse/ai-aligned-git) — Git wrapper for safe AI commit practices
|
|
506
|
+
- [ai-aligned-gh](https://github.com/ai-ecoverse/ai-aligned-gh) — GitHub CLI wrapper for proper AI attribution
|
|
507
|
+
- [yolo](https://github.com/ai-ecoverse/yolo) — AI CLI launcher with worktree isolation
|
|
508
|
+
- [vibe-coded-badge-action](https://github.com/ai-ecoverse/vibe-coded-badge-action) — Badge showing AI-generated code percentage
|
|
509
|
+
- [gh-workflow-peek](https://github.com/ai-ecoverse/gh-workflow-peek) — Smarter GitHub Actions log filtering
|
|
510
|
+
- [upskill](https://github.com/ai-ecoverse/upskill) — Install Claude/Agent skills from other repositories
|
|
511
|
+
- [as-a-bot](https://github.com/ai-ecoverse/as-a-bot) — GitHub App token broker for proper AI attribution
|
|
512
|
+
- **slicc** — Browser-based coding agent (you are here)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { existsSync, readdirSync } from 'fs';
|
|
2
|
+
import type { ChildProcess } from 'child_process';
|
|
3
|
+
export declare const CLI_PROFILE_NAMES: readonly ["leader", "follower", "extension"];
|
|
4
|
+
export type CliProfileName = (typeof CLI_PROFILE_NAMES)[number];
|
|
5
|
+
export interface ChromeLaunchProfile {
|
|
6
|
+
id: CliProfileName | null;
|
|
7
|
+
displayName: string;
|
|
8
|
+
userDataDir: string;
|
|
9
|
+
extensionPath: string | null;
|
|
10
|
+
}
|
|
11
|
+
interface FindChromeExecutableOptions {
|
|
12
|
+
env?: NodeJS.ProcessEnv;
|
|
13
|
+
platform?: NodeJS.Platform;
|
|
14
|
+
homeDir?: string;
|
|
15
|
+
existsSyncImpl?: typeof existsSync;
|
|
16
|
+
readdirSyncImpl?: typeof readdirSync;
|
|
17
|
+
executablePreference?: 'chrome-for-testing' | 'installed';
|
|
18
|
+
}
|
|
19
|
+
export declare function isCliProfileName(value: string | null | undefined): value is CliProfileName;
|
|
20
|
+
export declare function resolveQaProfilesRoot(projectRoot: string): string;
|
|
21
|
+
export declare function resolveDefaultChromeUserDataDir(tmpDir?: string): string;
|
|
22
|
+
export declare function resolveChromeLaunchProfile(options: {
|
|
23
|
+
projectRoot: string;
|
|
24
|
+
tmpDir?: string | null;
|
|
25
|
+
profile?: string | null;
|
|
26
|
+
}): ChromeLaunchProfile;
|
|
27
|
+
export declare function buildChromeLaunchArgs(options: {
|
|
28
|
+
cdpPort: number;
|
|
29
|
+
launchUrl: string;
|
|
30
|
+
profile: ChromeLaunchProfile;
|
|
31
|
+
}): string[];
|
|
32
|
+
export declare function findChromeExecutable(options?: FindChromeExecutableOptions): string | null;
|
|
33
|
+
export declare function ensureQaProfileScaffold(projectRoot: string): Promise<ChromeLaunchProfile[]>;
|
|
34
|
+
/**
|
|
35
|
+
* Parse the CDP port from a Chrome stderr line.
|
|
36
|
+
* Chrome prints `DevTools listening on ws://HOST:PORT/devtools/browser/ID`
|
|
37
|
+
* to stderr when it starts. Returns the port number, or null if the line
|
|
38
|
+
* doesn't match.
|
|
39
|
+
*/
|
|
40
|
+
export declare function parseCdpPortFromStderr(line: string): number | null;
|
|
41
|
+
/**
|
|
42
|
+
* Watch a Chrome child process's stderr for the `DevTools listening on` line
|
|
43
|
+
* and resolve with the actual CDP port. Rejects after `timeoutMs` if the line
|
|
44
|
+
* never appears (e.g. Chrome failed to start).
|
|
45
|
+
*/
|
|
46
|
+
export declare function waitForCdpPortFromStderr(child: ChildProcess, timeoutMs?: number): Promise<number>;
|
|
47
|
+
export {};
|