kombinat 0.0.0-stage → 0.2.2

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
@@ -1,3 +1,218 @@
1
- # Temporary Holding Version
1
+ <img src=".github/assets/banner.png" alt="Kombinat: routines in your repo, run by AI agents 24/7" width="100%" />
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Background AI agents that run routines defined in your repository, 24/7. They run on your machine under launchd with Claude Code, Codex or any other CLI agent, using your normal subscription login.
4
+
5
+ Ready to use in your organisation or at home.
6
+
7
+ 1. **Version-controlled by design.** Merge a `.md` file and the change is picked up automatically.
8
+ 2. **Minimal and lightweight.** Run one command on a machine that is on 24/7. Easy for non-engineers to contribute to.
9
+ 3. **Your own integrations.** Agents use your local environment as is, including skills, MCP, browser control and more.
10
+ 4. **Cheap.** Works with your existing Claude or Codex subscription. Don't burn your money on tokens.
11
+ 5. **Remote control.** Debug and monitor your remote machine from your mobile on your commute.
12
+ 6. **Webhooks.** Linear, GitHub or any other app can start a routine with a request, and the agent gets its body.
13
+ 7. **Battle-tested.** Polished on real use cases across engineering, design, product management and GTM.
14
+
15
+ **Ideas:**
16
+
17
+ 1. **Post-release monitoring.** Checks Intercom, Sentry, Grafana and the logs for problems in code shipped over the last 3 days, raises an alert and opens PRs with fixes.
18
+ 2. **On-call engineer.** Investigates production incidents and opens PRs to fix them.
19
+ 3. **Flaky E2E test fixer.**
20
+ 4. **Dead code and feature flag clean-up.**
21
+ 5. **Picking up bug fixes.**
22
+ 6. **Monitoring support chats for product signals.**
23
+ 7. **Delegating tasks to an agent from your task manager.**
24
+
25
+ **Quickstart:**
26
+
27
+ 1. Add Kombinat to the repository that will hold your routines.
28
+
29
+ ```bash
30
+ pnpm add kombinat # with npm: npm install kombinat
31
+ ```
32
+
33
+ 2. Add your routines as `.md` files in a `routines/` folder next to `package.json`, see [Writing a routine](#writing-a-routine). Changes are picked up on the next check, no restart needed. Agents run with your usual setup, so your global skills, MCP servers and `CLAUDE.md` are picked up.
34
+
35
+ ```
36
+ my-routines-or-project/
37
+ ├── routines/
38
+ │ └── fix-e2e-tests.md
39
+ └── package.json
40
+ ```
41
+
42
+ 3. Start from that folder.
43
+
44
+ ```bash
45
+ pnpm kombinat serve # or: npx kombinat serve
46
+ ```
47
+
48
+ It runs in this terminal. To keep it running in the background and after reboots, stop it and run `pnpm kombinat install` instead, see [Setup](#setup).
49
+
50
+ 4. Monitor and debug runs in the dashboard at http://localhost:7433, or in the terminal with `pnpm kombinat tui`, which also works over ssh. See [Monitoring](#monitoring). To open them from another machine, see [Remote access](#remote-access).
51
+
52
+ ## Monitoring
53
+
54
+ <img src=".github/assets/dashboard.png" alt="Kombinat dashboard: routines list, week calendar and a run transcript" width="100%" />
55
+
56
+ The daemon serves a dashboard at http://localhost:7433.
57
+
58
+ - **Routines.**
59
+ - **Calendar.**
60
+ - **Runs.**
61
+ - **Daemon status.**
62
+
63
+ ### In the terminal
64
+
65
+ <img src=".github/assets/tui.png" alt="Kombinat in the terminal: routines, recent runs and a routine's run history" width="100%" />
66
+
67
+ `pnpm kombinat tui` shows the same in the terminal. It works over ssh. Press `?` for keys.
68
+
69
+ ## Remote access
70
+
71
+ ### Over SSH
72
+
73
+ Turn on Remote Login on the Mac that runs Kombinat, in System Settings → General → Sharing. Then, on your laptop:
74
+
75
+ ```bash
76
+ npx kombinat connect admin@mac-mini # dashboard in the browser
77
+ npx kombinat connect admin@mac-mini --tui # dashboard in the terminal
78
+ ```
79
+
80
+ It opens an SSH tunnel to the daemon, then the dashboard. SSH asks for the password if you have no key set up. Ctrl-C disconnects. Instead of `admin@mac-mini`, use anything `ssh` accepts: a host from `~/.ssh/config`, an IP address or a Tailscale machine name. If the daemon there uses another `KOMBINAT_PORT`, add `--port`.
81
+
82
+ You can also ssh in and run `pnpm kombinat tui` in the folder Kombinat runs in.
83
+
84
+ ### With Tailscale Serve
85
+
86
+ To open the dashboard from any device in your tailnet, your phone included, run this on the Mac that runs Kombinat:
87
+
88
+ ```bash
89
+ tailscale serve --bg 7433
90
+ ```
91
+
92
+ The dashboard is then at `https://mac-mini.<your-tailnet>.ts.net`, and `npx kombinat tui --url https://mac-mini.<your-tailnet>.ts.net` shows it in the terminal. Serve needs HTTPS certificates in your tailnet, the command asks to turn them on. They put the machine name in public certificate logs. It stays on after a reboot, `tailscale serve --https=443 off` turns it off. If the Mac has no `tailscale` command, see [Using the Tailscale CLI](https://tailscale.com/kb/1080/cli).
93
+
94
+ Everyone who can reach the Mac in your tailnet can then read transcripts and start routines. To limit that, allow only some people to reach port 443 of the Mac in your [Tailscale access rules](https://tailscale.com/kb/1018/acls).
95
+
96
+ ## Routines
97
+
98
+ The example routines of this repository, one row per file in [`routines/`](routines/). Put the same `routines:start` and `routines:end` comments in your own README, and `pnpm kombinat readme` keeps a table like this one up to date.
99
+
100
+ <!-- prettier-ignore-start -->
101
+ <!-- routines:start -->
102
+ | Routine | When | What it does |
103
+ | - | - | - |
104
+ | [weather-example-routine](routines/weather-example-routine.md) | Weekdays at 08:00 | Says if you need an umbrella today |
105
+ | [weather-webhook-example-routine](routines/weather-webhook-example-routine.md) | On webhook | Says if you need an umbrella in the city from the request |
106
+ <!-- routines:end -->
107
+ <!-- prettier-ignore-end -->
108
+
109
+ ## How it works
110
+
111
+ - Each routine is a markdown file. The frontmatter sets the schedule and settings, the body is the prompt.
112
+ - A small daemon checks every 30 seconds which routines are due and starts their agent. It also serves a dashboard at http://localhost:7433.
113
+ - launchd keeps the daemon running and starts it again after a reboot. Runs only happen while the Mac is awake and you are logged in.
114
+ - Logs and run history are stored in `~/.kombinat/`.
115
+ - Claude and Codex use your subscription login. API key variables are removed from their environment.
116
+
117
+ ## Setup
118
+
119
+ You need Node 24 and the agents your routines use, logged in: Claude Code (`claude auth status`) and Codex (`codex login`). From the folder with `routines/` and `package.json`:
120
+
121
+ ```bash
122
+ pnpm add kombinat
123
+ pnpm kombinat install
124
+ ```
125
+
126
+ This starts the daemon under launchd, in that folder. Open http://localhost:7433. There is one daemon per macOS user, so running `install` in another folder moves it there.
127
+
128
+ ## Commands
129
+
130
+ Run them from the same folder. With npm, use `npx kombinat` instead of `pnpm kombinat`, with Yarn `yarn kombinat`.
131
+
132
+ ```bash
133
+ pnpm kombinat list # routines, next run, last status
134
+ pnpm kombinat run <name> # run a routine now, in the foreground
135
+ pnpm kombinat validate # check all routine files
136
+ pnpm kombinat tui # dashboard in the terminal, works over ssh
137
+ pnpm kombinat status # daemon and scheduler state
138
+ pnpm kombinat readme # update the routines table in README.md
139
+ pnpm kombinat uninstall # stop and remove the daemon
140
+ ```
141
+
142
+ ## Writing a routine
143
+
144
+ ```markdown
145
+ ---
146
+ name: fix-e2e-tests
147
+ description: Finds the failing e2e test and fixes it
148
+ schedule: '30 11 * * *'
149
+ cwd: ~/projects/app
150
+ agent: claude
151
+ model: claude-opus-5-5
152
+ effort: high
153
+ timeoutMinutes: 55
154
+ ---
155
+
156
+ 1. Open the latest failed e2e run on GitHub ...
157
+ ```
158
+
159
+ - `name` must match the file name.
160
+ - `schedule` is a 5-field cron in local time, or `manual` to run only on demand.
161
+ - `cwd` is where the agent starts.
162
+ - `agent` is `claude` (default), `codex` or `command`.
163
+ - `timeoutMinutes` stops the run after this time. Default 55.
164
+ - `before` is an optional shell command that runs first. If it fails or takes more than 3 minutes, the run fails.
165
+ - `enabled: false` keeps the file but stops the schedule.
166
+ - `webhook: true` lets other apps start the routine with a request, see [docs/webhook.md](docs/webhook.md).
167
+
168
+ Changes apply on the next check, no restart needed. Write the prompt so the agent never has to ask a question: nobody will answer.
169
+
170
+ ### Agents
171
+
172
+ | Setting | `claude` | `codex` | `command` |
173
+ | ---------------- | --------------------------------------------------------------------------------- | -------------------------------------------------------------- | --------- |
174
+ | `model` | default `claude-opus-5-5` | default from your Codex config | - |
175
+ | `effort` | `low`, `medium`, `high` (default), `xhigh`, `max` | `minimal`, `low`, `medium`, `high`, `xhigh` | - |
176
+ | `permissionMode` | `auto` (default), `acceptEdits`, `dontAsk`, `bypassPermissions`, `plan`, `manual` | `read-only`, `workspace-write` (default), `danger-full-access` | - |
177
+ | `maxBudgetUsd` | optional | - | - |
178
+ | `command` | - | - | required |
179
+
180
+ - `claude` runs `claude -p`. Anything that needs approval is denied.
181
+ - `codex` runs `codex exec`. `permissionMode` sets its sandbox.
182
+ - `command` runs any other CLI, for example `command: gemini --yolo`. It gets the prompt on stdin, and its output is the result.
183
+
184
+ A setting the agent does not support fails validation.
185
+
186
+ ## Scheduling
187
+
188
+ - If the Mac was asleep, each routine runs once for its latest missed time, up to 7 days back.
189
+ - A routine never runs twice at the same time. If it is still running at its next time, that run is skipped.
190
+ - At most 3 routines run at once.
191
+
192
+ ## Webhooks
193
+
194
+ A routine with `webhook: true` also runs when another app, such as Linear or GitHub, sends it a request. The request body goes into the prompt, an optional `webhookGate` command checks and filters requests, and requests that arrive while the routine runs wait in a queue. See [docs/webhook.md](docs/webhook.md).
195
+
196
+ ## Updating
197
+
198
+ The daemon runs `git pull` in the folder every 5 minutes, so merged changes go live on their own. It only pulls when the checkout is on `main` with no local changes.
199
+
200
+ To update Kombinat, bump `kombinat` in `package.json`, for example with a Renovate or Dependabot PR. When the lockfile changes, the daemon installs dependencies with pnpm, npm or Yarn and restarts. Running routines are not interrupted.
201
+
202
+ Up to 0.2.2, Kombinat was published as `@danilqa/kombinat`. To move to `kombinat`, replace the dependency in `package.json`, install it and run `pnpm kombinat install` again. Until then the launchd job of the daemon points into the old package folder, which the install removes, so the daemon does not pick up the new version or start again after a reboot.
203
+
204
+ ## Configuration
205
+
206
+ | Variable | Default | What |
207
+ | ------------------------- | --------------------- | -------------------------------------- |
208
+ | `KOMBINAT_PORT` | `7433` | dashboard port |
209
+ | `KOMBINAT_STATE_DIR` | `~/.kombinat` | logs and history |
210
+ | `KOMBINAT_ROUTINES_DIR` | `./routines` | routine files |
211
+ | `KOMBINAT_MAX_CONCURRENT` | `3` | routines that can run at once |
212
+ | `KOMBINAT_TICK_SECONDS` | `30` | how often the daemon checks routines |
213
+ | `KOMBINAT_PULL_MINUTES` | `5` | auto `git pull` interval, 0 to disable |
214
+ | `KOMBINAT_PULL_BRANCH` | `main` | branch the daemon pulls |
215
+ | `CLAUDE_BIN` | `~/.local/bin/claude` | Claude Code binary |
216
+ | `CODEX_BIN` | `codex` | Codex binary |
217
+
218
+ Set them before `pnpm kombinat install`. They are saved in the launchd config.
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ // A checkout runs the sources with tsx, the npm package ships dist/cli.js.
3
+ import fs from 'node:fs';
4
+
5
+ const source = new URL('../src/cli.ts', import.meta.url);
6
+
7
+ if (fs.existsSync(source)) {
8
+ await import('tsx');
9
+ await import(source.href);
10
+ } else {
11
+ await import('../dist/cli.js');
12
+ }