@gtc6244/immediacy-daemon 0.1.0 → 0.1.1
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/README.md +224 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# @gtc6244/immediacy-daemon
|
|
2
|
+
|
|
3
|
+
> The **Conductor core** for [Immediacy](https://GetImmediacy.com) — a local Mac
|
|
4
|
+
> (or Linux) daemon that owns git worktrees and drives headless Claude Code / Codex
|
|
5
|
+
> coding agents behind a single multiplexed WebSocket protocol.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@gtc6244/immediacy-daemon)
|
|
8
|
+
[](https://nodejs.org)
|
|
9
|
+
|
|
10
|
+
- 🌐 **Landing page:** <https://GetImmediacy.com>
|
|
11
|
+
- 📦 **npm:** <https://www.npmjs.com/package/@gtc6244/immediacy-daemon>
|
|
12
|
+
- 🛠 **Source / issues:** <https://github.com/GTC6244/Immediacy> (this package lives in [`/daemon`](https://github.com/GTC6244/Immediacy/tree/master/daemon))
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Overview
|
|
17
|
+
|
|
18
|
+
Immediacy lets you run parallel Claude Code coding agents on your Mac and drive
|
|
19
|
+
them from anywhere — an Android/iOS phone or tablet, a native macOS app, or a
|
|
20
|
+
browser. **This package is the daemon that makes that possible.**
|
|
21
|
+
|
|
22
|
+
It runs as a lightweight background service on the machine that holds your code.
|
|
23
|
+
Each task gets **one git worktree + one headless agent session**, isolated from
|
|
24
|
+
the others, and every client speaks to the daemon over one WebSocket wire
|
|
25
|
+
protocol. The daemon never opens an inbound port — remote clients reach it
|
|
26
|
+
through a Cloudflare edge that the Mac dials *out* to.
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
Flutter / iOS app ⇄ (WSS) ⇄ Cloudflare edge ⇄ (cloudflared outbound) ⇄ Mac daemon → N × (git worktree + agent)
|
|
30
|
+
macOS app ⇄ (WS, loopback) ─────────────────────────────────────────────┘
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The phone and the Mac **never connect directly**. The phone hits a public
|
|
34
|
+
Cloudflare URL; the Mac only holds an outbound tunnel open. The macOS app and the
|
|
35
|
+
bundled browser client talk to the same daemon over loopback (`ws://127.0.0.1:8787`).
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
- **One worktree + one agent per task.** The daemon forks a fresh `git worktree`
|
|
42
|
+
for every workspace and runs an isolated agent session against it. Deleting a
|
|
43
|
+
workspace removes the worktree — **never** the branch or the underlying repo.
|
|
44
|
+
- **Two agent backends behind one interface:**
|
|
45
|
+
- **Claude** (`claude-opus-4-8`, `claude-fable-5`, `claude-sonnet-5`, …) via the
|
|
46
|
+
Anthropic Agent SDK.
|
|
47
|
+
- **Codex** (`gpt-5-codex`, `gpt-5`, or `Codex (account default)`) via the OpenAI
|
|
48
|
+
`codex` CLI in headless, sandboxed `exec --json` mode.
|
|
49
|
+
- A **mock** backend (`AGENT_MODE=mock`) does real worktree writes and diffs with
|
|
50
|
+
no API credits — ideal for testing.
|
|
51
|
+
- **Permission gating by default.** Every tool call is deferred to the client
|
|
52
|
+
(`event.permission_request` → `permission.respond`) and **default-denies on
|
|
53
|
+
timeout**. The daemon never runs `--dangerously-skip-permissions`; Codex runs
|
|
54
|
+
sandboxed (`-s workspace-write`, `approval_policy=never`) so edits stay inside
|
|
55
|
+
the worktree.
|
|
56
|
+
- **Live streaming.** Assistant messages, session events, tool-use events, git
|
|
57
|
+
diffs (`diff.get`), and a real PTY terminal (`node-pty`) all stream over the
|
|
58
|
+
socket.
|
|
59
|
+
- **End-to-end crypto + multi-device pairing.** An optional NaCl box layer (`E2E=1`)
|
|
60
|
+
seals each socket to that device's own key, so a phone, tablet, and desktop pair
|
|
61
|
+
independently. Pairing is trust-on-first-use behind Cloudflare Access, via a QR
|
|
62
|
+
code — no shared secret beyond the Access token.
|
|
63
|
+
- **GitHub integration without leaking tokens.** Workspace creation can pick from
|
|
64
|
+
your GitHub repos using the `gh` CLI already authenticated on the Mac — the
|
|
65
|
+
token never touches the phone, the wire, or this source.
|
|
66
|
+
- **Bundled browser client.** The daemon's HTTP server serves a dependency-free
|
|
67
|
+
web UI on the same port `cloudflared` dials, so the Access login cookie authorizes
|
|
68
|
+
the same-origin WebSocket.
|
|
69
|
+
- **One CLI, every target.** Run in the foreground or install as a supervised
|
|
70
|
+
service — **launchd** on macOS, **systemd** (`--user`) on Linux. Native deps ship
|
|
71
|
+
prebuilds for macOS + Linux (glibc, arm64/x64), so no compiler toolchain is needed.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Install
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npm i -g @gtc6244/immediacy-daemon # public package — no auth needed
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Requires **Node.js ≥ 20**, plus `git` and (for GitHub integration) the `gh` CLI on
|
|
82
|
+
`PATH`. On **musl/Alpine** there are no native prebuilds — use Docker (see below).
|
|
83
|
+
|
|
84
|
+
### Run it
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
immediacy-daemon doctor # verify node / git / gh are present
|
|
88
|
+
immediacy-daemon install # write + start the background service
|
|
89
|
+
immediacy-daemon status # service state + /healthz probe
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Or run it in the foreground (Docker, ad-hoc):
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
immediacy-daemon start
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### CLI commands
|
|
99
|
+
|
|
100
|
+
| Command | What it does |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `start` | Run the daemon in the foreground (Ctrl-C to stop). |
|
|
103
|
+
| `install [--print]` | Install + start the supervised service (launchd/systemd). `--print` renders the unit without installing. |
|
|
104
|
+
| `uninstall` | Stop and remove the service. |
|
|
105
|
+
| `restart` | Restart the running service. |
|
|
106
|
+
| `status` | Show service state and probe `http://127.0.0.1:<port>/healthz`. |
|
|
107
|
+
| `logs [-f]` | Print (or `-f` to tail) the daemon's stdout/stderr logs. |
|
|
108
|
+
| `doctor` | Check `node`/`git`/`gh` on `PATH` and whether the daemon responds. |
|
|
109
|
+
| `help` / `version` | Show help or version. |
|
|
110
|
+
|
|
111
|
+
Options (also read from the environment):
|
|
112
|
+
|
|
113
|
+
| Flag | Env | Default | Meaning |
|
|
114
|
+
|---|---|---|---|
|
|
115
|
+
| `--port <n>` | `DAEMON_PORT` | `8787` | Local port to bind (the port `cloudflared` dials). |
|
|
116
|
+
| `--host <addr>` | `DAEMON_HOST` | `127.0.0.1` | Bind address (`0.0.0.0` to expose on a LAN/emulator). |
|
|
117
|
+
| `--agent-mode <m>` | `AGENT_MODE` | `claude` | `claude` \| `mock`. |
|
|
118
|
+
| `--e2e` | `E2E=1` | off | Enable the NaCl box E2E layer (needs a paired peer). |
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Cloudflare connection
|
|
123
|
+
|
|
124
|
+
Remote clients never talk to your Mac directly. `cloudflared` dials **out** from the
|
|
125
|
+
Mac to the Cloudflare edge and holds the connection open, so **there's no inbound
|
|
126
|
+
port, no port forwarding, and no VPN.** The daemon just binds a local WebSocket on
|
|
127
|
+
`127.0.0.1:8787`; Cloudflare Access does authentication/authorization at the edge.
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
app ⇄ (WSS, public URL) ⇄ Cloudflare edge ⇄ (cloudflared outbound) ⇄ Mac daemon (ws://127.0.0.1:8787)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
End state: the daemon is reachable at `wss://your-subdomain.your-domain`, gated by
|
|
134
|
+
Cloudflare Access, with a service token the app presents. The optional NaCl box
|
|
135
|
+
codec (`E2E=1`) keeps the message `payload` private even from the edge.
|
|
136
|
+
|
|
137
|
+
**Quick setup:**
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
brew install cloudflared
|
|
141
|
+
cloudflared tunnel login # pick your Cloudflare domain
|
|
142
|
+
cloudflared tunnel create immediacy # prints a tunnel UUID + creds path
|
|
143
|
+
cloudflared tunnel route dns immediacy conductor.example.com
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`~/.cloudflared/config.yml`:
|
|
147
|
+
|
|
148
|
+
```yaml
|
|
149
|
+
tunnel: immediacy
|
|
150
|
+
credentials-file: /Users/YOU/.cloudflared/<UUID>.json
|
|
151
|
+
ingress:
|
|
152
|
+
- hostname: conductor.example.com
|
|
153
|
+
service: ws://localhost:8787 # WebSockets are on by default
|
|
154
|
+
- service: http_status:404 # required catch-all
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Full walkthrough — tunnel + Access + service tokens:
|
|
158
|
+
[`docs/cloudflare-setup.md`](https://github.com/GTC6244/Immediacy/blob/master/docs/cloudflare-setup.md).
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Configuration & secrets
|
|
163
|
+
|
|
164
|
+
The daemon reads config from flags/environment and from `~/.immediacy/`:
|
|
165
|
+
|
|
166
|
+
| What | Where | Notes |
|
|
167
|
+
|---|---|---|
|
|
168
|
+
| Port / host / agent mode | `--port` / `--host` / `--agent-mode`, or `DAEMON_PORT` / `DAEMON_HOST` / `AGENT_MODE` | Baked into the service unit at install time. |
|
|
169
|
+
| E2E crypto | `--e2e` / `E2E=1` | NaCl box layer; needs a paired peer. |
|
|
170
|
+
| Provider API keys | `~/.immediacy/credentials.json` (0600), or `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `OPENROUTER_API_KEY` | Stored key wins over env. Anthropic/OpenAI fall back to a cached CLI/SSO login if unset. |
|
|
171
|
+
| NaCl keypair / paired peers | `~/.immediacy/keys.json`, `peers.json` | Auto-created on first run. |
|
|
172
|
+
|
|
173
|
+
> The npm package is **public**, so its source is world-readable. **Runtime secrets
|
|
174
|
+
> are never in the package** — they live in `~/.immediacy/` on each host. Never
|
|
175
|
+
> commit or bundle API keys, and don't bake them into a Docker image.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Docker (Linux fleet / Alpine)
|
|
180
|
+
|
|
181
|
+
For reproducible VPS fleets or musl/Alpine (no native prebuilds), a container is
|
|
182
|
+
cleaner than global npm — run the daemon in the foreground:
|
|
183
|
+
|
|
184
|
+
```dockerfile
|
|
185
|
+
FROM node:20-bookworm-slim
|
|
186
|
+
RUN apt-get update && apt-get install -y --no-install-recommends git ca-certificates \
|
|
187
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
188
|
+
RUN npm i -g @gtc6244/immediacy-daemon
|
|
189
|
+
EXPOSE 8787
|
|
190
|
+
# Mount ~/.immediacy for persistent keys/credentials; pass keys via env or the mount.
|
|
191
|
+
CMD ["immediacy-daemon", "start", "--host", "0.0.0.0"]
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Keep Macs on native launchd (real PTYs, local filesystem access) rather than Docker.
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Day-2 operations
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
immediacy-daemon status # is it up? is /healthz responding?
|
|
202
|
+
immediacy-daemon logs -f # tail stdout/err
|
|
203
|
+
immediacy-daemon restart # restart the service
|
|
204
|
+
immediacy-daemon uninstall # stop + remove the service
|
|
205
|
+
|
|
206
|
+
npm i -g @gtc6244/immediacy-daemon@latest # update to the latest published version
|
|
207
|
+
immediacy-daemon restart
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Logs: `~/Library/Logs/immediacy-daemon.{out,err}.log` (macOS) or
|
|
211
|
+
`~/.immediacy/daemon.{out,err}.log` (Linux).
|
|
212
|
+
|
|
213
|
+
Full deploy & publish guide:
|
|
214
|
+
[`daemon/DEPLOY.md`](https://github.com/GTC6244/Immediacy/blob/master/daemon/DEPLOY.md).
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Links
|
|
219
|
+
|
|
220
|
+
- **Landing page:** <https://GetImmediacy.com>
|
|
221
|
+
- **GitHub repo:** <https://github.com/GTC6244/Immediacy>
|
|
222
|
+
- **npm package:** <https://www.npmjs.com/package/@gtc6244/immediacy-daemon>
|
|
223
|
+
- **Architecture reference:** [`docs/ARCHITECTURE.md`](https://github.com/GTC6244/Immediacy/blob/master/docs/ARCHITECTURE.md)
|
|
224
|
+
- **Cloudflare setup:** [`docs/cloudflare-setup.md`](https://github.com/GTC6244/Immediacy/blob/master/docs/cloudflare-setup.md)
|
package/package.json
CHANGED