palmier 0.9.22 → 0.9.23

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 CHANGED
@@ -6,30 +6,23 @@
6
6
 
7
7
  **Website:** [palmier.me](https://www.palmier.me) | **Web App:** [app.palmier.me](https://app.palmier.me) | **Android App:** [caihongxu/palmier-android](https://github.com/caihongxu/palmier-android)
8
8
 
9
- **Free AI agents, right from your phone.**
9
+ Palmier installs, manages, and runs AI agent CLIs (Claude Code, Gemini CLI, Codex, etc.) on your machine using your existing AI subscriptions, and exposes them to your phone through a mobile-friendly PWA and an Android app. It runs as a background daemon and is agent-agnostic — adding support for a new CLI is a config change, not a code change.
10
10
 
11
- Palmier runs AI agents on your computer using the AI subscriptions you already have, then lets you start or schedule tasks, check progress, and respond to requests from your phone. It also gives your agents access to phone-side capabilities — calendar, contacts, notifications, location, SMS, alarms — so they can react to the real world, not just the terminal.
11
+ The control surface is bidirectional:
12
12
 
13
- Palmier is free, open source, and requires no account or API key. It runs as a background daemon on your machine and pairs with a mobile-friendly PWA or the Android app (iOS coming soon).
13
+ * **Phone host:** start ad-hoc sessions, register schedule- or event-triggered tasks, inspect session output, and respond to agent input/confirmation requests.
14
+ * **Host → phone:** agents can call MCP tools to read device state (location, calendar, contacts, notifications, SMS, battery) and trigger actions (push notifications, full-screen alarms, SMS, email, contact/calendar writes, ringer mode).
14
15
 
15
- ## What Palmier does
16
-
17
- * **Your phone becomes an agent remote** — start, schedule, monitor, and respond to agent tasks without being at your computer. On the same network, the Android app connects over LAN automatically for lower latency.
18
- * **Agent access to your phone data** — give agents access to your phone's location, calendar, contacts, notifications, and SMS. They can also send email on your behalf, send you push notifications, and ask for your input when needed. (Phone capabilities require the Android app.)
19
- * **Free with your existing AI subscriptions** — Palmier installs/detects agent CLIs and invokes them, so Claude Pro, Gemini, ChatGPT Plus, and [more](https://www.palmier.me/agents) just work. No extra account, no extra API key.
20
- * **Task scheduling** — run tasks on a schedule, on demand, or in response to events (e.g. when a push notification arrives), using native OS schedulers (systemd, launchd, Task Scheduler).
21
- * **You stay in control** — agents can only access phone capabilities you enable; approve requests from your phone, or enable yolo mode to auto-approve.
22
- * **Your agents, your machine** — agents run on your hardware, not ours. Your data stays on your machine. No account required.
16
+ Capability access is opt-in per device: each MCP tool is gated behind an Android permission and a per-host toggle. An optional yolo mode auto-approves agent input/confirmation requests.
23
17
 
24
18
  It is not:
25
19
 
26
- * an agent runtime itself
27
- * a system for driving your phone UI like a human tapping through apps
20
+ * an agent runtime itself — Palmier shells out to the agent CLI and streams its stdio
21
+ * a system for driving phone UI like a human tapping through apps — phone access is via OS-level APIs (FCM data messages, content providers, calendar/contacts APIs), not UI automation
28
22
 
29
23
  ## Quick Start
30
24
 
31
- 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).
32
- 2. Install Palmier:
25
+ 1. Install Palmier:
33
26
 
34
27
  **Linux / macOS:**
35
28
  ```bash
@@ -45,19 +38,18 @@ It is not:
45
38
  ```bash
46
39
  npm install -g palmier
47
40
  ```
48
- 3. Run the setup wizard from your Palmier root directory (e.g., `~/palmier`):
41
+ 2. Run the setup wizard from your Palmier root directory (e.g., `~/palmier`):
49
42
  ```bash
50
43
  palmier init
51
44
  ```
52
- This detects your agents, configures access, installs the background daemon, and starts pairing.
53
- 4. Open `http://localhost:7256` to access the app locally — no pairing needed.
54
- 5. To access from other devices, enter the pairing code shown after init into the [PWA](https://app.palmier.me) or the [Android app](https://github.com/caihongxu/palmier-android/releases/latest/download/palmier.apk).
45
+ This detects existing agent CLIs or offers to install supported ones ([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)), configures access, installs the background daemon, and starts pairing.
46
+ 3. Open `http://localhost:7256` to access the app locally — no pairing needed.
47
+ 4. To access from other devices, enter the pairing code shown after init into the [PWA](https://app.palmier.me) or the [Android app](https://github.com/caihongxu/palmier-android/releases/latest/download/palmier.apk).
55
48
 
56
49
  ### Prerequisites
57
50
 
58
51
  - **Node.js 24+**
59
52
  - **Linux with systemd**, **macOS 13+**, or **Windows 10/11**
60
- - At least one supported agent CLI
61
53
 
62
54
  ## How It Works
63
55
 
@@ -220,7 +212,7 @@ The default network interface is detected once during `palmier init` and saved t
220
212
  | `palmier serve` | Run the persistent RPC handler (default command) |
221
213
  | `palmier restart` | Restart the palmier serve daemon |
222
214
  | `palmier run <task-id>` | Execute a specific task |
223
- | `palmier uninstall` | Stop daemon and remove all scheduled tasks |
215
+ | `palmier uninstall` | Stop daemon, remove all scheduled tasks, and uninstall Palmier-managed agent CLIs |
224
216
 
225
217
  ## Uninstalling
226
218
 
@@ -228,12 +220,14 @@ To fully remove Palmier from a machine:
228
220
 
229
221
  1. **Unpair your device** in the PWA (via the host menu).
230
222
 
231
- 2. **Stop the daemon and remove all scheduled tasks:**
223
+ 2. **Stop the daemon, remove all scheduled tasks, and uninstall Palmier-managed agent CLIs:**
232
224
 
233
225
  ```bash
234
226
  palmier uninstall
235
227
  ```
236
228
 
229
+ Agents you installed yourself outside Palmier (no managed version stamp) are left in place.
230
+
237
231
  3. **Uninstall the package:**
238
232
 
239
233
  ```bash
@@ -21,3 +21,8 @@ export declare function pickAndInstallAgent(current: DetectedAgent[], options?:
21
21
  /** Show the uninstall picker. Runs `npm uninstall -g` for the chosen agent
22
22
  * and returns the agent key on success, or null on cancel/failure/no candidates. */
23
23
  export declare function pickAndUninstallAgent(current: DetectedAgent[]): Promise<string | null>;
24
+ /** Uninstall a single agent's npm package. Logs success/failure to stdout.
25
+ * Shared between the `palmier agents` interactive picker and the bulk
26
+ * managed-agent removal in `palmier uninstall`. */
27
+ export declare function uninstallAgent(agent: DetectedAgent): boolean;
28
+ export declare function uninstallManagedAgents(agents: DetectedAgent[]): void;
@@ -10,7 +10,7 @@ export const colors = {
10
10
  red: (s) => `\x1b[31m${s}\x1b[0m`,
11
11
  yellow: (s) => `\x1b[33m${s}\x1b[0m`,
12
12
  };
13
- const { bold, dim, green, cyan, red } = colors;
13
+ const { bold, dim, green, cyan, red, yellow } = colors;
14
14
  export function printInstalledAgents(agents) {
15
15
  if (agents.length === 0) {
16
16
  console.log(` ${dim("(none installed)")}`);
@@ -97,13 +97,23 @@ export async function pickAndUninstallAgent(current) {
97
97
  if (idx === null || idx === 0)
98
98
  return null;
99
99
  const target = uninstallable[idx - 1];
100
- if (!target.npmPackage)
100
+ if (!uninstallAgent(target))
101
101
  return null;
102
- if (!uninstallAgentPackage(target.npmPackage))
103
- return null;
104
- console.log(green(` ${target.label} uninstalled.`));
105
102
  return target.key;
106
103
  }
104
+ /** Uninstall a single agent's npm package. Logs success/failure to stdout.
105
+ * Shared between the `palmier agents` interactive picker and the bulk
106
+ * managed-agent removal in `palmier uninstall`. */
107
+ export function uninstallAgent(agent) {
108
+ if (!agent.npmPackage)
109
+ return false;
110
+ if (!uninstallAgentPackage(agent.npmPackage)) {
111
+ console.log(red(` Skipped ${agent.label}; uninstall it manually with npm uninstall -g ${agent.npmPackage}.`));
112
+ return false;
113
+ }
114
+ console.log(green(` ${agent.label} uninstalled.`));
115
+ return true;
116
+ }
107
117
  function installAgentPackage(agent) {
108
118
  console.log(`\nInstalling ${cyan(agent.npmPackage)}...\n`);
109
119
  const cmd = `npm install -g ${agent.npmPackage}`;
@@ -126,6 +136,28 @@ function installAgentPackage(agent) {
126
136
  }
127
137
  return true;
128
138
  }
139
+ export function uninstallManagedAgents(agents) {
140
+ const managed = agents.filter((a) => a.version && a.npmPackage);
141
+ if (managed.length === 0) {
142
+ console.log(`\n${dim("No Palmier-managed agent CLIs to uninstall.")}`);
143
+ return;
144
+ }
145
+ console.log(`\n${bold(`Uninstalling ${managed.length} Palmier-managed agent ${managed.length === 1 ? "CLI" : "CLIs"}...`)}`);
146
+ let succeeded = 0;
147
+ for (let i = 0; i < managed.length; i++) {
148
+ const agent = managed[i];
149
+ console.log(`\n${dim(`[${i + 1}/${managed.length}]`)} ${agent.label}`);
150
+ if (uninstallAgent(agent))
151
+ succeeded++;
152
+ }
153
+ const failed = managed.length - succeeded;
154
+ if (failed === 0) {
155
+ console.log(`\n${green(`Uninstalled ${succeeded} agent ${succeeded === 1 ? "CLI" : "CLIs"}.`)}`);
156
+ }
157
+ else {
158
+ console.log(`\n${yellow(`Uninstalled ${succeeded} of ${managed.length} agent CLIs (${failed} skipped).`)}`);
159
+ }
160
+ }
129
161
  function uninstallAgentPackage(npmPackage) {
130
162
  console.log(`\nUninstalling ${cyan(npmPackage)}...\n`);
131
163
  const cmd = `npm uninstall -g ${npmPackage}`;
@@ -1,7 +1,20 @@
1
1
  import { getPlatform } from "../platform/index.js";
2
+ import { loadConfig } from "../config.js";
3
+ import { uninstallManagedAgents } from "../agents/wizard.js";
2
4
  export async function uninstallCommand() {
5
+ console.log("Stopping daemon and removing scheduled tasks...");
3
6
  const platform = getPlatform();
4
7
  platform.uninstallDaemon();
5
- console.log("\nTo uninstall the package: npm uninstall -g palmier");
8
+ console.log("Daemon stopped and scheduled tasks removed.");
9
+ let config = null;
10
+ try {
11
+ config = loadConfig();
12
+ }
13
+ catch { /* host not initialized */ }
14
+ if (config?.agents) {
15
+ uninstallManagedAgents(config.agents);
16
+ }
17
+ console.log("\nUninstall finished.");
18
+ console.log("To remove the palmier package itself: npm uninstall -g palmier");
6
19
  console.log("To also remove configuration and task data, see https://github.com/caihongxu/palmier#uninstalling");
7
20
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "palmier",
3
- "version": "0.9.22",
3
+ "version": "0.9.23",
4
4
  "description": "Palmier host CLI - provisions, executes tasks, and serves NATS RPC",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Hongxu Cai",