@agentmessier/restwalker 1.0.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,137 @@
1
+ # restwalker
2
+
3
+ > While you rest, it walks.
4
+
5
+ Idle-time Claude task runner — a Mac background service that queues and runs Claude Code agent tasks during your off-hours, gated by live Claude usage so it never burns your interactive budget.
6
+
7
+ Runs as a LaunchAgent on port **47290** with a SQLite database, a dashboard UI, a REST API (OpenAPI 3.0), and an MCP server for Claude Code.
8
+
9
+ ## How it works
10
+
11
+ 1. You add tasks to the queue (via dashboard, REST API, or MCP tools in Claude Code)
12
+ 2. The gate checks live Claude usage from `api.anthropic.com` — same source as `ccstatusline`
13
+ 3. When usage is low and you're outside your coding window, tasks run automatically
14
+ 4. Sessions are recorded; results, token counts, and transcripts are stored per task
15
+
16
+ ### Budget gates (all configurable)
17
+
18
+ | Gate | Default | Behaviour |
19
+ |---|---|---|
20
+ | Coding window | 4 PM – 2 AM | Always paused during active hours |
21
+ | 5h usage | ≥ 75% | Pause to protect interactive budget |
22
+ | Weekly ceiling | ≥ 65% | Pause background jobs |
23
+ | Weekly hard stop | ≥ 90% | Hard stop regardless |
24
+
25
+ ## Install
26
+
27
+ **Requirements:** macOS, Node.js 20+, Claude Code CLI (must be logged in)
28
+
29
+ ```bash
30
+ git clone https://github.com/agentmessier-ai/restwalker.git
31
+ cd restwalker
32
+ ./install.sh
33
+ ```
34
+
35
+ The installer:
36
+ - Installs Node dependencies
37
+ - Installs and starts the LaunchAgent (auto-restarts on login)
38
+ - Interactively offers to register the MCP server with Claude Code
39
+
40
+ Open `http://localhost:47290` to confirm it's running.
41
+
42
+ ### Custom Node path
43
+
44
+ ```bash
45
+ NODE=/opt/homebrew/bin/node ./install.sh
46
+ ```
47
+
48
+ ## Uninstall
49
+
50
+ ```bash
51
+ ./uninstall.sh
52
+ ```
53
+
54
+ Stops the service, removes the LaunchAgent, and optionally deletes `~/.restwalker/` (DB + logs).
55
+
56
+ ## Dashboard
57
+
58
+ `http://localhost:47290`
59
+
60
+ - Live gate status, 5h and weekly usage, next window
61
+ - 48h trend chart with threshold overlays and coding-window shading
62
+ - Task queue: add, paginate, expand rows to view session transcripts and reasoning blocks
63
+ - Agent providers: configure which CLI runs tasks and with what arguments
64
+ - Settings: all thresholds configurable without restart
65
+
66
+ ## Task queue
67
+
68
+ Tasks have a description (the prompt), an optional working directory, model, provider, and schedule:
69
+
70
+ | Schedule | Behaviour |
71
+ |---|---|
72
+ | `once` | Runs once when the gate opens |
73
+ | `hourly` / `daily` / `weekly` / `monthly` | Automatically re-queues after each run |
74
+
75
+ ## Agent providers
76
+
77
+ The default provider runs `claude --print --permission-mode auto --model {{model}} {{task}}`. You can add any provider with a custom command and args template using `{{task}}`, `{{model}}`, and `{{cwd}}` placeholders.
78
+
79
+ ## MCP server
80
+
81
+ The MCP server (`node/mcp.ts`) exposes 17 tools for Claude Code via stdio transport:
82
+
83
+ | Group | Tools |
84
+ |---|---|
85
+ | Status | `status`, `can_run`, `usage_history`, `sync` |
86
+ | Queue | `queue_stats`, `queue_list`, `queue_get`, `queue_add`, `queue_cancel`, `queue_force_run`, `queue_session` |
87
+ | Providers | `list_providers`, `add_provider`, `set_default_provider` |
88
+ | Discovery | `list_models`, `list_projects` |
89
+ | Settings | `get_settings`, `update_settings` |
90
+
91
+ Register manually if you skipped it during install:
92
+
93
+ ```bash
94
+ claude mcp add --scope user restwalker -- node /path/to/node_modules/.bin/tsx /path/to/node/mcp.ts
95
+ ```
96
+
97
+ ## API
98
+
99
+ Full OpenAPI 3.0 spec and interactive docs at **`http://localhost:47290/docs`**.
100
+
101
+ Key endpoints:
102
+
103
+ | Endpoint | Method | Description |
104
+ |---|---|---|
105
+ | `/queue` | GET | List tasks (paginated) |
106
+ | `/queue` | POST | Add a task |
107
+ | `/queue/:id/force-run` | POST | Force-run bypassing the gate |
108
+ | `/queue/:id/session` | GET | Session transcript with thinking blocks |
109
+ | `/queue/stats` | GET | Counts by status |
110
+ | `/providers` | GET/POST | List or add agent providers |
111
+ | `/models` | GET | Live Anthropic model list |
112
+ | `/projects` | GET | Claude Code projects from history |
113
+ | `/status` | GET | Full daemon state |
114
+ | `/can-run` | GET | Quick gate check |
115
+ | `/settings` | GET/POST | Read or update thresholds |
116
+ | `/healthz` | GET | `{ok: true}` |
117
+
118
+ ## Files
119
+
120
+ | Path | Purpose |
121
+ |---|---|
122
+ | `node/app.ts` | Fastify app, OpenAPI spec, routes, schedule checker |
123
+ | `node/db.ts` | Drizzle ORM repositories (tasks, providers, settings, snapshots) |
124
+ | `node/schema.ts` | Drizzle table definitions — single source of truth |
125
+ | `node/runner.ts` | better-queue worker, provider resolution, gate logic |
126
+ | `node/scheduler.ts` | Keychain read, Anthropic API fetch, time gate, budget logic |
127
+ | `node/session.ts` | Session JSONL parser and analysis |
128
+ | `node/mcp.ts` | MCP server (stdio, 17 tools) |
129
+ | `index.html` | Dashboard UI (no build step) |
130
+ | `install.sh` | One-command installer with interactive MCP registration |
131
+ | `uninstall.sh` | Clean removal |
132
+
133
+ ## Logs
134
+
135
+ ```bash
136
+ tail -f ~/.restwalker/restwalker.log
137
+ ```
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * restwalker CLI — install, start, and manage the idle-time Claude task runner.
4
+ *
5
+ * Usage:
6
+ * npx @agentmessier/restwalker install # install LaunchAgent + register MCP
7
+ * npx @agentmessier/restwalker uninstall # remove LaunchAgent
8
+ * npx @agentmessier/restwalker start # start the daemon in the foreground
9
+ * npx @agentmessier/restwalker status # check if daemon is running
10
+ */
11
+
12
+ import { execFileSync, spawn } from 'child_process'
13
+ import { fileURLToPath } from 'url'
14
+ import { dirname, join } from 'path'
15
+ import { existsSync } from 'fs'
16
+
17
+ const __dirname = dirname(fileURLToPath(import.meta.url))
18
+ const ROOT = join(__dirname, '..')
19
+
20
+ const cmd = process.argv[2]
21
+
22
+ function sh(script, args = []) {
23
+ const full = join(ROOT, script)
24
+ if (!existsSync(full)) {
25
+ console.error(`Script not found: ${full}`)
26
+ process.exit(1)
27
+ }
28
+ execFileSync('bash', [full, ...args], { stdio: 'inherit', cwd: ROOT })
29
+ }
30
+
31
+ switch (cmd) {
32
+ case 'install':
33
+ sh('install.sh', process.argv.slice(3))
34
+ break
35
+
36
+ case 'uninstall':
37
+ sh('uninstall.sh')
38
+ break
39
+
40
+ case 'start': {
41
+ const tsx = join(ROOT, 'node', 'node_modules', '.bin', 'tsx')
42
+ const app = join(ROOT, 'node', 'app.ts')
43
+ if (!existsSync(tsx)) {
44
+ console.error('Dependencies not installed. Run: npx @agentmessier/restwalker install')
45
+ process.exit(1)
46
+ }
47
+ const proc = spawn(process.execPath, [tsx, app], { stdio: 'inherit', cwd: ROOT })
48
+ proc.on('exit', code => process.exit(code ?? 0))
49
+ break
50
+ }
51
+
52
+ case 'status': {
53
+ try {
54
+ const res = await fetch('http://localhost:47290/healthz')
55
+ if (res.ok) {
56
+ const data = await res.json()
57
+ console.log('restwalker is running —', JSON.stringify(data))
58
+ } else {
59
+ console.log('restwalker returned', res.status)
60
+ process.exit(1)
61
+ }
62
+ } catch {
63
+ console.log('restwalker is not running (nothing on port 47290)')
64
+ process.exit(1)
65
+ }
66
+ break
67
+ }
68
+
69
+ default:
70
+ console.log(`
71
+ restwalker — idle-time Claude task runner
72
+
73
+ Usage:
74
+ npx @agentmessier/restwalker install install LaunchAgent + register MCP
75
+ npx @agentmessier/restwalker uninstall remove LaunchAgent
76
+ npx @agentmessier/restwalker start run daemon in foreground
77
+ npx @agentmessier/restwalker status check if daemon is running
78
+
79
+ Dashboard: http://localhost:47290
80
+ `)
81
+ }