palmier 0.8.8 → 0.8.9

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.
Files changed (33) hide show
  1. package/README.md +26 -17
  2. package/dist/commands/init.js +6 -11
  3. package/dist/commands/pair.js +3 -0
  4. package/dist/pwa/assets/index-1gs4vwFo.js +120 -0
  5. package/dist/pwa/assets/{index-UaZFu6XL.css → index-DQJHVyP6.css} +1 -1
  6. package/dist/pwa/assets/{web-DYwZE4qa.js → web-BqVsIFtP.js} +1 -1
  7. package/dist/pwa/assets/web-DrSNtZ3i.js +1 -0
  8. package/dist/pwa/assets/{web-nSzKzI8x.js → web-lefgO9YR.js} +1 -1
  9. package/dist/pwa/index.html +2 -2
  10. package/dist/pwa/service-worker.js +1 -1
  11. package/dist/transports/http-transport.js +42 -27
  12. package/dist/types.d.ts +0 -2
  13. package/package.json +1 -1
  14. package/palmier-server/CLAUDE.md +4 -0
  15. package/palmier-server/PRODUCTION.md +1 -1
  16. package/palmier-server/README.md +1 -1
  17. package/palmier-server/pnpm-lock.yaml +12 -0
  18. package/palmier-server/pwa/package.json +1 -0
  19. package/palmier-server/pwa/src/App.css +61 -0
  20. package/palmier-server/pwa/src/components/CapabilityToggles.tsx +1 -1
  21. package/palmier-server/pwa/src/components/ConnectionStatusIcon.tsx +69 -0
  22. package/palmier-server/pwa/src/components/HostMenu.tsx +5 -4
  23. package/palmier-server/pwa/src/constants.ts +1 -1
  24. package/palmier-server/pwa/src/contexts/HostConnectionContext.tsx +156 -66
  25. package/palmier-server/pwa/src/pages/Dashboard.tsx +2 -0
  26. package/palmier-server/pwa/src/pages/PairHost.tsx +9 -9
  27. package/palmier-server/pwa/src/types.ts +3 -1
  28. package/palmier-server/spec.md +21 -19
  29. package/src/commands/init.ts +7 -12
  30. package/src/commands/pair.ts +3 -0
  31. package/src/transports/http-transport.ts +34 -29
  32. package/src/types.ts +0 -2
  33. package/dist/pwa/assets/index-BiAE5qeC.js +0 -120
package/README.md CHANGED
@@ -15,6 +15,18 @@ It runs on your machine as a background daemon and connects to a mobile-friendly
15
15
 
16
16
  1. Install a supported agent CLI — [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [Gemini CLI](https://github.com/google-gemini/gemini-cli), [Codex CLI](https://github.com/openai/codex), [GitHub Copilot](https://github.com/github/gh-copilot), [OpenClaw](https://openclaw.ai/), or [others](https://www.palmier.me/agents).
17
17
  2. Install Palmier:
18
+
19
+ **Linux / macOS:**
20
+ ```bash
21
+ curl -fsSL https://palmier.me/install.sh | bash
22
+ ```
23
+
24
+ **Windows (PowerShell):**
25
+ ```powershell
26
+ irm https://palmier.me/install.ps1 | iex
27
+ ```
28
+
29
+ The one-liner installs Node.js 24+ if needed (via [fnm](https://github.com/Schniz/fnm) on Linux/macOS, winget on Windows), then `palmier` globally. If you already have Node.js 24+ and npm:
18
30
  ```bash
19
31
  npm install -g palmier
20
32
  ```
@@ -61,7 +73,7 @@ Palmier exposes an [MCP](https://modelcontextprotocol.io) server at `http://loca
61
73
  **Available resources:**
62
74
  | Resource | URI | Permission | Description |
63
75
  |----------|-----|------------|-------------|
64
- | Device Notifications | `notifications://device` | Read Notifications | Recent notifications from the user's Android device |
76
+ | Device Notifications | `notifications://device` | Notifications from Other Apps | Recent notifications from the user's Android device |
65
77
  | Device SMS | `sms-messages://device` | Read SMS | Recent SMS messages from the user's Android device |
66
78
 
67
79
  Resources support MCP subscriptions — clients can subscribe via `resources/subscribe` and receive real-time `notifications/resources/updated` events via the streamable HTTP transport when the resource changes.
@@ -92,32 +104,29 @@ All device tools work while the Palmier Android app is in the background — the
92
104
  │ SMS, contacts, │
93
105
  │ calendar, GPS) │
94
106
  └──────────────────┘
95
- Local / LAN: direct HTTP
96
- Server mode: via relay server + FCM
107
+ Local mode (loopback): direct HTTP on the host machine
108
+ Server mode: via relay (events) + auto-LAN direct HTTP for RPC when reachable (native app)
97
109
  ```
98
110
 
99
111
  ## Access Modes
100
112
 
101
- Local always works. Enable LAN and/or Server mode during `palmier init`.
113
+ Two modes — Local always works on the host machine; Server pairs other devices through the cloud relay.
102
114
 
103
- | Mode | Transport | URL | Pairing | Features |
104
- |------|-----------|-----|---------|----------|
105
- | **Local** | HTTP (localhost) | `http://localhost:<port>` | Not required | Full access from the host machine, no internet needed |
106
- | **LAN** | HTTP (direct) | `http://<host-ip>:<port>` | Required | Access from other devices on the local network |
107
- | **Server** | Cloud relay (NATS) | [https://app.palmier.me](https://app.palmier.me) | Required | Push notifications, remote access from anywhere |
115
+ | Mode | URL | Pairing | Notes |
116
+ |------|-----|---------|-------|
117
+ | **Local** | `http://localhost:<port>` | Not required | Loopback only open in a browser on the host machine. No internet needed. |
118
+ | **Server** | [https://app.palmier.me](https://app.palmier.me) | Required | Pair the device with a one-time code. Push notifications, remote access from anywhere. |
108
119
 
109
- **LAN mode** binds the daemon to `0.0.0.0` so the PWA is accessible from other devices on your network. Devices must pair with a pairing code.
110
-
111
- **Server mode** relays communication through the Palmier cloud server (via [NATS](https://nats.io)). All features including push notifications are available. Server mode and LAN mode can be active at the same time.
120
+ **Auto-LAN (native app only).** When the Capacitor Android app is on the same network as the host, it transparently routes RPC over direct LAN HTTP (`http://<host-ip>:<port>/rpc/...`) instead of through the relay lower latency, no protocol change. Events still flow over the relay. Browser PWAs can't do this and stay on the relay.
112
121
 
113
122
  ## Security & Privacy
114
123
 
115
- **Local mode** — all traffic stays on `127.0.0.1`. No data leaves your machine.
116
-
117
- **LAN mode** — traffic stays on your local network. Devices must pair with a one-time pairing code before they can access the host. Unpaired requests are rejected.
124
+ **Local mode** — all traffic stays on `127.0.0.1`. No data leaves your machine. The web UI, `/pair`, and `/events` reject any non-loopback caller; only `/rpc/<method>` (bearer-auth) and `/health` are reachable from the LAN.
118
125
 
119
126
  **Server mode** — communication between your device and host is relayed through the Palmier cloud server over TLS-encrypted NATS connections. The server acts as a passthrough relay only — it does not store, log, or inspect any user data, task content, or agent output. The only data the server persists is a host registration ID used for message routing and Web Push subscription info for delivering notifications. See the [Privacy Policy](https://www.palmier.me/privacy) for full details.
120
127
 
128
+ **Auto-LAN** — direct LAN HTTP requests use the same client token (Bearer auth) generated during pairing. The host validates every `/rpc/*` call regardless of source.
129
+
121
130
  In all modes, client tokens are generated and validated entirely on your host. The Palmier server never sees or stores them.
122
131
 
123
132
  ## Setup Details
@@ -126,7 +135,7 @@ In all modes, client tokens are generated and validated entirely on your host. T
126
135
 
127
136
  Local access (`http://localhost:<port>`) works immediately — no pairing needed.
128
137
 
129
- For LAN or server mode, run `palmier pair` on the host to generate a pairing code. Enter it in the PWA — either at `http://<host-ip>:<port>` (LAN mode) or [https://app.palmier.me](https://app.palmier.me) (server mode).
138
+ For other devices, run `palmier pair` on the host to generate a code, then enter it at [https://app.palmier.me](https://app.palmier.me). Pairing always goes through the relay; auto-LAN kicks in transparently afterward when the device is on the same network.
130
139
 
131
140
  ### Managing Clients
132
141
 
@@ -145,7 +154,7 @@ palmier clients revoke-all
145
154
 
146
155
  The wizard:
147
156
  - Detects installed agent CLIs and caches the result
148
- - Configures access modes (HTTP port, LAN access)
157
+ - Asks for the HTTP port
149
158
  - Shows a summary (including any existing scheduled tasks to recover) and asks for confirmation
150
159
  - Registers with the Palmier server, saves configuration to `~/.config/palmier/host.json`
151
160
  - Installs a background daemon (systemd user service on Linux, LaunchAgent on macOS, Task Scheduler on Windows)
@@ -27,24 +27,20 @@ export async function initCommand() {
27
27
  process.exit(1);
28
28
  }
29
29
  console.log(` Found: ${green(agents.map((a) => a.label).join(", "))}\n`);
30
- const lanAnswer = await ask("Enable LAN access (direct HTTP from local network)? (y/N): ");
31
- const lanEnabled = lanAnswer.trim().toLowerCase() === "y";
32
30
  let httpPort = 7256;
33
- const portLabel = lanEnabled ? "HTTP port for local and LAN access" : "HTTP port for local access";
34
- const portAnswer = await ask(`${portLabel} (default ${httpPort}): `);
31
+ const portAnswer = await ask(`HTTP port (default ${httpPort}): `);
35
32
  const parsed = parseInt(portAnswer.trim(), 10);
36
33
  if (parsed > 0 && parsed < 65536)
37
34
  httpPort = parsed;
35
+ const lanIp = detectLanIp();
38
36
  console.log(`\n${bold("Setup summary:")}\n`);
39
37
  console.log(` ${dim("Task storage:")} ${bold(process.cwd())}`);
40
38
  console.log(` All tasks and execution data will be stored here.\n`);
41
39
  console.log(` ${dim("Local access:")} ${cyan(`http://localhost:${httpPort}`)}`);
42
- console.log(` Always available — no internet required.\n`);
43
- if (lanEnabled) {
44
- const ip = detectLanIp();
45
- console.log(` ${dim("LAN access:")} ${cyan(`http://${ip}:${httpPort}`)}`);
46
- console.log(` Accessible from other devices on your local network. Pairing required.\n`);
47
- }
40
+ console.log(` Open in a browser on this machine — no internet required.\n`);
41
+ console.log(` ${dim("Remote access:")} ${cyan("https://app.palmier.me")}`);
42
+ console.log(` Pair the app to your host. The app uses ${cyan(`http://${lanIp}:${httpPort}`)}`);
43
+ console.log(` for direct RPC when on the same network, otherwise the relay.\n`);
48
44
  console.log(` ${dim("Agents:")} ${agents.map((a) => a.label).join(", ")}\n`);
49
45
  const existingTasks = listTasks(process.cwd());
50
46
  if (existingTasks.length > 0) {
@@ -93,7 +89,6 @@ export async function initCommand() {
93
89
  natsNkeySeed: registerResponse.natsNkeySeed,
94
90
  agents,
95
91
  httpPort,
96
- lanEnabled,
97
92
  };
98
93
  saveConfig(config);
99
94
  console.log(`Config saved to ${dim("~/.config/palmier/host.json")}`);
@@ -4,6 +4,7 @@ import { StringCodec } from "nats";
4
4
  import { loadConfig } from "../config.js";
5
5
  import { connectNats } from "../nats-client.js";
6
6
  import { addClient } from "../client-store.js";
7
+ import { detectLanIp } from "../transports/http-transport.js";
7
8
  const CODE_CHARS = "ABCDEFGHJKMNPQRSTUVWXYZ23456789"; // no O/0/I/1/L
8
9
  const CODE_LENGTH = 6;
9
10
  export const PAIRING_EXPIRY_MS = 60 * 1000; // 1 minute
@@ -14,9 +15,11 @@ export function generatePairingCode() {
14
15
  }
15
16
  function buildPairResponse(config, label) {
16
17
  const client = addClient(label);
18
+ const port = config.httpPort ?? 7256;
17
19
  return {
18
20
  hostId: config.hostId,
19
21
  clientToken: client.token,
22
+ directUrl: `http://${detectLanIp()}:${port}`,
20
23
  hostName: os.hostname(),
21
24
  };
22
25
  }