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 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 (Dashboard User)
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
- ### Install
13
+ ### Prerequisites
14
+
15
+ [Bun](https://bun.sh) is required (used as the runtime):
14
16
 
15
17
  ```bash
16
- npm i -g clocktopus
18
+ curl -fsSL https://bun.sh/install | bash
17
19
  ```
18
20
 
19
- Requires [Bun](https://bun.sh) runtime:
21
+ ### Install
20
22
 
21
23
  ```bash
22
- curl -fsSL https://bun.sh/install | bash
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
- ### Dashboard Commands
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
- ## Power User Guide
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 Development
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 first
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 (`data/sessions.db`) and managed through the dashboard Settings tab. No `.env` file is needed.
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
- #### OAuth Architecture
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
- Power users can override credentials via environment variables or a `.env` file:
122
+ ### Project Structure
198
123
 
199
124
  ```
200
- CLOCKIFY_API_KEY="your_key"
201
- ATLASSIAN_CLIENT_ID="your_id"
202
- ATLASSIAN_CLIENT_SECRET="your_secret"
203
- GOOGLE_CLIENT_ID="your_id"
204
- GOOGLE_CLIENT_SECRET="your_secret"
205
- ```
206
-
207
- The app checks the database first, then falls back to environment variables.
208
-
209
- ### Local Project Filtering (CLI only)
210
-
211
- On first `clocktopus start`, all projects are saved to `data/local-projects.json`. Edit this file to keep only your frequently used projects:
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** (or your terminal app) has notifications enabled.
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
- The idle monitor detects screen lock and system idle (5 min). If your Mac's display turns off without locking, enable **Require password immediately** in System Settings > Lock Screen.
149
+ Enable **Require password immediately** in System Settings > Lock Screen.
252
150
 
253
- ### Linux Requirements
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 clocktopus = processes.find((p) => p.name === 'clocktopus');
24
- if (!clocktopus) {
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: clocktopus.pm2_env.status === 'online',
29
- status: clocktopus.pm2_env.status,
30
- uptime: clocktopus.pm2_env.pm_uptime,
31
- restarts: clocktopus.pm2_env.restart_time,
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
- const result = pm2Exec(`bunx pm2 start ${SCRIPT_PATH} --name clocktopus --interpreter ${bunPath} -- monitor`);
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('bunx pm2 stop clocktopus');
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('bunx pm2 restart clocktopus');
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.5",
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",