clocktopus 1.0.5 → 1.0.7
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 +33 -154
- package/dist/dashboard/routes/monitor.js +15 -9
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -6,20 +6,22 @@
|
|
|
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
|
|
|
13
|
-
###
|
|
13
|
+
### Prerequisites
|
|
14
|
+
|
|
15
|
+
[Bun](https://bun.sh) is required (used as the runtime):
|
|
14
16
|
|
|
15
17
|
```bash
|
|
16
|
-
|
|
18
|
+
curl -fsSL https://bun.sh/install | bash
|
|
17
19
|
```
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
### Install
|
|
20
22
|
|
|
21
23
|
```bash
|
|
22
|
-
|
|
24
|
+
bun i -g clocktopus
|
|
23
25
|
```
|
|
24
26
|
|
|
25
27
|
### Run
|
|
@@ -43,7 +45,7 @@ Open [http://localhost:4001](http://localhost:4001) in your browser.
|
|
|
43
45
|
|
|
44
46
|
That's it. Start/stop timers from the Home tab.
|
|
45
47
|
|
|
46
|
-
###
|
|
48
|
+
### Commands
|
|
47
49
|
|
|
48
50
|
| Command | Description |
|
|
49
51
|
| ----------------------- | ------------------------------------ |
|
|
@@ -51,6 +53,10 @@ That's it. Start/stop timers from the Home tab.
|
|
|
51
53
|
| `clocktopus serve` | Start dashboard as background daemon |
|
|
52
54
|
| `clocktopus serve:stop` | Stop the dashboard daemon |
|
|
53
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 (foreground) |
|
|
54
60
|
|
|
55
61
|
### Desktop App (macOS)
|
|
56
62
|
|
|
@@ -66,9 +72,7 @@ The dashboard server must be running (`clocktopus serve`). See [desktop/README.m
|
|
|
66
72
|
|
|
67
73
|
---
|
|
68
74
|
|
|
69
|
-
##
|
|
70
|
-
|
|
71
|
-
For CLI-based workflows, scripting, and advanced features.
|
|
75
|
+
## Development
|
|
72
76
|
|
|
73
77
|
### Install from Source
|
|
74
78
|
|
|
@@ -79,105 +83,32 @@ bun install
|
|
|
79
83
|
bun run build
|
|
80
84
|
```
|
|
81
85
|
|
|
82
|
-
### Local
|
|
86
|
+
### Local Commands
|
|
83
87
|
|
|
84
88
|
When running from source, use `bun run clock` instead of `clocktopus`:
|
|
85
89
|
|
|
86
90
|
```bash
|
|
87
|
-
# Build
|
|
88
|
-
bun run build
|
|
91
|
+
bun run build # Build TypeScript
|
|
89
92
|
|
|
90
|
-
# Dashboard
|
|
91
93
|
bun run dashboard # Start dashboard (foreground)
|
|
92
|
-
|
|
93
|
-
# Timer
|
|
94
94
|
bun run clock start "Task" # Start a timer
|
|
95
95
|
bun run clock start -j PROJ-1 # Start with Jira ticket
|
|
96
96
|
bun run clock stop # Stop timer
|
|
97
97
|
bun run clock status # Check timer status
|
|
98
98
|
|
|
99
|
-
# Monitor
|
|
100
99
|
bun run monitor # Start idle monitor (PM2 daemon)
|
|
101
100
|
bun run monitor:stop # Stop monitor
|
|
102
101
|
bun run monitor:restart # Restart monitor
|
|
103
|
-
bun run monitor:status # Check monitor status
|
|
104
102
|
bun run monitor:logs # View monitor logs
|
|
105
103
|
|
|
106
|
-
# Google Calendar
|
|
107
104
|
bun run google-auth # Authenticate Google account
|
|
108
105
|
bun run log-calendar -t # Log today's events
|
|
109
|
-
|
|
110
|
-
# Database
|
|
111
106
|
bun run db:cleanup # Clean old session logs
|
|
112
107
|
```
|
|
113
108
|
|
|
114
|
-
### CLI Commands
|
|
115
|
-
|
|
116
|
-
#### Timer Management
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
# Start a timer (interactive project selection)
|
|
120
|
-
clocktopus start "Task description"
|
|
121
|
-
|
|
122
|
-
# Start with a Jira ticket (auto-fetches ticket title)
|
|
123
|
-
clocktopus start -j TICKET-123
|
|
124
|
-
|
|
125
|
-
# Stop the current timer
|
|
126
|
-
clocktopus stop
|
|
127
|
-
|
|
128
|
-
# Check timer status
|
|
129
|
-
clocktopus status
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
#### Idle Monitor
|
|
133
|
-
|
|
134
|
-
Automatically stops timers when you're idle (5 min) or lock your screen, and restarts when you're back.
|
|
135
|
-
|
|
136
|
-
```bash
|
|
137
|
-
# Run in foreground
|
|
138
|
-
clocktopus monitor
|
|
139
|
-
|
|
140
|
-
# Or manage via dashboard UI (Start/Stop/Restart buttons)
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
The dashboard's Idle Monitor buttons use PM2 under the hood:
|
|
144
|
-
|
|
145
|
-
| Action | What it does |
|
|
146
|
-
| ----------- | ------------------------------ |
|
|
147
|
-
| **Start** | Launches monitor as PM2 daemon |
|
|
148
|
-
| **Stop** | Stops the monitor daemon |
|
|
149
|
-
| **Restart** | Restarts after code changes |
|
|
150
|
-
|
|
151
|
-
#### Google Calendar Integration
|
|
152
|
-
|
|
153
|
-
Log Google Calendar events as Clockify time entries.
|
|
154
|
-
|
|
155
|
-
```bash
|
|
156
|
-
# Authenticate (one-time)
|
|
157
|
-
clocktopus google-auth
|
|
158
|
-
|
|
159
|
-
# Log events for a date range
|
|
160
|
-
clocktopus log-calendar -s 2025-07-21 -e 2025-07-22
|
|
161
|
-
|
|
162
|
-
# Log today's events
|
|
163
|
-
clocktopus log-calendar -t
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
For each event, you'll be prompted to select a Clockify project. Selections are cached by event name for recurring meetings.
|
|
167
|
-
|
|
168
|
-
#### Database Cleanup
|
|
169
|
-
|
|
170
|
-
```bash
|
|
171
|
-
# Delete session logs older than 5 days (default)
|
|
172
|
-
clocktopus db:cleanup
|
|
173
|
-
|
|
174
|
-
# Delete logs older than N days
|
|
175
|
-
clocktopus db:cleanup 10
|
|
176
|
-
```
|
|
177
|
-
|
|
178
109
|
### Configuration
|
|
179
110
|
|
|
180
|
-
All configuration is stored in a local SQLite database
|
|
111
|
+
All configuration is stored in a local SQLite database and managed through the dashboard Settings tab.
|
|
181
112
|
|
|
182
113
|
| Setting | How to configure |
|
|
183
114
|
| ---------------- | ------------------------------------------------ |
|
|
@@ -186,56 +117,23 @@ All configuration is stored in a local SQLite database (`data/sessions.db`) and
|
|
|
186
117
|
| Jira (API token) | Dashboard > Settings > "or use API token" |
|
|
187
118
|
| Google Calendar | Dashboard > Settings > Click "Connect Google" |
|
|
188
119
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
- **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.
|
|
192
|
-
- **Google**: Uses a Desktop-type OAuth client. Credentials are handled transparently.
|
|
193
|
-
- **Clockify**: Each user provides their own API key.
|
|
194
|
-
|
|
195
|
-
#### Environment Variables (Optional Override)
|
|
120
|
+
OAuth for Jira and Google is handled transparently through a [Cloudflare Worker proxy](docs/atlassian-proxy-flow.md) — no client credentials needed from users.
|
|
196
121
|
|
|
197
|
-
|
|
122
|
+
### Project Structure
|
|
198
123
|
|
|
199
124
|
```
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
```json
|
|
214
|
-
[
|
|
215
|
-
{ "id": "671b783fbd91bc5e5ddcb944", "name": "Project A" },
|
|
216
|
-
{ "id": "another_id", "name": "Project B" }
|
|
217
|
-
]
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
### Shell Aliases
|
|
221
|
-
|
|
222
|
-
For quick access, add to `~/.zshrc`:
|
|
223
|
-
|
|
224
|
-
```bash
|
|
225
|
-
CLOCKTOPUS_PATH="$HOME/Projects/Personal/clocktopus"
|
|
226
|
-
|
|
227
|
-
clockto() {
|
|
228
|
-
cd "$CLOCKTOPUS_PATH" || return
|
|
229
|
-
bun run "$@"
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
alias cbuild="clockto build"
|
|
233
|
-
alias cstart="clockto clock start"
|
|
234
|
-
alias cstop="clockto clock stop"
|
|
235
|
-
alias mstart="clockto monitor"
|
|
236
|
-
alias mstop="clockto monitor:stop"
|
|
237
|
-
alias mrestart="clockto monitor:restart"
|
|
238
|
-
alias mlogs="clockto monitor:logs"
|
|
125
|
+
clocktopus/
|
|
126
|
+
├── index.ts # CLI entry point (Commander)
|
|
127
|
+
├── clockify.ts # Clockify API client
|
|
128
|
+
├── lib/ # Core libraries (db, auth, credentials)
|
|
129
|
+
├── dashboard/ # Web dashboard (Hono server)
|
|
130
|
+
│ ├── server.ts # Dashboard server
|
|
131
|
+
│ ├── views.ts # HTML/CSS/JS (single-page app)
|
|
132
|
+
│ └── routes/ # API routes
|
|
133
|
+
├── desktop/ # Tauri macOS menu bar app
|
|
134
|
+
├── proxy/ # Cloudflare Worker (OAuth proxy)
|
|
135
|
+
├── scripts/ # Google auth & calendar scripts
|
|
136
|
+
└── data/ # SQLite DB & config (gitignored)
|
|
239
137
|
```
|
|
240
138
|
|
|
241
139
|
---
|
|
@@ -244,37 +142,18 @@ alias mlogs="clockto monitor:logs"
|
|
|
244
142
|
|
|
245
143
|
### No notifications on macOS
|
|
246
144
|
|
|
247
|
-
Go to **System Settings > Notifications** and ensure **terminal-notifier**
|
|
145
|
+
Go to **System Settings > Notifications** and ensure **terminal-notifier** has notifications enabled.
|
|
248
146
|
|
|
249
147
|
### Monitor not detecting display off
|
|
250
148
|
|
|
251
|
-
|
|
149
|
+
Enable **Require password immediately** in System Settings > Lock Screen.
|
|
252
150
|
|
|
253
|
-
### Linux
|
|
151
|
+
### Linux
|
|
254
152
|
|
|
255
153
|
```bash
|
|
256
154
|
apt install libxss-dev pkg-config build-essential
|
|
257
155
|
```
|
|
258
156
|
|
|
259
|
-
---
|
|
260
|
-
|
|
261
|
-
## Project Structure
|
|
262
|
-
|
|
263
|
-
```
|
|
264
|
-
clocktopus/
|
|
265
|
-
├── index.ts # CLI entry point (Commander)
|
|
266
|
-
├── clockify.ts # Clockify API client
|
|
267
|
-
├── lib/ # Core libraries (db, auth, credentials)
|
|
268
|
-
├── dashboard/ # Web dashboard (Hono server)
|
|
269
|
-
│ ├── server.ts # Dashboard server
|
|
270
|
-
│ ├── views.ts # HTML/CSS/JS (single-page app)
|
|
271
|
-
│ └── routes/ # API routes
|
|
272
|
-
├── desktop/ # Tauri macOS menu bar app
|
|
273
|
-
├── proxy/ # Cloudflare Worker (OAuth proxy)
|
|
274
|
-
├── scripts/ # Google auth & calendar scripts
|
|
275
|
-
└── data/ # SQLite DB & config (gitignored)
|
|
276
|
-
```
|
|
277
|
-
|
|
278
157
|
## License
|
|
279
158
|
|
|
280
159
|
MIT
|
|
@@ -5,6 +5,7 @@ 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 PM2_NAME = 'clocktopus-monitor';
|
|
8
9
|
const monitorRoutes = new Hono();
|
|
9
10
|
function pm2Exec(command) {
|
|
10
11
|
try {
|
|
@@ -20,15 +21,15 @@ monitorRoutes.get('/monitor/status', (c) => {
|
|
|
20
21
|
try {
|
|
21
22
|
const output = execSync('bunx pm2 jlist', { encoding: 'utf-8', timeout: 10000 });
|
|
22
23
|
const processes = JSON.parse(output);
|
|
23
|
-
const
|
|
24
|
-
if (!
|
|
24
|
+
const proc = processes.find((p) => p.name === PM2_NAME);
|
|
25
|
+
if (!proc) {
|
|
25
26
|
return c.json({ running: false, status: 'not found' });
|
|
26
27
|
}
|
|
27
28
|
return c.json({
|
|
28
|
-
running:
|
|
29
|
-
status:
|
|
30
|
-
uptime:
|
|
31
|
-
restarts:
|
|
29
|
+
running: proc.pm2_env.status === 'online',
|
|
30
|
+
status: proc.pm2_env.status,
|
|
31
|
+
uptime: proc.pm2_env.pm_uptime,
|
|
32
|
+
restarts: proc.pm2_env.restart_time,
|
|
32
33
|
});
|
|
33
34
|
}
|
|
34
35
|
catch {
|
|
@@ -37,15 +38,20 @@ monitorRoutes.get('/monitor/status', (c) => {
|
|
|
37
38
|
});
|
|
38
39
|
monitorRoutes.post('/monitor/start', (c) => {
|
|
39
40
|
const bunPath = execSync('which bun', { encoding: 'utf-8' }).trim();
|
|
40
|
-
|
|
41
|
+
// Delete any existing process to avoid duplicates
|
|
42
|
+
try {
|
|
43
|
+
execSync(`bunx pm2 delete ${PM2_NAME}`, { stdio: 'ignore' });
|
|
44
|
+
}
|
|
45
|
+
catch { }
|
|
46
|
+
const result = pm2Exec(`bunx pm2 start ${SCRIPT_PATH} --name ${PM2_NAME} --interpreter ${bunPath} -- monitor`);
|
|
41
47
|
return c.json(result);
|
|
42
48
|
});
|
|
43
49
|
monitorRoutes.post('/monitor/stop', (c) => {
|
|
44
|
-
const result = pm2Exec(
|
|
50
|
+
const result = pm2Exec(`bunx pm2 stop ${PM2_NAME}`);
|
|
45
51
|
return c.json(result);
|
|
46
52
|
});
|
|
47
53
|
monitorRoutes.post('/monitor/restart', (c) => {
|
|
48
|
-
const result = pm2Exec(
|
|
54
|
+
const result = pm2Exec(`bunx pm2 restart ${PM2_NAME}`);
|
|
49
55
|
return c.json(result);
|
|
50
56
|
});
|
|
51
57
|
export default monitorRoutes;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clocktopus",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"scripts": {
|
|
16
16
|
"build": "bunx tsc",
|
|
17
17
|
"prepublishOnly": "bunx tsc",
|
|
18
|
+
"postinstall": "cd node_modules/macos-notification-state && node-gyp rebuild 2>/dev/null; cd ../desktop-idle && node-gyp rebuild 2>/dev/null; true",
|
|
18
19
|
"lint": "eslint . --ext .ts",
|
|
19
20
|
"clock": "bun dist/index.js",
|
|
20
21
|
"clockd": "bunx pm2 start dist/index.js --name clocktopus --",
|
|
@@ -41,9 +42,9 @@
|
|
|
41
42
|
"inquirer": "^8.2.4",
|
|
42
43
|
"macos-notification-state": "^3.0.0",
|
|
43
44
|
"node-notifier": "^10.0.1",
|
|
45
|
+
"pm2": "^6.0.8",
|
|
44
46
|
"uuid": "^11.1.0",
|
|
45
|
-
"zod": "^3.25.76"
|
|
46
|
-
"pm2": "^6.0.8"
|
|
47
|
+
"zod": "^3.25.76"
|
|
47
48
|
},
|
|
48
49
|
"devDependencies": {
|
|
49
50
|
"@types/bun": "^1.3.11",
|