loop-task 1.3.0 → 1.4.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.
Files changed (43) hide show
  1. package/README.md +250 -195
  2. package/dist/board/App.js +225 -87
  3. package/dist/board/components/ActionButtons.js +28 -8
  4. package/dist/board/components/CreateForm.js +224 -70
  5. package/dist/board/components/CreateProjectModal.js +104 -0
  6. package/dist/board/components/DeleteProjectConfirm.js +53 -0
  7. package/dist/board/components/EditProjectModal.js +106 -0
  8. package/dist/board/components/FilterBar.js +5 -4
  9. package/dist/board/components/Footer.js +19 -6
  10. package/dist/board/components/Header.js +33 -3
  11. package/dist/board/components/HelpModal.js +11 -10
  12. package/dist/board/components/Inspector.js +1 -1
  13. package/dist/board/components/LogModal.js +39 -8
  14. package/dist/board/components/Navigator.js +30 -14
  15. package/dist/board/components/ProjectsModal.js +70 -0
  16. package/dist/board/components/ProjectsPage.js +105 -0
  17. package/dist/board/components/RunHistory.js +48 -9
  18. package/dist/board/components/TaskBrowser.js +95 -0
  19. package/dist/board/components/TaskFilterBar.js +6 -0
  20. package/dist/board/components/TaskForm.js +177 -0
  21. package/dist/board/daemon.js +56 -0
  22. package/dist/board/format.js +19 -12
  23. package/dist/board/hooks/useBoardKeybindings.js +264 -156
  24. package/dist/board/hooks/useTaskKeybindings.js +114 -0
  25. package/dist/board/router.js +16 -0
  26. package/dist/board/state.js +18 -14
  27. package/dist/cli.js +61 -6
  28. package/dist/client/commands.js +157 -1
  29. package/dist/config/constants.js +15 -0
  30. package/dist/config/paths.js +6 -0
  31. package/dist/core/command-runner.js +2 -0
  32. package/dist/core/foreground-loop.js +4 -1
  33. package/dist/core/loop-controller.js +210 -32
  34. package/dist/daemon/index.js +5 -2
  35. package/dist/daemon/manager.js +113 -34
  36. package/dist/daemon/projects.js +104 -0
  37. package/dist/daemon/server.js +177 -6
  38. package/dist/daemon/state.js +32 -1
  39. package/dist/daemon/task-manager.js +59 -0
  40. package/dist/i18n/en.json +139 -20
  41. package/dist/loop-config.js +13 -4
  42. package/dist/shared/clipboard.js +19 -0
  43. package/package.json +1 -1
package/README.md CHANGED
@@ -1,195 +1,250 @@
1
- <div align="center">
2
-
3
- # loop-task
4
-
5
- **Run commands on repeat. Manage them from a terminal board.**
6
-
7
- `loop-task` is a cross-platform CLI that runs shell commands at human-readable intervals. Create loops in the background, manage them from an interactive TUI board, or run them in the foreground.
8
-
9
- [![npm version](https://img.shields.io/npm/v/loop-task?style=flat-square&color=black)](https://www.npmjs.com/package/loop-task)
10
- [![npm downloads](https://img.shields.io/npm/dm/loop-task?style=flat-square&color=black)](https://www.npmjs.com/package/loop-task)
11
- [![license](https://img.shields.io/npm/l/loop-task?style=flat-square&color=black)](./LICENSE)
12
- [![node](https://img.shields.io/node/v/loop-task?style=flat-square&color=black)](https://nodejs.org)
13
-
14
- </div>
15
-
16
- ## Quick start
17
-
18
- ```bash
19
- npm install -g loop-task
20
- loop-task # open the board (requires Bun)
21
- loop-task start # start the daemon, restore persisted loops
22
- loop-task new 30m -- npm test # create a background loop
23
- loop-task run --now 10s -- echo hi # run a loop in the foreground
24
- ```
25
-
26
- Or run it directly:
27
-
28
- ```bash
29
- npx loop-task
30
- npx loop-task new 30m -- npm test
31
- ```
32
-
33
- ## Requirements
34
-
35
- - **Node.js >= 20** — required for all commands
36
- - **Bun >= 1.2** — required for the interactive board only
37
-
38
- Install Bun:
39
-
40
- ```bash
41
- npm install -g bun
42
- ```
43
-
44
- `start`, `new`, and `run` work with Node alone. The board auto-delegates to Bun when needed.
45
-
46
- ## Commands
47
-
48
- | Command | Description |
49
- | ------- | ----------- |
50
- | `loop-task` | Open the interactive board (requires Bun) |
51
- | `loop-task start` | Start the background daemon, restore persisted loops |
52
- | `loop-task new <interval> -- <command>` | Create a background loop |
53
- | `loop-task run <interval> -- <command>` | Run a loop in the foreground |
54
-
55
- ### Options (for `new` and `run`)
56
-
57
- | Option | Description |
58
- | ------ | ----------- |
59
- | `--now` | Run immediately before waiting |
60
- | `--max-runs <n>` | Stop after N executions |
61
- | `--cwd <dir>` | Working directory for the command |
62
- | `--verbose` | Show execution details |
63
- | `-h, --help` | Display help |
64
- | `-V, --version` | Display version |
65
-
66
- ## Examples
67
-
68
- ```bash
69
- # Run tests every 30 minutes
70
- loop-task new 30m -- npm test
71
-
72
- # Run immediately, then every hour
73
- loop-task new --now 1h -- npm test
74
-
75
- # Run up to 5 times, then stop
76
- loop-task run --max-runs 5 5m -- npm test
77
-
78
- # Agent workflow schedule an AI task every 30 minutes
79
- loop-task new 30m --now -- opencode run "find and fix lint issues"
80
-
81
- # Run in a specific directory
82
- loop-task new 30m --cwd ./packages/api -- npm test
83
-
84
- # Verbose mode
85
- loop-task run --verbose 30m -- npm test
86
- ```
87
-
88
- When the command has its own flags, use `--` to stop argument parsing:
89
-
90
- ```bash
91
- loop-task new 30m -- node -e "console.log('hello')"
92
- ```
93
-
94
- ## The board
95
-
96
- The board is the primary way to manage loops. It shows all loops, their status, run history, and logs in a single terminal interface.
97
-
98
- ### Board controls
99
-
100
- ```
101
- ↑/↓, j/k move selection
102
- Enter edit selected loop
103
- n create a new loop
104
- p pause / resume selected loop
105
- r force run selected loop now
106
- del delete selected loop
107
- / search loops
108
- f cycle status filter
109
- s cycle sort mode
110
- ←/→ switch between panels
111
- h toggle help
112
- Esc quit
113
- ```
114
-
115
- Destructive actions (pause, force run, delete) prompt a confirmation before executing.
116
-
117
- ### Loop fields
118
-
119
- When creating or editing a loop:
120
-
121
- | Field | Description |
122
- | ----- | ----------- |
123
- | **Interval** | How often to run (`30s`, `5m`, `1h`, `1d`, `1w`) |
124
- | **Command** | The full command line |
125
- | **Description** | Optional label shown in the list; defaults to the command |
126
- | **Working dir** | Directory the command runs in; defaults to current directory |
127
- | **Run immediately?** | Run once now, then every interval, or wait the first interval |
128
- | **Max runs** | Stop after N runs, or leave blank to run forever |
129
-
130
- ## How it works
131
-
132
- ```
133
- loop-task (board) ──IPC──► daemon ──► loop 1 (background process)
134
- ├──► loop 2
135
- └──► loop 3
136
- ```
137
-
138
- - The **daemon** is a background process that manages all loops. It starts automatically when you run `loop-task start` or any command that needs it.
139
- - The **board** is a terminal UI that connects to the daemon via IPC.
140
- - Loops **persist to disk** they survive daemon restarts and system reboots. When the daemon starts, it restores all loops and accounts for elapsed time.
141
-
142
- ### Lifecycle
143
-
144
- 1. `loop-task start` or `loop-task new ...` spawns the daemon if not running
145
- 2. The daemon creates a loop and persists its state to disk
146
- 3. `loop-task` opens the board for interactive management
147
- 4. Closing the board or terminal does **not** stop loops — the daemon keeps running
148
- 5. After a reboot, `loop-task start` restores all persisted loops with correct timing
149
-
150
- ## Supported intervals
151
-
152
- | Format | Description |
153
- | ------ | ----------- |
154
- | `10s` | 10 seconds |
155
- | `5m` | 5 minutes |
156
- | `1h` | 1 hour |
157
- | `1d` | 1 day |
158
- | `1w` | 1 week |
159
-
160
- ## Behavior
161
-
162
- - **No overlapping** — waits for the command to finish before starting the next interval
163
- - **Resilient** — continues looping even if a command exits with a non-zero code
164
- - **Persistent** — loop state is saved after every run; survives restarts
165
- - **Graceful shutdown** — background loops are daemon-managed; foreground loops finish the current execution on Ctrl+C
166
-
167
- ## Development
168
-
169
- Requires [Bun](https://bun.sh) >= 1.2 for package management and the board, and [Node.js](https://nodejs.org) >= 20 for the CLI and daemon.
170
-
171
- ```bash
172
- bun install
173
- npm run build
174
- ```
175
-
176
- Run locally:
177
-
178
- ```bash
179
- bun run dev # board
180
- node dist/entry.js new --now 30m -- npm test # background loop
181
- node dist/entry.js run --now --max-runs 1 10s -- echo hello # foreground
182
- ```
183
-
184
- Quality gates:
185
-
186
- ```bash
187
- bun run typecheck
188
- bun run lint
189
- bun run test
190
- npm run build
191
- ```
192
-
193
- ## License
194
-
195
- MIT
1
+ <div align="center">
2
+
3
+ # loop-task
4
+
5
+ **Run commands on repeat. Manage them from a terminal board.**
6
+
7
+ `loop-task` is a cross-platform CLI that runs shell commands at human-readable intervals. Create loops in the background, manage them from an interactive TUI board, or run them in the foreground.
8
+
9
+ [![npm version](https://img.shields.io/npm/v/loop-task?style=flat-square&color=black)](https://www.npmjs.com/package/loop-task)
10
+ [![npm downloads](https://img.shields.io/npm/dm/loop-task?style=flat-square&color=black)](https://www.npmjs.com/package/loop-task)
11
+ [![license](https://img.shields.io/npm/l/loop-task?style=flat-square&color=black)](./LICENSE)
12
+ [![node](https://img.shields.io/node/v/loop-task?style=flat-square&color=black)](https://nodejs.org)
13
+
14
+ </div>
15
+
16
+ ## Quick start
17
+
18
+ ```bash
19
+ npm install -g loop-task
20
+ loop-task # open the board (requires Bun)
21
+ loop-task start # start the daemon, restore persisted loops
22
+ loop-task new 30m -- npm test # create a background loop
23
+ loop-task run --now 10s -- echo hi # run a loop in the foreground
24
+ ```
25
+
26
+ Or run it directly:
27
+
28
+ ```bash
29
+ npx loop-task
30
+ npx loop-task new 30m -- npm test
31
+ ```
32
+
33
+ ## Requirements
34
+
35
+ - **Node.js >= 20** — required for all commands
36
+ - **Bun >= 1.2** — required for the interactive board only
37
+
38
+ Install Bun:
39
+
40
+ ```bash
41
+ npm install -g bun
42
+ ```
43
+
44
+ `start`, `new`, and `run` work with Node alone. The board auto-delegates to Bun when needed.
45
+
46
+ ## Concepts
47
+
48
+ ### Loops
49
+
50
+ A **loop** is a schedule it defines *when* something runs. Loops trigger **tasks**.
51
+
52
+ | Field | Description |
53
+ | ----- | ----------- |
54
+ | **Interval** | How often to run (`30s`, `5m`, `1h`, `1d`, `1w`) |
55
+ | **Task** | Inline command or a reference to a previously defined task |
56
+ | **Description** | Optional label shown in the list; defaults to the task name |
57
+ | **Run immediately?** | Run once now, then every interval, or wait the first interval |
58
+ | **Max runs** | Stop after N runs, or leave blank to run forever |
59
+
60
+ ### Tasks
61
+
62
+ A **task** is an executable unit — it defines *what* runs. Tasks can chain to other tasks on success or failure.
63
+
64
+ | Field | Description |
65
+ | ----- | ----------- |
66
+ | **Name** | A short label for the task |
67
+ | **Command** | The full command line |
68
+ | **On success** | Optional task to run when this one exits with code 0 |
69
+ | **On failure** | Optional task to run when this one exits with a non-zero code |
70
+
71
+ Tasks are reusable — the same task can be referenced by multiple loops or by other tasks' success/failure chains.
72
+
73
+ ### Projects
74
+
75
+ A **project** is an organizational scope for loops. Every loop belongs to exactly one project. The board shows only loops in the currently selected project.
76
+
77
+ | Field | Description |
78
+ | ----- | ----------- |
79
+ | **Name** | A short label for the project |
80
+ | **Color** | One of six colors: white, cyan, orange, green, red, yellow |
81
+
82
+ Key behaviors:
83
+ - **Default project** — always present, cannot be renamed or deleted. New loops are assigned here when no other project is selected.
84
+ - **Color bullets** — each loop in the navigator displays a colored bullet (●) matching its project color.
85
+ - **Project filter** the board shows only loops belonging to the currently active project. The selection persists across sessions via `localStorage`.
86
+
87
+ To use projects from the board:
88
+ - Press `c` to open the **Project selector** (switch between projects)
89
+ - Click **Manage Projects** in the filter bar (or use the keyboard shortcut) to open the **Manage Projects** page
90
+ - From the Manage Projects page: `n` creates a new project, `e` renames the selected project, `d` deletes it, `Esc` returns to the board
91
+
92
+ From the CLI:
93
+ - `loop-task project list` — list all projects
94
+ - `loop-task project new <name> [--color <color>]` — create a project
95
+ - `loop-task project rename <id|name> <new-name>` — rename a project
96
+ - `loop-task project color <id|name> <color>` change a project's color
97
+ - `loop-task project delete <id|name>` — delete a project (loops move to Default)
98
+ - `loop-task new <interval> --project <name> -- <command>` — create a loop assigned to a project
99
+
100
+ Colors can be a name (`white`, `cyan`, `green`, `yellow`, `orange`, `pink`) or a `#rrggbb` hex value.
101
+
102
+ ## Commands
103
+
104
+ | Command | Description |
105
+ | ------- | ----------- |
106
+ | `loop-task` | Open the interactive board (requires Bun) |
107
+ | `loop-task start` | Start the background daemon, restore persisted loops |
108
+ | `loop-task new <interval> -- <command>` | Create a background loop (creates an inline task) |
109
+ | `loop-task new <interval> --project <name> -- <command>` | Create a loop assigned to a project |
110
+ | `loop-task run <interval> -- <command>` | Run a loop in the foreground |
111
+ | `loop-task project list` | List all projects |
112
+ | `loop-task project new <name> [--color <color>]` | Create a project |
113
+ | `loop-task project rename <id\|name> <new-name>` | Rename a project |
114
+ | `loop-task project color <id\|name> <color>` | Change project color |
115
+ | `loop-task project delete <id\|name>` | Delete a project (loops move to Default) |
116
+
117
+ ### Options (for `new` and `run`)
118
+
119
+ | Option | Description |
120
+ | ------ | ----------- |
121
+ | `--now` | Run immediately before waiting |
122
+ | `--max-runs <n>` | Stop after N executions |
123
+ | `--cwd <dir>` | Working directory for the command |
124
+ | `--verbose` | Show execution details |
125
+ | `-h, --help` | Display help |
126
+ | `-V, --version` | Display version |
127
+
128
+ ## Examples
129
+
130
+ ```bash
131
+ # Run tests every 30 minutes
132
+ loop-task new 30m -- npm test
133
+
134
+ # Run immediately, then every hour
135
+ loop-task new --now 1h -- npm test
136
+
137
+ # Run up to 5 times, then stop
138
+ loop-task run --max-runs 5 5m -- npm test
139
+
140
+ # Agent workflowschedule an AI task every 30 minutes
141
+ loop-task new 30m --now -- opencode run "search missing translations and translate them, 3 maximum" --model "opencode/big-pickle"
142
+ # Run in a specific directory
143
+ loop-task new 30m --cwd ./packages/api -- npm test
144
+
145
+ # Verbose mode
146
+ loop-task run --verbose 30m -- npm test
147
+ ```
148
+
149
+ When the command has its own flags, use `--` to stop argument parsing:
150
+
151
+ ```bash
152
+ loop-task new 30m -- node -e "console.log('hello')"
153
+ ```
154
+
155
+ ## The board
156
+
157
+ The board is the primary way to manage loops and tasks. It shows all loops, their status, run history, and logs in a single terminal interface.
158
+
159
+ ### Board controls
160
+
161
+ ```
162
+ ↑/↓, j/k move selection
163
+ Enter edit selected loop
164
+ e edit loop
165
+ d/del delete loop
166
+ p pause (when waiting) / play (when idle/paused)
167
+ s stop loop (resets schedule)
168
+ n create a new loop
169
+ t create a new task
170
+ o cycle sort mode (order by)
171
+ ←/→ switch between panels
172
+ / search loops
173
+ h toggle help
174
+ esc quit
175
+ ```
176
+
177
+ Destructive actions (pause, force run, delete) prompt a confirmation before executing.
178
+
179
+ ### Pause vs Stop
180
+
181
+ - **Pause** (`p`) — temporarily halts the loop. Resuming continues the original schedule (e.g., a loop that runs every 6h at :00 paused at 12:00 and resumed at 14:00 will still fire at 16:00).
182
+ - **Stop** (`s`) — halts the loop and clears the schedule. Playing starts a fresh interval from now (e.g., the same loop stopped at 12:00 and played at 14:00 will fire at 20:00).
183
+
184
+ ## How it works
185
+
186
+ ```
187
+ loop-task (board) ──IPC──► daemon ──► loop 1 ──► task (command)
188
+ ├──► loop 2 ──► task ──► on-success task
189
+ └──► loop 3 ──► task ──► on-failure task
190
+ ```
191
+
192
+ - The **daemon** is a background process that manages all loops and tasks. It starts automatically when you run `loop-task start` or any command that needs it.
193
+ - The **board** is a terminal UI that connects to the daemon via IPC.
194
+ - **Loops** define schedules and reference tasks. **Tasks** define commands and optional success/failure chains.
195
+ - Loops and tasks **persist to disk** — they survive daemon restarts and system reboots. When the daemon starts, it restores all loops and accounts for elapsed time.
196
+
197
+ ### Lifecycle
198
+
199
+ 1. `loop-task start` or `loop-task new ...` spawns the daemon if not running
200
+ 2. The daemon creates a loop and a task, and persists their state to disk
201
+ 3. `loop-task` opens the board for interactive management
202
+ 4. Closing the board or terminal does **not** stop loops — the daemon keeps running
203
+ 5. After a reboot, `loop-task start` restores all persisted loops with correct timing
204
+
205
+ ## Supported intervals
206
+
207
+ | Format | Description |
208
+ | ------ | ----------- |
209
+ | `10s` | 10 seconds |
210
+ | `5m` | 5 minutes |
211
+ | `1h` | 1 hour |
212
+ | `1d` | 1 day |
213
+ | `1w` | 1 week |
214
+
215
+ ## Behavior
216
+
217
+ - **No overlapping** — waits for the command to finish before starting the next interval
218
+ - **Resilient** — continues looping even if a command exits with a non-zero code
219
+ - **Persistent** — loop and task state is saved after every run; survives restarts
220
+ - **Graceful shutdown** — background loops are daemon-managed; foreground loops finish the current execution on Ctrl+C
221
+
222
+ ## Development
223
+
224
+ Requires [Bun](https://bun.sh) >= 1.2 for package management and the board, and [Node.js](https://nodejs.org) >= 20 for the CLI and daemon.
225
+
226
+ ```bash
227
+ bun install
228
+ npm run build
229
+ ```
230
+
231
+ Run locally:
232
+
233
+ ```bash
234
+ bun run dev # board
235
+ node dist/entry.js new --now 30m -- npm test # background loop
236
+ node dist/entry.js run --now --max-runs 1 10s -- echo hello # foreground
237
+ ```
238
+
239
+ Quality gates:
240
+
241
+ ```bash
242
+ bun run typecheck
243
+ bun run lint
244
+ bun run test
245
+ npm run build
246
+ ```
247
+
248
+ ## License
249
+
250
+ MIT