@workermill/agent 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/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # @workermill/agent
2
+
3
+ Run WorkerMill AI workers locally using your Claude Max subscription. The agent polls the WorkerMill cloud dashboard for tasks, runs planning via Claude CLI, and spawns Docker worker containers on your machine.
4
+
5
+ ## Prerequisites
6
+
7
+ - **Docker Desktop** — [Install Docker](https://docs.docker.com/get-docker/)
8
+ - **Claude Code CLI** — The setup wizard auto-installs this, or install manually:
9
+ - macOS/Linux/WSL: `curl -fsSL https://claude.ai/install.sh | bash`
10
+ - Windows PowerShell: `irm https://claude.ai/install.ps1 | iex`
11
+ - **Claude Max subscription** — Run `claude` and sign in with your Claude account
12
+ - **Node.js >= 20** — [Install Node.js](https://nodejs.org/)
13
+ - **WorkerMill account** — Sign up at [workermill.com](https://workermill.com)
14
+
15
+ ## Install & Setup
16
+
17
+ ```bash
18
+ npm install -g @workermill/agent
19
+ ```
20
+
21
+ The setup wizard launches automatically after install. It will:
22
+ 1. Check all prerequisites (auto-installs Claude CLI if missing)
23
+ 2. Prompt for your API key (from Settings > Integrations on the dashboard)
24
+ 3. Validate connectivity to the WorkerMill API
25
+ 4. Prompt for your SCM token (GitHub/GitLab/Bitbucket)
26
+ 5. Pull the worker Docker image
27
+ 6. Save configuration to `~/.workermill/config.json`
28
+
29
+ ## Usage
30
+
31
+ ```bash
32
+ # Start the agent (foreground)
33
+ workermill-agent start
34
+
35
+ # Start in background (daemon mode)
36
+ workermill-agent start --detach
37
+
38
+ # Check status
39
+ workermill-agent status
40
+
41
+ # Stop a background agent
42
+ workermill-agent stop
43
+ ```
44
+
45
+ ## How It Works
46
+
47
+ 1. **Agent polls** the cloud API for tasks assigned to your organization
48
+ 2. **Planning runs locally** via Claude CLI (using your Claude Max subscription — no per-token API charges)
49
+ 3. **Worker containers** spawn locally via Docker, executing code changes
50
+ 4. **Logs and status** stream back to the cloud dashboard in real-time
51
+ 5. **PRs are created** on your SCM provider (GitHub/GitLab/Bitbucket)
52
+
53
+ ## Configuration
54
+
55
+ Config is stored at `~/.workermill/config.json` (created by `workermill-agent setup`):
56
+
57
+ | Field | Default | Description |
58
+ |-------|---------|-------------|
59
+ | `apiUrl` | `https://workermill.com` | WorkerMill API URL |
60
+ | `apiKey` | — | Organization API key |
61
+ | `agentId` | `agent-<hostname>` | Unique agent identifier |
62
+ | `maxWorkers` | `2` | Max concurrent worker containers |
63
+ | `workerImage` | `public.ecr.aws/a7k5r0v0/workermill-worker:latest` | Docker image for workers |
64
+
65
+ ## Troubleshooting
66
+
67
+ | Issue | Solution |
68
+ |-------|----------|
69
+ | "No config found" | Run `workermill-agent setup` |
70
+ | Auth failure | Check API key in Settings > Integrations |
71
+ | Docker not found | Install Docker Desktop and ensure it's running |
72
+ | Claude CLI not found | See install instructions above |
73
+ | Image pull fails | Check internet and try `docker pull public.ecr.aws/a7k5r0v0/workermill-worker:latest` |
package/dist/api.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Shared Axios instance for talking to the WorkerMill cloud API.
3
+ * Configured lazily after config is loaded.
4
+ */
5
+ import { type AxiosInstance } from "axios";
6
+ /**
7
+ * Initialize the shared API client.
8
+ */
9
+ export declare function initApi(baseUrl: string, apiKey: string): void;
10
+ /**
11
+ * Get the shared API client. Must call initApi() first.
12
+ */
13
+ export declare const api: AxiosInstance;
package/dist/api.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Shared Axios instance for talking to the WorkerMill cloud API.
3
+ * Configured lazily after config is loaded.
4
+ */
5
+ import axios from "axios";
6
+ let _api = null;
7
+ /**
8
+ * Initialize the shared API client.
9
+ */
10
+ export function initApi(baseUrl, apiKey) {
11
+ _api = axios.create({
12
+ baseURL: baseUrl,
13
+ headers: {
14
+ "Content-Type": "application/json",
15
+ "x-api-key": apiKey,
16
+ },
17
+ timeout: 30_000,
18
+ });
19
+ }
20
+ /**
21
+ * Get the shared API client. Must call initApi() first.
22
+ */
23
+ export const api = new Proxy({}, {
24
+ get(_target, prop) {
25
+ if (!_api)
26
+ throw new Error("API client not initialized. Call initApi() first.");
27
+ return _api[prop];
28
+ },
29
+ });
package/dist/cli.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * WorkerMill Remote Agent CLI
4
+ *
5
+ * Smart default: running `workermill-agent` with no args auto-launches
6
+ * setup if no config exists, or starts the agent if already configured.
7
+ */
8
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * WorkerMill Remote Agent CLI
4
+ *
5
+ * Smart default: running `workermill-agent` with no args auto-launches
6
+ * setup if no config exists, or starts the agent if already configured.
7
+ */
8
+ import { existsSync } from "fs";
9
+ import { Command } from "commander";
10
+ import { setupCommand } from "./commands/setup.js";
11
+ import { startCommand } from "./commands/start.js";
12
+ import { stopCommand } from "./commands/stop.js";
13
+ import { statusCommand } from "./commands/status.js";
14
+ import { logsCommand } from "./commands/logs.js";
15
+ import { pullCommand } from "./commands/pull.js";
16
+ import { getConfigFile } from "./config.js";
17
+ const program = new Command();
18
+ program
19
+ .name("workermill-agent")
20
+ .description("WorkerMill Remote Agent - Run AI workers locally with your Claude Max subscription")
21
+ .version("0.1.0");
22
+ program
23
+ .command("setup")
24
+ .description("Interactive setup wizard - configure API key, validate prerequisites, pull worker image")
25
+ .action(setupCommand);
26
+ program
27
+ .command("start")
28
+ .description("Start the agent, polling the cloud API for tasks")
29
+ .option("--detach", "Run in background (daemon mode)")
30
+ .action(startCommand);
31
+ program
32
+ .command("stop")
33
+ .description("Stop the running agent")
34
+ .action(stopCommand);
35
+ program
36
+ .command("status")
37
+ .description("Show agent status, active containers, and API connectivity")
38
+ .action(statusCommand);
39
+ program
40
+ .command("logs")
41
+ .description("Live tail of agent logs (like tail -f)")
42
+ .option("-n, --lines <count>", "Number of lines to show initially", "50")
43
+ .action(logsCommand);
44
+ program
45
+ .command("pull")
46
+ .description("Pull the latest worker Docker image")
47
+ .action(pullCommand);
48
+ // If no command given, auto-detect: run setup if no config, otherwise start
49
+ if (process.argv.length <= 2) {
50
+ if (existsSync(getConfigFile())) {
51
+ startCommand({ detach: false });
52
+ }
53
+ else {
54
+ setupCommand();
55
+ }
56
+ }
57
+ else {
58
+ program.parse();
59
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Logs Command — Live tail of agent logs.
3
+ *
4
+ * Works like `tail -f ~/.workermill/agent.log`.
5
+ * Shows the last N lines then follows new output.
6
+ */
7
+ export declare function logsCommand(options: {
8
+ lines?: string;
9
+ }): Promise<void>;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Logs Command — Live tail of agent logs.
3
+ *
4
+ * Works like `tail -f ~/.workermill/agent.log`.
5
+ * Shows the last N lines then follows new output.
6
+ */
7
+ import chalk from "chalk";
8
+ import { existsSync, readFileSync, watchFile, statSync, openSync, readSync, closeSync } from "fs";
9
+ import { getLogFile } from "../config.js";
10
+ export async function logsCommand(options) {
11
+ const logFile = getLogFile();
12
+ if (!existsSync(logFile)) {
13
+ console.log(chalk.yellow("No log file found."));
14
+ console.log(chalk.dim(`Expected at: ${logFile}`));
15
+ console.log(chalk.dim("Start the agent with --detach to generate logs."));
16
+ return;
17
+ }
18
+ const tailLines = parseInt(options.lines || "50", 10);
19
+ // Show last N lines
20
+ const content = readFileSync(logFile, "utf-8");
21
+ const lines = content.split("\n");
22
+ const startIdx = Math.max(0, lines.length - tailLines);
23
+ const tail = lines.slice(startIdx).join("\n");
24
+ if (tail.trim()) {
25
+ process.stdout.write(tail);
26
+ if (!tail.endsWith("\n"))
27
+ process.stdout.write("\n");
28
+ }
29
+ console.log(chalk.dim(`── Following ${logFile} (Ctrl+C to stop) ──`));
30
+ // Follow new output
31
+ let lastSize = statSync(logFile).size;
32
+ watchFile(logFile, { interval: 500 }, () => {
33
+ try {
34
+ const currentSize = statSync(logFile).size;
35
+ if (currentSize <= lastSize) {
36
+ lastSize = currentSize;
37
+ return;
38
+ }
39
+ const fd = openSync(logFile, "r");
40
+ const buffer = Buffer.alloc(currentSize - lastSize);
41
+ readSync(fd, buffer, 0, buffer.length, lastSize);
42
+ closeSync(fd);
43
+ process.stdout.write(buffer.toString());
44
+ lastSize = currentSize;
45
+ }
46
+ catch {
47
+ // File may have been rotated
48
+ }
49
+ });
50
+ // Keep process alive
51
+ await new Promise(() => { });
52
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Pull Command — Pull the latest worker Docker image.
3
+ */
4
+ export declare function pullCommand(): Promise<void>;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Pull Command — Pull the latest worker Docker image.
3
+ */
4
+ import chalk from "chalk";
5
+ import { spawnSync } from "child_process";
6
+ import { existsSync } from "fs";
7
+ import { loadConfigFromFile, getConfigFile } from "../config.js";
8
+ export async function pullCommand() {
9
+ let workerImage = "public.ecr.aws/a7k5r0v0/workermill-worker:latest";
10
+ // Use configured image if config exists
11
+ if (existsSync(getConfigFile())) {
12
+ const config = loadConfigFromFile();
13
+ workerImage = config.workerImage || workerImage;
14
+ }
15
+ console.log();
16
+ console.log(chalk.dim(` Pulling worker image: ${workerImage}`));
17
+ console.log(chalk.dim(" This may take a few minutes..."));
18
+ console.log();
19
+ const result = spawnSync("docker", ["pull", workerImage], {
20
+ stdio: "inherit",
21
+ timeout: 600_000,
22
+ });
23
+ console.log();
24
+ if (result.status === 0) {
25
+ console.log(chalk.green(` ✓ Worker image updated`));
26
+ }
27
+ else {
28
+ console.log(chalk.red(" ✗ Failed to pull worker image."));
29
+ if (result.error) {
30
+ console.log(chalk.yellow(` Error: ${result.error.message}`));
31
+ }
32
+ console.log(chalk.yellow(" Is Docker Desktop running?"));
33
+ process.exit(1);
34
+ }
35
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Setup Wizard — Interactive configuration for the WorkerMill Remote Agent.
3
+ *
4
+ * Prerequisites checked/installed:
5
+ * - Docker Desktop (must be installed manually)
6
+ * - Git for Windows (must be installed manually — required by Claude Code on Windows)
7
+ * - Claude CLI → winget on Windows, curl | bash on Linux/macOS/WSL
8
+ * - Claude auth → launches `claude` which prompts for sign-in on first run
9
+ * - Worker image → `docker pull public.ecr.aws/a7k5r0v0/workermill-worker:latest`
10
+ */
11
+ export declare function setupCommand(): Promise<void>;