jarvis-hq 0.0.3
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 +21 -0
- package/README.md +484 -0
- package/dist/bot-routes.js +196 -0
- package/dist/bot-store.js +297 -0
- package/dist/client-html.js +2241 -0
- package/dist/client-vendor.js +32 -0
- package/dist/client.js +118 -0
- package/dist/dictation.js +128 -0
- package/dist/env-file.js +79 -0
- package/dist/index.js +41 -0
- package/dist/jarvis-tools.js +143 -0
- package/dist/jarvis.js +341 -0
- package/dist/ls.js +46 -0
- package/dist/progress.js +33 -0
- package/dist/relay-client.js +216 -0
- package/dist/relay-types.js +2 -0
- package/dist/server-common.js +663 -0
- package/dist/server.js +530 -0
- package/dist/start-claude-code.js +557 -0
- package/dist/start-codex.js +886 -0
- package/dist/start-opencode.js +452 -0
- package/dist/start.js +742 -0
- package/dist/sync.js +15 -0
- package/dist/trophy.js +7 -0
- package/dist/turns.js +91 -0
- package/dist/workspace.js +152 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 anildukkipatty
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Jarvis
|
|
4
|
+
|
|
5
|
+
**A persistent AI engineering partner. Talk to it from anywhere; it puts coding agents to work on your machine.**
|
|
6
|
+
|
|
7
|
+
Run one command. Scan a QR code. Say what you need — Jarvis works out which project it concerns, hands the work to a Claude Code agent in that project's checkout, and you come back when it's done.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
[Installation](#installation) · [Quick Start](#quick-start) · [How It Works](#how-it-works) · [Commands](#commands) · [API Reference](#api-reference) · [Contributing](#contributing)
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
## What is Jarvis?
|
|
16
|
+
|
|
17
|
+
Jarvis is a **persistent engineering partner** built on top of Claude Code and other coding harnesses (Opencode, Codex). Underneath it is a bot hub:
|
|
18
|
+
|
|
19
|
+
A *bot* is a named, reusable agent you define once: a job description that is appended to the harness's own system prompt, an emoji and a name, setup instructions for what it needs on a machine, a default repo, a model, and a permission mode. Once a bot exists, you give it work in *threads* — each thread is a live agent session scoped to a folder, and a bot can have as many as you want.
|
|
20
|
+
|
|
21
|
+
Jarvis spins up a local server that serves the bot hub UI and bridges every thread to a real agent session on your machine — one that reads your files, writes code, and runs commands. The hub runs in your browser, on any device on your network. Your phone, your tablet, whatever.
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
You on the couch Your laptop
|
|
25
|
+
(phone browser) <---> (jarvis server)
|
|
26
|
+
WiFi bots → threads → Claude Code / Opencode / Codex
|
|
27
|
+
running in your local project directories
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
No copy-pasting. Just scan and go.
|
|
31
|
+
|
|
32
|
+
## Jarvis
|
|
33
|
+
|
|
34
|
+
Jarvis is the front door. Instead of picking a bot and a folder, you open the hub and say what you need:
|
|
35
|
+
|
|
36
|
+
> What's the latest commit on Grass? · Review Madan's latest PR · Did we ever build the MCP feature in Zap Eve? Check it's ready for tomorrow's demo.
|
|
37
|
+
|
|
38
|
+
Jarvis works out which **project** the request concerns and how the work should happen:
|
|
39
|
+
|
|
40
|
+
- **Handoff** — the conversation moves into the project. Its agent (Claude Code, running in the project's checkout) answers you directly, and your follow-ups ("why did we do that?", "review it properly", "fix it, but don't merge") stay there with full context.
|
|
41
|
+
- **Delegate** — Jarvis gives one or more project agents a bounded task, waits for their reports, and answers you itself. Used for cross-project questions and anything Jarvis needs to combine.
|
|
42
|
+
|
|
43
|
+
Work runs on the machine where `jarvis start` is running, so you can close your phone and come back: the **Recent** list on the Jarvis screen shows every thread across projects, with the ones still running marked live, and opening one rejoins it.
|
|
44
|
+
|
|
45
|
+
### Projects
|
|
46
|
+
|
|
47
|
+
A project is an engineering context, not just a repo. Each one is a Markdown file under `~/jarvis/projects/<slug>.md`:
|
|
48
|
+
|
|
49
|
+
```markdown
|
|
50
|
+
---
|
|
51
|
+
name: Grass
|
|
52
|
+
path: /Users/you/projects/grass
|
|
53
|
+
repo: https://github.com/you/grass
|
|
54
|
+
---
|
|
55
|
+
# Grass
|
|
56
|
+
People, useful commands, architecture notes, previous work — whatever helps.
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Jarvis reads these, keeps them up to date as it learns, and creates one when you mention a project it doesn't know: it will offer an unclaimed folder in the workspace if one matches, or ask for the repo URL and clone it. `~/jarvis/CLAUDE.md` holds what Jarvis should always know about you (standing rules, people). Set `JARVIS_DIR` to move the directory.
|
|
60
|
+
|
|
61
|
+
Under the hood, Jarvis and every project are bots in the hub — so threads, resume, transcripts and the Projects & bots page all work as before. Jarvis runs with its own in-process tools (`list_projects`, `read_project`, `create_project`, `update_project`, `delegate`, `handoff`) and without a shell of its own; project agents run in `auto-approve` mode so dispatched work does not stall waiting for taps. Neither merges, pushes to a shared branch or deletes anything unless you asked for it in the conversation.
|
|
62
|
+
|
|
63
|
+
Run `jarvis start` from the directory that holds your checkouts (e.g. `~/projects`) — that is where new projects are cloned.
|
|
64
|
+
|
|
65
|
+
## Installation
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npm install -g jarvis-ai
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
That's it. `jarvis` is now available everywhere.
|
|
72
|
+
|
|
73
|
+
> [!NOTE]
|
|
74
|
+
> Jarvis requires **Node.js 18+**. The Claude Code agent requires the `claude` CLI to be installed and authenticated on your machine. The Opencode agent requires the `@opencode-ai/sdk` package. The Codex agent requires the `codex` CLI.
|
|
75
|
+
|
|
76
|
+
### Build from source
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
git clone https://github.com/anildukkipatty/grass-ide.git
|
|
80
|
+
cd grass-ide/cli # branch: jarvis
|
|
81
|
+
|
|
82
|
+
npm install
|
|
83
|
+
npm run build
|
|
84
|
+
npm install -g .
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
## Quick Start
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Navigate to a workspace directory (parent of your repos, or a specific project)
|
|
92
|
+
cd ~/projects
|
|
93
|
+
|
|
94
|
+
# Start Jarvis
|
|
95
|
+
jarvis start -p 3000
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
That's it. You'll see something like:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
jarvis — starting in /Users/you/projects
|
|
102
|
+
available agents: claude-code, opencode, codex
|
|
103
|
+
workspace: /Users/you/projects
|
|
104
|
+
port: 3000 (specified)
|
|
105
|
+
|
|
106
|
+
Local Network http://192.168.1.42:3000
|
|
107
|
+
|
|
108
|
+
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
|
109
|
+
█ ▄▄▄▄▄ █ █ █ █
|
|
110
|
+
█ █ █ █▄█ █ █
|
|
111
|
+
█ ▄▄▄▄▄ █ ▄▄█ █
|
|
112
|
+
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
113
|
+
|
|
114
|
+
Scan to open on your phone
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Open the URL or scan the QR code. You land on the Jarvis screen: ask about any project, or hand over some work. The Projects page underneath still lets you make hand-crafted bots with their own instructions and setup steps.
|
|
118
|
+
|
|
119
|
+
## How It Works
|
|
120
|
+
|
|
121
|
+
Jarvis runs a single HTTP server that handles everything:
|
|
122
|
+
|
|
123
|
+
1. **Serves the bot hub UI** — A full-featured React app, embedded directly in the binary. No separate frontend to deploy.
|
|
124
|
+
2. **Stores your bots** — Bots and their threads live in a JSON store under your home directory, so they survive restarts and are shared by every workspace on the machine.
|
|
125
|
+
3. **Manages a workspace** — Jarvis treats the directory where you run `jarvis start` as a workspace. It can list the subdirectories as repos, browse their file trees, read files, and clone new repos into the workspace.
|
|
126
|
+
4. **Bridges bots to harnesses** — Each thread creates a real agent session via the Claude Agent SDK (Claude Code), the Opencode SDK, or the Codex CLI, with the bot's instructions appended to the harness's own system prompt. The agent sees your project files, can edit code, run commands — everything it normally does.
|
|
127
|
+
5. **Streams events to the UI** — Agent output is delivered via Server-Sent Events (SSE), so the UI receives a live stream of assistant messages, tool calls, permission requests, and status updates.
|
|
128
|
+
|
|
129
|
+
By default the connection is local: your prompts go from your browser, over your WiFi, to the Jarvis server on your machine. Nothing leaves your network (except the agent's own API calls to Anthropic or its configured provider). Pass `--relay` instead and the server dials out to a relay so you can reach it from outside your LAN.
|
|
130
|
+
|
|
131
|
+
### Bots carry their own setup
|
|
132
|
+
|
|
133
|
+
A bot can declare what it needs from a machine — "ffmpeg must be on PATH", "run `npm install` in the repo". The first time that bot lands on a machine, Jarvis opens a **setup thread** and lets the bot prepare the machine itself, once. Until that setup is marked complete, the bot will not accept work threads. Setup travels with the bot definition, so a bot shared with someone else knows how to set itself up on their machine too.
|
|
134
|
+
|
|
135
|
+
### Threads are where the work happens
|
|
136
|
+
|
|
137
|
+
A thread belongs to one bot and runs in one folder — the folder you pick, else the bot's default repo, else the directory you started Jarvis in. Threads are listed, renamed, rejoined and deleted from the hub, and their messages are read back from the harness's own transcript on disk rather than duplicated into Jarvis's store.
|
|
138
|
+
|
|
139
|
+
### Sessions are persistent
|
|
140
|
+
|
|
141
|
+
Close your browser tab. Your phone dies. The WiFi drops. It doesn't matter — your agent session keeps running on your machine. When you reconnect, you pick up right where you left off. Claude Code session history is loaded from its transcript files on disk; Opencode history is fetched from its local server.
|
|
142
|
+
|
|
143
|
+
### Permissions are forwarded to you
|
|
144
|
+
|
|
145
|
+
When the agent wants to do something that needs approval (run a bash command, edit a file, fetch a URL), you'll see a permission prompt right in the chat UI. You approve or deny from your phone. You stay in control.
|
|
146
|
+
|
|
147
|
+
### Dictation
|
|
148
|
+
|
|
149
|
+
Both message boxes have a mic button: tap to record, tap again to stop. The clip is transcribed with Deepgram (`nova-2`) and then cleaned up by `gpt-4o-mini` — filler words dropped, self-corrections resolved ("5, no, make it 6" becomes "6") — and the polished instruction lands in the box for you to review and send. Set `DEEPGRAM_API_KEY` and `OPENAI_API_KEY` to enable it — either exported in the shell or in an env file (see below). Browsers only allow microphone access over `https` or on `localhost`, so on a plain-`http` LAN address the button will report that; relay mode works from any device.
|
|
150
|
+
|
|
151
|
+
### API keys and env files
|
|
152
|
+
|
|
153
|
+
Jarvis reads keys from `process.env`, and on startup it also loads them from the first of these files that defines them — a real environment variable always wins:
|
|
154
|
+
|
|
155
|
+
| Path | When to use it |
|
|
156
|
+
|---|---|
|
|
157
|
+
| `$JARVIS_ENV_FILE` | explicit override |
|
|
158
|
+
| `./.env` | the directory you run `jarvis start` in |
|
|
159
|
+
| `~/.config/jarvis/env` | machine-wide; written by `scripts/sandbox-setup.sh` |
|
|
160
|
+
|
|
161
|
+
```sh
|
|
162
|
+
# .env
|
|
163
|
+
DEEPGRAM_API_KEY=...
|
|
164
|
+
OPENAI_API_KEY=...
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Usual format: `KEY=value` per line, `#` comments, optional quotes, a leading `export` is ignored. Each file that supplies a key is printed at startup. `.env` is gitignored — keep keys out of the repo.
|
|
168
|
+
|
|
169
|
+
### Ports and the relay
|
|
170
|
+
|
|
171
|
+
`jarvis start` runs locally and binds port `3000` by default. Pass `-p <port>` to use a different one — handy when several instances run at once in different directories. Passing `-r <url>` (and no `-p`) switches to relay mode instead: the server dials out to the relay, defaulting to `wss://relay.codeongrass.com`, so the hub is reachable from outside your LAN. An explicit `-p` always wins over `-r`.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Commands
|
|
176
|
+
|
|
177
|
+
### `jarvis start`
|
|
178
|
+
|
|
179
|
+
The only command. Starts Jarvis — an HTTP server with SSE event streaming.
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
jarvis start [options]
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
| Flag | Description |
|
|
186
|
+
|---|---|
|
|
187
|
+
| `-p, --port <number>` | Bind this local port and serve the UI at `http://localhost:<port>` (implies `--local`; default `3000`) |
|
|
188
|
+
| `-l, --local` | Bind a local port instead of connecting to the relay |
|
|
189
|
+
| `-r, --relay <url>` | Connect to a relay server instead of binding a local port (default: `wss://relay.codeongrass.com`) |
|
|
190
|
+
| `-c, --caffeinate` | Prevent macOS sleep for 8 hours while the server is running |
|
|
191
|
+
|
|
192
|
+
**Examples:**
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# Default — local server on port 3000, great for a phone on the same WiFi
|
|
196
|
+
jarvis start
|
|
197
|
+
|
|
198
|
+
# A different local port
|
|
199
|
+
jarvis start -p 4000
|
|
200
|
+
|
|
201
|
+
# Relay mode — reachable from outside your LAN
|
|
202
|
+
jarvis start --relay wss://relay.codeongrass.com
|
|
203
|
+
|
|
204
|
+
# Point at your own relay
|
|
205
|
+
jarvis start --relay wss://relay.example.com
|
|
206
|
+
|
|
207
|
+
# Keep your Mac awake while your bots work
|
|
208
|
+
jarvis start -p 3000 --caffeinate
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## API Reference
|
|
214
|
+
|
|
215
|
+
Jarvis exposes a REST + SSE API. All endpoints return JSON unless noted.
|
|
216
|
+
|
|
217
|
+
### Workspace & Infrastructure
|
|
218
|
+
|
|
219
|
+
| Method | Path | Description |
|
|
220
|
+
|---|---|---|
|
|
221
|
+
| `GET` | `/health` | Returns `{ status: "ok", cwd }` |
|
|
222
|
+
| `GET` | `/agents` | Returns `{ agents: string[] }` — list of available agents |
|
|
223
|
+
| `GET` | `/repos` | List subdirectories of the workspace as `{ name, path, isGit }[]` |
|
|
224
|
+
| `GET` | `/repos/details?repoPath=<path>` | Returns `{ branch, lastCommit, dominantLanguage }` for a specific repo |
|
|
225
|
+
| `POST` | `/repos/clone` | Clone a git repo into the workspace. Body: `{ url }`. Returns `{ path, name }` |
|
|
226
|
+
| `POST` | `/folders` | Create an empty folder in the workspace. Body: `{ name }`. Returns `{ path, name }` |
|
|
227
|
+
| `GET` | `/dir?repoPath=<path>&path=<subpath>` | List directory entries (files and folders) within a repo. Path is validated to stay inside `repoPath`. |
|
|
228
|
+
| `GET` | `/file?repoPath=<path>&path=<filePath>` | Read a file. Path is validated to stay inside `repoPath`. 5 MB max. |
|
|
229
|
+
| `GET` | `/diffs?repoPath=<path>` | Returns `git diff HEAD` output for a repo as `{ diff }` |
|
|
230
|
+
|
|
231
|
+
### Jarvis
|
|
232
|
+
|
|
233
|
+
| Method | Path | Description |
|
|
234
|
+
|---|---|---|
|
|
235
|
+
| `GET` | `/jarvis` | Jarvis's bot, its directory, and the known projects |
|
|
236
|
+
| `POST` | `/jarvis/ask` | Start a fresh Jarvis conversation. Body: `{ prompt }`. Returns `{ thread, sessionId }` |
|
|
237
|
+
| `GET` | `/sessions/active` | Threads with a turn in flight, as `{ active: { threadId, sessionId }[] }` — for rejoining after a reload |
|
|
238
|
+
|
|
239
|
+
Jarvis's event stream carries three extra event types: `delegation` (`project`, `botId`, `threadId`, `sessionId`, `title`, `status`), `handoff` (same fields, no status — the client moves to that thread) and `project_created` (`project`).
|
|
240
|
+
|
|
241
|
+
### Bots & Threads
|
|
242
|
+
|
|
243
|
+
| Method | Path | Description |
|
|
244
|
+
|---|---|---|
|
|
245
|
+
| `GET` | `/bots` | List all bots |
|
|
246
|
+
| `POST` | `/bots` | Create a bot. Body: `{ name, description?, emoji?, instructions?, setupInstructions?, model?, repoPath?, permissionMode?, allowedTools?, disallowedTools? }`. Returns `{ bot, setupThread? }` |
|
|
247
|
+
| `GET` | `/bots/:id` | Fetch one bot |
|
|
248
|
+
| `PATCH` | `/bots/:id` | Update a bot. Returns `{ bot, setupThread? }` |
|
|
249
|
+
| `DELETE` | `/bots/:id` | Delete a bot |
|
|
250
|
+
| `POST` | `/bots/:id/setup` | Mark this machine's setup. Body: `{ action: "complete" \| "reset" \| "fail" }` |
|
|
251
|
+
| `GET` | `/threads?botId=<id>` | List threads, optionally filtered to one bot |
|
|
252
|
+
| `POST` | `/threads` | Open a thread. Body: `{ botId, repoPath?, title? }`. Returns `409` with `setupRequired` if the bot has not set up this machine yet |
|
|
253
|
+
| `GET` | `/threads/:id` | Fetch one thread |
|
|
254
|
+
| `PATCH` | `/threads/:id` | Update a thread (e.g. rename) |
|
|
255
|
+
| `DELETE` | `/threads/:id` | Delete a thread |
|
|
256
|
+
| `GET` | `/threads/:id/messages` | Message history for a thread, read from the harness transcript |
|
|
257
|
+
|
|
258
|
+
### Sessions
|
|
259
|
+
|
|
260
|
+
| Method | Path | Description |
|
|
261
|
+
|---|---|---|
|
|
262
|
+
| `GET` | `/sessions?agent=<agent>&repoPath=<path>` | List past sessions for a repo and agent |
|
|
263
|
+
| `GET` | `/sessions/:id/history?agent=<agent>&repoPath=<path>` | Load message history for a session |
|
|
264
|
+
| `GET` | `/sessions/:id/status` | Returns `{ streaming: boolean }` |
|
|
265
|
+
| `POST` | `/sessions/:id/abort` | Cancel an in-progress session |
|
|
266
|
+
| `POST` | `/sessions/:id/permission` | Respond to a permission request. Body: `{ toolUseID, approved: boolean }` |
|
|
267
|
+
|
|
268
|
+
### Chat
|
|
269
|
+
|
|
270
|
+
| Method | Path | Description |
|
|
271
|
+
|---|---|---|
|
|
272
|
+
| `POST` | `/chat` | Start or continue a session. Body: `{ repoPath, agent, prompt, sessionId? }`. Returns `{ sessionId }` |
|
|
273
|
+
|
|
274
|
+
### Dictation
|
|
275
|
+
|
|
276
|
+
| Method | Path | Description |
|
|
277
|
+
|---|---|---|
|
|
278
|
+
| `GET` | `/dictate/status` | Returns `{ deepgram: boolean, openai: boolean }` — whether each key is set |
|
|
279
|
+
| `POST` | `/dictate` | Transcribe and clean up a voice clip. Body: `{ audio: <base64>, mimeType }`. Returns `{ text }` |
|
|
280
|
+
|
|
281
|
+
### Streaming Events
|
|
282
|
+
|
|
283
|
+
| Method | Path | Description |
|
|
284
|
+
|---|---|---|
|
|
285
|
+
| `GET` | `/events?sessionId=<id>` | SSE stream for a specific session. Supports `Last-Event-ID` for reconnect/replay. |
|
|
286
|
+
| `GET` | `/permissions/events` | Global SSE stream of all pending permission requests across all active sessions |
|
|
287
|
+
|
|
288
|
+
#### SSE Event Types (`/events`)
|
|
289
|
+
|
|
290
|
+
| Event type | Payload fields | Description |
|
|
291
|
+
|---|---|---|
|
|
292
|
+
| `user_prompt` | `prompt` | The prompt that was sent to the agent |
|
|
293
|
+
| `system` | `subtype`, `data` | Agent session initialized |
|
|
294
|
+
| `assistant` | `content` | Streaming assistant text |
|
|
295
|
+
| `tool_use` | `tool_name`, `tool_input` | Agent is calling a tool |
|
|
296
|
+
| `status` | `status`, `tool_name?` | Activity indicator ("thinking", "tool") |
|
|
297
|
+
| `permission_request` | `toolUseID`, `toolName`, `input` | Agent is requesting permission |
|
|
298
|
+
| `result` | `subtype`, `cost`, `duration_ms`, `num_turns` | Query complete (success or error) |
|
|
299
|
+
| `done` | — | Session finished |
|
|
300
|
+
| `aborted` | `message` | Session was cancelled |
|
|
301
|
+
| `error` | `message` | An error occurred |
|
|
302
|
+
| `agent_error` | `message` | Agent-side error (opencode) |
|
|
303
|
+
|
|
304
|
+
Events include a `seq` field and are delivered with SSE `id:` headers so clients can use `Last-Event-ID` to resume a stream without missing events.
|
|
305
|
+
|
|
306
|
+
#### SSE Event Types (`/permissions/events`)
|
|
307
|
+
|
|
308
|
+
| Event type | Payload fields | Description |
|
|
309
|
+
|---|---|---|
|
|
310
|
+
| `permissions` | `permissions[]` | Full snapshot of all pending permissions across all sessions |
|
|
311
|
+
|
|
312
|
+
Each permission entry includes `sessionId`, `agent`, `repoPath`, `repoName`, `toolUseID`, `toolName`, and `input`.
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Architecture
|
|
317
|
+
|
|
318
|
+
```
|
|
319
|
+
┌─────────────────────────────┐
|
|
320
|
+
│ Browser (any device) │
|
|
321
|
+
│ React bot hub UI │
|
|
322
|
+
│ ─ bots + threads │
|
|
323
|
+
│ ─ repo + folder picker │
|
|
324
|
+
│ ─ markdown rendering │
|
|
325
|
+
│ ─ syntax highlighting │
|
|
326
|
+
│ ─ permission modals │
|
|
327
|
+
│ ─ diff viewer │
|
|
328
|
+
│ ─ file browser │
|
|
329
|
+
└──────────┬──────────────────┘
|
|
330
|
+
│ HTTP + SSE
|
|
331
|
+
│ (local port, or via relay)
|
|
332
|
+
┌──────────▼──────────────────┐
|
|
333
|
+
│ Jarvis Server │
|
|
334
|
+
│ ─ bot + thread store │
|
|
335
|
+
│ ─ workspace management │
|
|
336
|
+
│ ─ session management │
|
|
337
|
+
│ ─ tool permission relay │
|
|
338
|
+
│ ─ SSE event streaming │
|
|
339
|
+
│ ─ repo details + file API │
|
|
340
|
+
└──────┬───────────┬──────────┘
|
|
341
|
+
│ │ │
|
|
342
|
+
Claude SDK Opencode SDK Codex CLI
|
|
343
|
+
┌──────▼──────┐ ┌──▼──────────┐ ┌▼────────────┐
|
|
344
|
+
│ Claude Code │ │ Opencode │ │ Codex │
|
|
345
|
+
│ harness │ │ harness │ │ harness │
|
|
346
|
+
└─────────────┘ └─────────────┘ └─────────────┘
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Transport: SSE instead of WebSocket
|
|
350
|
+
|
|
351
|
+
Jarvis uses **Server-Sent Events (SSE)** for streaming, not WebSockets. The client sends requests via regular HTTP POST and receives the response stream via a GET `/events` connection. This means:
|
|
352
|
+
|
|
353
|
+
- Standard HTTP — works through proxies and most network configurations
|
|
354
|
+
- The `Last-Event-ID` header lets clients reconnect and replay any buffered events they missed
|
|
355
|
+
- The `/permissions/events` endpoint provides a single global stream for all pending permissions, useful for building dashboard-style UIs that manage multiple sessions at once
|
|
356
|
+
|
|
357
|
+
### Session Management
|
|
358
|
+
|
|
359
|
+
Sessions are the core abstraction. A session is created when a `/chat` POST is received, and lives in memory on the server.
|
|
360
|
+
|
|
361
|
+
- **Persistence** — Sessions survive client disconnects. If the browser closes mid-query, the agent keeps running. When the client reconnects, it can replay buffered events using `Last-Event-ID`.
|
|
362
|
+
- **Resumption** — Clients can resume prior sessions by passing `sessionId` to `/chat`. For Claude Code, the SDK resumes from the `.jsonl` transcript file on disk. For Opencode, the SDK resumes from its local session store.
|
|
363
|
+
- **Multi-repo** — Each session is scoped to a `repoPath`. The agent runs with that directory as its working directory.
|
|
364
|
+
- **Idle cleanup** — Automatic cleanup is currently disabled. Sessions are kept in memory indefinitely (cleanup will be re-enabled once a race-condition-free implementation is ready).
|
|
365
|
+
- **Abort** — `POST /sessions/:id/abort` cancels a running session. For Claude Code, this signals an `AbortController`. For Opencode, it calls the SDK abort endpoint and immediately marks the session done.
|
|
366
|
+
|
|
367
|
+
### Multi-Agent Support
|
|
368
|
+
|
|
369
|
+
Jarvis detects which harnesses are available at startup by checking for the `claude` CLI, the `@opencode-ai/sdk` package, and the `codex` CLI. It reports the available agents at `/agents`. A bot's `model` and `permissionMode` are applied to whichever harness runs its threads.
|
|
370
|
+
|
|
371
|
+
**Claude Code** (`claude-code`): Uses the `@anthropic-ai/claude-agent-sdk` `query()` function. Runs the `claude-opus-4-6` model in `default` permission mode. Supports `canUseTool` for per-tool permission prompts. Session transcripts are stored at `~/.claude/projects/<cwd>/<session-id>.jsonl`.
|
|
372
|
+
|
|
373
|
+
**Opencode** (`opencode`): Uses the `@opencode-ai/sdk`. Jarvis spawns an Opencode server process at startup (or connects to one already running on port 4096). Per-directory clients are maintained so sessions can be scoped to different repos simultaneously. Events are received via a persistent Opencode event stream (`client.event.subscribe()`). If the stream fails, it reconnects automatically after 2 seconds.
|
|
374
|
+
|
|
375
|
+
### Repo Details
|
|
376
|
+
|
|
377
|
+
`GET /repos/details?repoPath=<path>` returns metadata about a git repository without loading its full file tree:
|
|
378
|
+
|
|
379
|
+
- **`branch`** — current HEAD branch name
|
|
380
|
+
- **`lastCommit`** — message, hash, and timestamp of the most recent commit
|
|
381
|
+
- **`dominantLanguage`** — the most common file extension in the repo (determined by `git ls-files`, so it respects `.gitignore`)
|
|
382
|
+
|
|
383
|
+
### File System API
|
|
384
|
+
|
|
385
|
+
`GET /dir` and `GET /file` provide a sandboxed file browser. Both endpoints validate that the requested path is inside the given `repoPath` before serving anything, preventing path traversal. `readFile` enforces a 5 MB cap.
|
|
386
|
+
|
|
387
|
+
### Session Titles
|
|
388
|
+
|
|
389
|
+
When listing Claude Code sessions, Jarvis first looks for a `custom-title` entry in the session's `.jsonl` transcript. If found, that title is used as the session preview. Otherwise, it collects text from the first few user and assistant messages to build a ~80-character preview string.
|
|
390
|
+
|
|
391
|
+
### Chat UI Features
|
|
392
|
+
|
|
393
|
+
The UI is a self-contained React app embedded in the server binary. No build step, no separate deployment.
|
|
394
|
+
|
|
395
|
+
- **Bot hub** — create, edit and delete bots; presets to start from; per-bot thread lists
|
|
396
|
+
- **Setup threads** — a bot prepares this machine once, in a thread of its own, before it takes work
|
|
397
|
+
- **Repo + folder picker** — choose where a thread runs
|
|
398
|
+
- **Markdown rendering** with syntax-highlighted code blocks (via `marked` + `highlight.js`)
|
|
399
|
+
- **Light/dark theme** toggle (persisted in `localStorage`, respects system preference)
|
|
400
|
+
- **Session picker** — browse and resume prior conversations
|
|
401
|
+
- **Diff viewer** — full-screen file-by-file git diff display with syntax highlighting
|
|
402
|
+
- **File browser** — browse the repo file tree and read file contents from within the UI
|
|
403
|
+
- **Permission modals** — approve/deny the agent's tool usage with formatted previews (including diff previews for file edits)
|
|
404
|
+
- **Activity indicators** — animated status showing what the agent is doing ("Thinking", "Reading file", "Running bash")
|
|
405
|
+
- **Cost tracking** — each response shows API cost and duration
|
|
406
|
+
- **Mobile-first** — safe-area insets, touch targets, disabled zoom, `100dvh` layout
|
|
407
|
+
- **Auto-reconnect** — exponential backoff with connection status indicator
|
|
408
|
+
|
|
409
|
+
## Project Structure
|
|
410
|
+
|
|
411
|
+
```
|
|
412
|
+
cli/
|
|
413
|
+
├── src/
|
|
414
|
+
│ ├── index.ts # CLI entrypoint (commander setup)
|
|
415
|
+
│ ├── server.ts # HTTP request routing, session lifecycle
|
|
416
|
+
│ ├── server-common.ts # Shared: HTTP server, SSE, session store, workspace routes
|
|
417
|
+
│ ├── start-claude-code.ts # Claude Code harness integration
|
|
418
|
+
│ ├── start-opencode.ts # Opencode harness integration
|
|
419
|
+
│ ├── start-codex.ts # Codex harness integration
|
|
420
|
+
│ ├── workspace.ts # Repo listing, file browser, git details, clone
|
|
421
|
+
│ ├── bot-store.ts # Bot + thread persistence (JSON store)
|
|
422
|
+
│ ├── bot-routes.ts # REST surface for /bots and /threads
|
|
423
|
+
│ ├── jarvis.ts # Jarvis directory, project files, Jarvis/project bots and prompts
|
|
424
|
+
│ ├── jarvis-tools.ts # Jarvis's in-process tools: projects, delegate, handoff
|
|
425
|
+
│ ├── turns.ts # Start a turn on a thread (shared by /chat and Jarvis)
|
|
426
|
+
│ ├── relay-client.ts # Relay mode transport
|
|
427
|
+
│ └── client-html.ts # Embedded React bot hub UI
|
|
428
|
+
├── dist/ # Compiled output (CommonJS)
|
|
429
|
+
├── package.json
|
|
430
|
+
├── tsconfig.json
|
|
431
|
+
└── CLAUDE.md # Project instructions for Claude Code
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
## Tech Stack
|
|
435
|
+
|
|
436
|
+
| Component | Technology |
|
|
437
|
+
|---|---|
|
|
438
|
+
| Language | TypeScript (CommonJS, ES2020) |
|
|
439
|
+
| CLI | Commander v14 |
|
|
440
|
+
| Transport | HTTP + Server-Sent Events (SSE) |
|
|
441
|
+
| Claude Code | `@anthropic-ai/claude-agent-sdk` |
|
|
442
|
+
| Opencode | `@opencode-ai/sdk` |
|
|
443
|
+
| Codex | `codex` CLI |
|
|
444
|
+
| UI | React 18 (CDN), Babel standalone |
|
|
445
|
+
| Markdown | marked + highlight.js |
|
|
446
|
+
| QR codes | qrcode-terminal |
|
|
447
|
+
|
|
448
|
+
## Development
|
|
449
|
+
|
|
450
|
+
```bash
|
|
451
|
+
# Run in dev mode (no build step)
|
|
452
|
+
npm run dev -- start -p 3000
|
|
453
|
+
|
|
454
|
+
# Build
|
|
455
|
+
npm run build
|
|
456
|
+
|
|
457
|
+
# Run built version
|
|
458
|
+
./dist/index.js start -p 3000
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
The working directory where you run `jarvis start` is treated as the workspace root. Repos are the subdirectories of that workspace. You can run Jarvis from any directory — the hub lets you pick the folder a thread runs in. Bots themselves are stored per-machine, not per-workspace.
|
|
462
|
+
|
|
463
|
+
## Security Considerations
|
|
464
|
+
|
|
465
|
+
> [!IMPORTANT]
|
|
466
|
+
> Jarvis has **no authentication**. Anyone who can reach the Jarvis port on your network can run your bots on your machine, browse your project files, and read file contents. Bots can be given `auto-approve` permission mode, in which case they act without asking you first.
|
|
467
|
+
>
|
|
468
|
+
> Use local mode on trusted networks only. Relay mode exposes the hub beyond your LAN — only use it if you accept that.
|
|
469
|
+
|
|
470
|
+
## Contributing
|
|
471
|
+
|
|
472
|
+
Contributions are welcome. If you want to help:
|
|
473
|
+
|
|
474
|
+
1. Fork the repo
|
|
475
|
+
2. Create a branch (`git checkout -b my-feature`)
|
|
476
|
+
3. Make your changes
|
|
477
|
+
4. Run `npm run build` to verify compilation
|
|
478
|
+
5. Open a PR
|
|
479
|
+
|
|
480
|
+
Please keep changes focused and avoid unnecessary refactoring. If you're unsure whether a change fits, open an issue first.
|
|
481
|
+
|
|
482
|
+
## License
|
|
483
|
+
|
|
484
|
+
MIT — see [LICENSE](LICENSE) for details.
|