clocktopus 1.0.6 → 1.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 +36 -157
- package/dist/dashboard/routes/monitor.js +16 -9
- package/dist/index.js +56 -7
- package/dist/lib/db.js +9 -1
- package/package.json +6 -7
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
CLI-based time-tracking automation for Clockify with idle monitoring, Jira integration, Google Calendar sync, and a web dashboard.
|
|
8
8
|
|
|
9
|
-
## Quick Start
|
|
9
|
+
## Quick Start
|
|
10
10
|
|
|
11
11
|
Most users only need the dashboard — a web UI to manage timers, connect integrations, and monitor idle time.
|
|
12
12
|
|
|
@@ -45,14 +45,20 @@ Open [http://localhost:4001](http://localhost:4001) in your browser.
|
|
|
45
45
|
|
|
46
46
|
That's it. Start/stop timers from the Home tab.
|
|
47
47
|
|
|
48
|
-
###
|
|
49
|
-
|
|
50
|
-
| Command
|
|
51
|
-
|
|
|
52
|
-
| `clocktopus dash`
|
|
53
|
-
| `clocktopus serve`
|
|
54
|
-
| `clocktopus serve:stop`
|
|
55
|
-
| `clocktopus serve:logs`
|
|
48
|
+
### Commands
|
|
49
|
+
|
|
50
|
+
| Command | Description |
|
|
51
|
+
| ------------------------- | --------------------------------------- |
|
|
52
|
+
| `clocktopus dash` | Start dashboard (foreground) |
|
|
53
|
+
| `clocktopus serve` | Start dashboard as background daemon |
|
|
54
|
+
| `clocktopus serve:stop` | Stop the dashboard daemon |
|
|
55
|
+
| `clocktopus serve:logs` | View dashboard daemon logs |
|
|
56
|
+
| `clocktopus start` | Start a timer (interactive) |
|
|
57
|
+
| `clocktopus stop` | Stop the current timer |
|
|
58
|
+
| `clocktopus status` | Check timer status |
|
|
59
|
+
| `clocktopus monitor` | Start idle monitor as background daemon |
|
|
60
|
+
| `clocktopus monitor:stop` | Stop the idle monitor |
|
|
61
|
+
| `clocktopus monitor:logs` | View idle monitor logs |
|
|
56
62
|
|
|
57
63
|
### Desktop App (macOS)
|
|
58
64
|
|
|
@@ -68,9 +74,7 @@ The dashboard server must be running (`clocktopus serve`). See [desktop/README.m
|
|
|
68
74
|
|
|
69
75
|
---
|
|
70
76
|
|
|
71
|
-
##
|
|
72
|
-
|
|
73
|
-
For CLI-based workflows, scripting, and advanced features.
|
|
77
|
+
## Development
|
|
74
78
|
|
|
75
79
|
### Install from Source
|
|
76
80
|
|
|
@@ -81,105 +85,32 @@ bun install
|
|
|
81
85
|
bun run build
|
|
82
86
|
```
|
|
83
87
|
|
|
84
|
-
### Local
|
|
88
|
+
### Local Commands
|
|
85
89
|
|
|
86
90
|
When running from source, use `bun run clock` instead of `clocktopus`:
|
|
87
91
|
|
|
88
92
|
```bash
|
|
89
|
-
# Build
|
|
90
|
-
bun run build
|
|
93
|
+
bun run build # Build TypeScript
|
|
91
94
|
|
|
92
|
-
# Dashboard
|
|
93
95
|
bun run dashboard # Start dashboard (foreground)
|
|
94
|
-
|
|
95
|
-
# Timer
|
|
96
96
|
bun run clock start "Task" # Start a timer
|
|
97
97
|
bun run clock start -j PROJ-1 # Start with Jira ticket
|
|
98
98
|
bun run clock stop # Stop timer
|
|
99
99
|
bun run clock status # Check timer status
|
|
100
100
|
|
|
101
|
-
# Monitor
|
|
102
101
|
bun run monitor # Start idle monitor (PM2 daemon)
|
|
103
102
|
bun run monitor:stop # Stop monitor
|
|
104
103
|
bun run monitor:restart # Restart monitor
|
|
105
|
-
bun run monitor:status # Check monitor status
|
|
106
104
|
bun run monitor:logs # View monitor logs
|
|
107
105
|
|
|
108
|
-
# Google Calendar
|
|
109
106
|
bun run google-auth # Authenticate Google account
|
|
110
107
|
bun run log-calendar -t # Log today's events
|
|
111
|
-
|
|
112
|
-
# Database
|
|
113
108
|
bun run db:cleanup # Clean old session logs
|
|
114
109
|
```
|
|
115
110
|
|
|
116
|
-
### CLI Commands
|
|
117
|
-
|
|
118
|
-
#### Timer Management
|
|
119
|
-
|
|
120
|
-
```bash
|
|
121
|
-
# Start a timer (interactive project selection)
|
|
122
|
-
clocktopus start "Task description"
|
|
123
|
-
|
|
124
|
-
# Start with a Jira ticket (auto-fetches ticket title)
|
|
125
|
-
clocktopus start -j TICKET-123
|
|
126
|
-
|
|
127
|
-
# Stop the current timer
|
|
128
|
-
clocktopus stop
|
|
129
|
-
|
|
130
|
-
# Check timer status
|
|
131
|
-
clocktopus status
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
#### Idle Monitor
|
|
135
|
-
|
|
136
|
-
Automatically stops timers when you're idle (5 min) or lock your screen, and restarts when you're back.
|
|
137
|
-
|
|
138
|
-
```bash
|
|
139
|
-
# Run in foreground
|
|
140
|
-
clocktopus monitor
|
|
141
|
-
|
|
142
|
-
# Or manage via dashboard UI (Start/Stop/Restart buttons)
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
The dashboard's Idle Monitor buttons use PM2 under the hood:
|
|
146
|
-
|
|
147
|
-
| Action | What it does |
|
|
148
|
-
| ----------- | ------------------------------ |
|
|
149
|
-
| **Start** | Launches monitor as PM2 daemon |
|
|
150
|
-
| **Stop** | Stops the monitor daemon |
|
|
151
|
-
| **Restart** | Restarts after code changes |
|
|
152
|
-
|
|
153
|
-
#### Google Calendar Integration
|
|
154
|
-
|
|
155
|
-
Log Google Calendar events as Clockify time entries.
|
|
156
|
-
|
|
157
|
-
```bash
|
|
158
|
-
# Authenticate (one-time)
|
|
159
|
-
clocktopus google-auth
|
|
160
|
-
|
|
161
|
-
# Log events for a date range
|
|
162
|
-
clocktopus log-calendar -s 2025-07-21 -e 2025-07-22
|
|
163
|
-
|
|
164
|
-
# Log today's events
|
|
165
|
-
clocktopus log-calendar -t
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
For each event, you'll be prompted to select a Clockify project. Selections are cached by event name for recurring meetings.
|
|
169
|
-
|
|
170
|
-
#### Database Cleanup
|
|
171
|
-
|
|
172
|
-
```bash
|
|
173
|
-
# Delete session logs older than 5 days (default)
|
|
174
|
-
clocktopus db:cleanup
|
|
175
|
-
|
|
176
|
-
# Delete logs older than N days
|
|
177
|
-
clocktopus db:cleanup 10
|
|
178
|
-
```
|
|
179
|
-
|
|
180
111
|
### Configuration
|
|
181
112
|
|
|
182
|
-
All configuration is stored in a local SQLite database
|
|
113
|
+
All configuration is stored in a local SQLite database and managed through the dashboard Settings tab.
|
|
183
114
|
|
|
184
115
|
| Setting | How to configure |
|
|
185
116
|
| ---------------- | ------------------------------------------------ |
|
|
@@ -188,56 +119,23 @@ All configuration is stored in a local SQLite database (`data/sessions.db`) and
|
|
|
188
119
|
| Jira (API token) | Dashboard > Settings > "or use API token" |
|
|
189
120
|
| Google Calendar | Dashboard > Settings > Click "Connect Google" |
|
|
190
121
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
- **Jira**: OAuth tokens are exchanged through a [Cloudflare Worker proxy](docs/atlassian-proxy-flow.md) that holds the client secret securely. Users just click Connect.
|
|
194
|
-
- **Google**: Uses a Desktop-type OAuth client. Credentials are handled transparently.
|
|
195
|
-
- **Clockify**: Each user provides their own API key.
|
|
196
|
-
|
|
197
|
-
#### Environment Variables (Optional Override)
|
|
198
|
-
|
|
199
|
-
Power users can override credentials via environment variables or a `.env` file:
|
|
200
|
-
|
|
201
|
-
```
|
|
202
|
-
CLOCKIFY_API_KEY="your_key"
|
|
203
|
-
ATLASSIAN_CLIENT_ID="your_id"
|
|
204
|
-
ATLASSIAN_CLIENT_SECRET="your_secret"
|
|
205
|
-
GOOGLE_CLIENT_ID="your_id"
|
|
206
|
-
GOOGLE_CLIENT_SECRET="your_secret"
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
The app checks the database first, then falls back to environment variables.
|
|
122
|
+
OAuth for Jira and Google is handled transparently through a [Cloudflare Worker proxy](docs/atlassian-proxy-flow.md) — no client credentials needed from users.
|
|
210
123
|
|
|
211
|
-
###
|
|
124
|
+
### Project Structure
|
|
212
125
|
|
|
213
|
-
On first `clocktopus start`, all projects are saved to `data/local-projects.json`. Edit this file to keep only your frequently used projects:
|
|
214
|
-
|
|
215
|
-
```json
|
|
216
|
-
[
|
|
217
|
-
{ "id": "671b783fbd91bc5e5ddcb944", "name": "Project A" },
|
|
218
|
-
{ "id": "another_id", "name": "Project B" }
|
|
219
|
-
]
|
|
220
126
|
```
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
alias cbuild="clockto build"
|
|
235
|
-
alias cstart="clockto clock start"
|
|
236
|
-
alias cstop="clockto clock stop"
|
|
237
|
-
alias mstart="clockto monitor"
|
|
238
|
-
alias mstop="clockto monitor:stop"
|
|
239
|
-
alias mrestart="clockto monitor:restart"
|
|
240
|
-
alias mlogs="clockto monitor:logs"
|
|
127
|
+
clocktopus/
|
|
128
|
+
├── index.ts # CLI entry point (Commander)
|
|
129
|
+
├── clockify.ts # Clockify API client
|
|
130
|
+
├── lib/ # Core libraries (db, auth, credentials)
|
|
131
|
+
├── dashboard/ # Web dashboard (Hono server)
|
|
132
|
+
│ ├── server.ts # Dashboard server
|
|
133
|
+
│ ├── views.ts # HTML/CSS/JS (single-page app)
|
|
134
|
+
│ └── routes/ # API routes
|
|
135
|
+
├── desktop/ # Tauri macOS menu bar app
|
|
136
|
+
├── proxy/ # Cloudflare Worker (OAuth proxy)
|
|
137
|
+
├── scripts/ # Google auth & calendar scripts
|
|
138
|
+
└── data/ # SQLite DB & config (gitignored)
|
|
241
139
|
```
|
|
242
140
|
|
|
243
141
|
---
|
|
@@ -246,37 +144,18 @@ alias mlogs="clockto monitor:logs"
|
|
|
246
144
|
|
|
247
145
|
### No notifications on macOS
|
|
248
146
|
|
|
249
|
-
Go to **System Settings > Notifications** and ensure **terminal-notifier**
|
|
147
|
+
Go to **System Settings > Notifications** and ensure **terminal-notifier** has notifications enabled.
|
|
250
148
|
|
|
251
149
|
### Monitor not detecting display off
|
|
252
150
|
|
|
253
|
-
|
|
151
|
+
Enable **Require password immediately** in System Settings > Lock Screen.
|
|
254
152
|
|
|
255
|
-
### Linux
|
|
153
|
+
### Linux
|
|
256
154
|
|
|
257
155
|
```bash
|
|
258
156
|
apt install libxss-dev pkg-config build-essential
|
|
259
157
|
```
|
|
260
158
|
|
|
261
|
-
---
|
|
262
|
-
|
|
263
|
-
## Project Structure
|
|
264
|
-
|
|
265
|
-
```
|
|
266
|
-
clocktopus/
|
|
267
|
-
├── index.ts # CLI entry point (Commander)
|
|
268
|
-
├── clockify.ts # Clockify API client
|
|
269
|
-
├── lib/ # Core libraries (db, auth, credentials)
|
|
270
|
-
├── dashboard/ # Web dashboard (Hono server)
|
|
271
|
-
│ ├── server.ts # Dashboard server
|
|
272
|
-
│ ├── views.ts # HTML/CSS/JS (single-page app)
|
|
273
|
-
│ └── routes/ # API routes
|
|
274
|
-
├── desktop/ # Tauri macOS menu bar app
|
|
275
|
-
├── proxy/ # Cloudflare Worker (OAuth proxy)
|
|
276
|
-
├── scripts/ # Google auth & calendar scripts
|
|
277
|
-
└── data/ # SQLite DB & config (gitignored)
|
|
278
|
-
```
|
|
279
|
-
|
|
280
159
|
## License
|
|
281
160
|
|
|
282
161
|
MIT
|
|
@@ -5,6 +5,8 @@ import { fileURLToPath } from 'url';
|
|
|
5
5
|
const __filename = fileURLToPath(import.meta.url);
|
|
6
6
|
const __dirname = path.dirname(__filename);
|
|
7
7
|
const SCRIPT_PATH = path.resolve(__dirname, '../../index.js');
|
|
8
|
+
const isDev = SCRIPT_PATH.includes('/Projects/') || SCRIPT_PATH.includes('/src/');
|
|
9
|
+
const PM2_NAME = isDev ? 'clocktopus-monitor-dev' : 'clocktopus-monitor';
|
|
8
10
|
const monitorRoutes = new Hono();
|
|
9
11
|
function pm2Exec(command) {
|
|
10
12
|
try {
|
|
@@ -20,15 +22,15 @@ monitorRoutes.get('/monitor/status', (c) => {
|
|
|
20
22
|
try {
|
|
21
23
|
const output = execSync('bunx pm2 jlist', { encoding: 'utf-8', timeout: 10000 });
|
|
22
24
|
const processes = JSON.parse(output);
|
|
23
|
-
const
|
|
24
|
-
if (!
|
|
25
|
+
const proc = processes.find((p) => p.name === PM2_NAME);
|
|
26
|
+
if (!proc) {
|
|
25
27
|
return c.json({ running: false, status: 'not found' });
|
|
26
28
|
}
|
|
27
29
|
return c.json({
|
|
28
|
-
running:
|
|
29
|
-
status:
|
|
30
|
-
uptime:
|
|
31
|
-
restarts:
|
|
30
|
+
running: proc.pm2_env.status === 'online',
|
|
31
|
+
status: proc.pm2_env.status,
|
|
32
|
+
uptime: proc.pm2_env.pm_uptime,
|
|
33
|
+
restarts: proc.pm2_env.restart_time,
|
|
32
34
|
});
|
|
33
35
|
}
|
|
34
36
|
catch {
|
|
@@ -37,15 +39,20 @@ monitorRoutes.get('/monitor/status', (c) => {
|
|
|
37
39
|
});
|
|
38
40
|
monitorRoutes.post('/monitor/start', (c) => {
|
|
39
41
|
const bunPath = execSync('which bun', { encoding: 'utf-8' }).trim();
|
|
40
|
-
|
|
42
|
+
// Delete any existing process to avoid duplicates
|
|
43
|
+
try {
|
|
44
|
+
execSync(`bunx pm2 delete ${PM2_NAME}`, { stdio: 'ignore' });
|
|
45
|
+
}
|
|
46
|
+
catch { }
|
|
47
|
+
const result = pm2Exec(`bunx pm2 start ${SCRIPT_PATH} --name ${PM2_NAME} --interpreter ${bunPath} -- monitor:run`);
|
|
41
48
|
return c.json(result);
|
|
42
49
|
});
|
|
43
50
|
monitorRoutes.post('/monitor/stop', (c) => {
|
|
44
|
-
const result = pm2Exec(
|
|
51
|
+
const result = pm2Exec(`bunx pm2 stop ${PM2_NAME}`);
|
|
45
52
|
return c.json(result);
|
|
46
53
|
});
|
|
47
54
|
monitorRoutes.post('/monitor/restart', (c) => {
|
|
48
|
-
const result = pm2Exec(
|
|
55
|
+
const result = pm2Exec(`bunx pm2 restart ${PM2_NAME}`);
|
|
49
56
|
return c.json(result);
|
|
50
57
|
});
|
|
51
58
|
export default monitorRoutes;
|
package/dist/index.js
CHANGED
|
@@ -137,8 +137,8 @@ function sleep(ms) {
|
|
|
137
137
|
return new Promise((res) => setTimeout(res, ms));
|
|
138
138
|
}
|
|
139
139
|
program
|
|
140
|
-
.command('monitor')
|
|
141
|
-
.description('
|
|
140
|
+
.command('monitor:run', { hidden: true })
|
|
141
|
+
.description('Run monitor in foreground (used by PM2).')
|
|
142
142
|
.action(async () => {
|
|
143
143
|
const { workspaceId, userId } = await getWorkspaceAndUser();
|
|
144
144
|
async function stopTimerAndLog(reason) {
|
|
@@ -275,6 +275,56 @@ program
|
|
|
275
275
|
.action(() => {
|
|
276
276
|
startDashboard();
|
|
277
277
|
});
|
|
278
|
+
const isDev = __dirname.includes('/Projects/') || __dirname.includes('/src/');
|
|
279
|
+
const MONITOR_PM2_NAME = isDev ? 'clocktopus-monitor-dev' : 'clocktopus-monitor';
|
|
280
|
+
const DASH_PM2_NAME = isDev ? 'clocktopus-dash-dev' : 'clocktopus-dash';
|
|
281
|
+
program
|
|
282
|
+
.command('monitor')
|
|
283
|
+
.description('Start idle monitor as a background daemon.')
|
|
284
|
+
.action(async () => {
|
|
285
|
+
const { execSync } = await import('child_process');
|
|
286
|
+
const bunPath = execSync('which bun', { encoding: 'utf-8' }).trim();
|
|
287
|
+
const scriptPath = path.join(__dirname, 'index.js');
|
|
288
|
+
try {
|
|
289
|
+
try {
|
|
290
|
+
execSync(`bunx pm2 delete ${MONITOR_PM2_NAME}`, { stdio: 'ignore' });
|
|
291
|
+
}
|
|
292
|
+
catch { }
|
|
293
|
+
execSync(`bunx pm2 start ${scriptPath} --name ${MONITOR_PM2_NAME} --interpreter ${bunPath} -- monitor:run`, {
|
|
294
|
+
stdio: 'inherit',
|
|
295
|
+
});
|
|
296
|
+
console.log(chalk.green('Idle monitor started in background.'));
|
|
297
|
+
console.log(chalk.gray(' Stop: clocktopus monitor:stop'));
|
|
298
|
+
console.log(chalk.gray(' Logs: clocktopus monitor:logs'));
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
console.error(chalk.red('Failed to start monitor.'));
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
program
|
|
305
|
+
.command('monitor:stop')
|
|
306
|
+
.description('Stop the idle monitor daemon.')
|
|
307
|
+
.action(async () => {
|
|
308
|
+
const { execSync } = await import('child_process');
|
|
309
|
+
try {
|
|
310
|
+
execSync(`bunx pm2 stop ${MONITOR_PM2_NAME}`, { stdio: 'inherit' });
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
console.log(chalk.yellow('Monitor is not running.'));
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
program
|
|
317
|
+
.command('monitor:logs')
|
|
318
|
+
.description('Show idle monitor logs.')
|
|
319
|
+
.action(async () => {
|
|
320
|
+
const { execSync } = await import('child_process');
|
|
321
|
+
try {
|
|
322
|
+
execSync(`bunx pm2 logs ${MONITOR_PM2_NAME} --lines 50`, { stdio: 'inherit' });
|
|
323
|
+
}
|
|
324
|
+
catch {
|
|
325
|
+
console.log(chalk.yellow('Monitor is not running.'));
|
|
326
|
+
}
|
|
327
|
+
});
|
|
278
328
|
program
|
|
279
329
|
.command('serve')
|
|
280
330
|
.description('Start dashboard as a background daemon (PM2).')
|
|
@@ -283,12 +333,11 @@ program
|
|
|
283
333
|
const bunPath = execSync('which bun', { encoding: 'utf-8' }).trim();
|
|
284
334
|
const scriptPath = path.join(__dirname, 'index.js');
|
|
285
335
|
try {
|
|
286
|
-
// Stop existing if running
|
|
287
336
|
try {
|
|
288
|
-
execSync(
|
|
337
|
+
execSync(`bunx pm2 delete ${DASH_PM2_NAME}`, { stdio: 'ignore' });
|
|
289
338
|
}
|
|
290
339
|
catch { }
|
|
291
|
-
execSync(`bunx pm2 start ${scriptPath} --name
|
|
340
|
+
execSync(`bunx pm2 start ${scriptPath} --name ${DASH_PM2_NAME} --interpreter ${bunPath} -- dash`, {
|
|
292
341
|
stdio: 'inherit',
|
|
293
342
|
});
|
|
294
343
|
console.log(chalk.green('Dashboard running at http://localhost:4001'));
|
|
@@ -305,7 +354,7 @@ program
|
|
|
305
354
|
.action(async () => {
|
|
306
355
|
const { execSync } = await import('child_process');
|
|
307
356
|
try {
|
|
308
|
-
execSync(
|
|
357
|
+
execSync(`bunx pm2 stop ${DASH_PM2_NAME}`, { stdio: 'inherit' });
|
|
309
358
|
}
|
|
310
359
|
catch {
|
|
311
360
|
console.log(chalk.yellow('Dashboard is not running.'));
|
|
@@ -317,7 +366,7 @@ program
|
|
|
317
366
|
.action(async () => {
|
|
318
367
|
const { execSync } = await import('child_process');
|
|
319
368
|
try {
|
|
320
|
-
execSync(
|
|
369
|
+
execSync(`bunx pm2 logs ${DASH_PM2_NAME} --lines 50`, { stdio: 'inherit' });
|
|
321
370
|
}
|
|
322
371
|
catch {
|
|
323
372
|
console.log(chalk.yellow('Dashboard is not running.'));
|
package/dist/lib/db.js
CHANGED
|
@@ -2,7 +2,15 @@ import * as fs from 'fs';
|
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { Database } from 'bun:sqlite';
|
|
4
4
|
import { z } from 'zod';
|
|
5
|
-
|
|
5
|
+
function getDataDir() {
|
|
6
|
+
const scriptDir = path.dirname(new URL(import.meta.url).pathname);
|
|
7
|
+
const isDev = scriptDir.includes('/Projects/') || scriptDir.includes('/src/');
|
|
8
|
+
if (isDev) {
|
|
9
|
+
return path.join(process.cwd(), 'data/db');
|
|
10
|
+
}
|
|
11
|
+
return path.join(process.env.HOME || '~', '.clocktopus', 'data');
|
|
12
|
+
}
|
|
13
|
+
const DB_DIR = getDataDir();
|
|
6
14
|
const DB_PATH = path.join(DB_DIR, 'sessions.db');
|
|
7
15
|
if (!fs.existsSync(DB_DIR)) {
|
|
8
16
|
fs.mkdirSync(DB_DIR, { recursive: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clocktopus",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -18,12 +18,11 @@
|
|
|
18
18
|
"postinstall": "cd node_modules/macos-notification-state && node-gyp rebuild 2>/dev/null; cd ../desktop-idle && node-gyp rebuild 2>/dev/null; true",
|
|
19
19
|
"lint": "eslint . --ext .ts",
|
|
20
20
|
"clock": "bun dist/index.js",
|
|
21
|
-
"
|
|
22
|
-
"monitor": "bun
|
|
23
|
-
"monitor:restart": "bunx pm2 restart clocktopus",
|
|
24
|
-
"monitor:
|
|
25
|
-
"monitor:
|
|
26
|
-
"monitor:status": "bunx pm2 status clocktopus",
|
|
21
|
+
"monitor": "bun dist/index.js monitor",
|
|
22
|
+
"monitor:stop": "bun dist/index.js monitor:stop",
|
|
23
|
+
"monitor:restart": "bunx pm2 restart clocktopus-monitor-dev",
|
|
24
|
+
"monitor:logs": "bun dist/index.js monitor:logs",
|
|
25
|
+
"monitor:status": "bunx pm2 status clocktopus-monitor-dev",
|
|
27
26
|
"prepare": "husky",
|
|
28
27
|
"dashboard": "bun -e \"import('./dist/dashboard/server.js').then(m => m.startDashboard())\"",
|
|
29
28
|
"db:cleanup": "bun dist/scripts/db-cleanup.js",
|