cc-caffeine 0.2.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.
@@ -0,0 +1,70 @@
1
+ {
2
+ "hooks": {
3
+ "UserPromptSubmit": [
4
+ {
5
+ "matcher": "*",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "npx cc-caffeine caffeinate"
10
+ }
11
+ ]
12
+ }
13
+ ],
14
+ "PreToolUse": [
15
+ {
16
+ "matcher": "*",
17
+ "hooks": [
18
+ {
19
+ "type": "command",
20
+ "command": "npx cc-caffeine caffeinate"
21
+ }
22
+ ]
23
+ }
24
+ ],
25
+ "PostToolUse": [
26
+ {
27
+ "matcher": "*",
28
+ "hooks": [
29
+ {
30
+ "type": "command",
31
+ "command": "npx cc-caffeine caffeinate"
32
+ }
33
+ ]
34
+ }
35
+ ],
36
+ "Notification": [
37
+ {
38
+ "matcher": "*",
39
+ "hooks": [
40
+ {
41
+ "type": "command",
42
+ "command": "npx cc-caffeine uncaffeinate"
43
+ }
44
+ ]
45
+ }
46
+ ],
47
+ "Stop": [
48
+ {
49
+ "matcher": "*",
50
+ "hooks": [
51
+ {
52
+ "type": "command",
53
+ "command": "npx cc-caffeine uncaffeinate"
54
+ }
55
+ ]
56
+ }
57
+ ],
58
+ "SessionEnd": [
59
+ {
60
+ "matcher": "*",
61
+ "hooks": [
62
+ {
63
+ "type": "command",
64
+ "command": "npx cc-caffeine uncaffeinate"
65
+ }
66
+ ]
67
+ }
68
+ ]
69
+ }
70
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "cc-caffeine",
3
+ "description": "Prevents your computer from sleeping while Claude Code works hard",
4
+ "version": "0.2.0",
5
+ "author": {
6
+ "name": "Samuel Berthe",
7
+ "email": "hey@samuel-berthe.fr"
8
+ },
9
+ "homepage": "https://github.com/samber/cc-caffeine",
10
+ "repository": "https://github.com/samber/cc-caffeine",
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "claude-code",
14
+ "claude-code-plugin",
15
+ "plugin",
16
+ "nap",
17
+ "sleep",
18
+ "sleep-prevention",
19
+ "caffeine",
20
+ "caffeinate",
21
+ "system-tray"
22
+ ]
23
+ }
package/.eslintrc.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "env": {
3
+ "browser": true,
4
+ "es2021": true,
5
+ "node": true
6
+ },
7
+ "extends": [
8
+ "eslint:recommended"
9
+ ],
10
+ "parserOptions": {
11
+ "ecmaVersion": "latest",
12
+ "sourceType": "module"
13
+ },
14
+ "rules": {
15
+ "indent": ["error", 2],
16
+ "linebreak-style": ["error", "unix"],
17
+ "quotes": ["error", "single"],
18
+ "semi": ["error", "always"],
19
+ "no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
20
+ "no-console": "off",
21
+ "prefer-const": "error",
22
+ "no-var": "error",
23
+ "object-shorthand": "error",
24
+ "prefer-arrow-callback": "error",
25
+ "arrow-spacing": "error",
26
+ "comma-dangle": ["error", "never"],
27
+ "eol-last": "error",
28
+ "no-trailing-spaces": "error",
29
+ "space-before-blocks": "error",
30
+ "keyword-spacing": "error",
31
+ "space-infix-ops": "error",
32
+ "no-multiple-empty-lines": ["error", { "max": 2 }],
33
+ "brace-style": ["error", "1tbs"],
34
+ "curly": "error"
35
+ }
36
+ }
@@ -0,0 +1 @@
1
+ github: [samber]
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: npm
4
+ directory: /
5
+ schedule:
6
+ interval: monthly
@@ -0,0 +1,79 @@
1
+ name: CI Checks
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ node-version:
15
+ - 14.x
16
+ - 16.x
17
+ - 18.x
18
+ - 20.x
19
+ - 22.x
20
+
21
+ steps:
22
+ - name: Checkout code
23
+ uses: actions/checkout@v4
24
+
25
+ - name: Setup Node.js ${{ matrix.node-version }}
26
+ uses: actions/setup-node@v4
27
+ with:
28
+ node-version: ${{ matrix.node-version }}
29
+ cache: 'npm'
30
+
31
+ - name: Install dependencies
32
+ run: npm install
33
+
34
+ - name: Check version numbers match
35
+ run: |
36
+ # Extract version from package.json
37
+ PACKAGE_VERSION=$(node -p "require('./package.json').version")
38
+ echo "Package version: $PACKAGE_VERSION"
39
+
40
+ # Extract version from plugin.json
41
+ if [ -f ".claude-plugin/plugin.json" ]; then
42
+ PLUGIN_VERSION=$(node -p "require('./.claude-plugin/plugin.json').version")
43
+ echo "Plugin version: $PLUGIN_VERSION"
44
+
45
+ # Check if versions match
46
+ if [ "$PACKAGE_VERSION" != "$PLUGIN_VERSION" ]; then
47
+ echo "❌ Version mismatch detected!"
48
+ echo "Package version: $PACKAGE_VERSION"
49
+ echo "Plugin version: $PLUGIN_VERSION"
50
+ exit 1
51
+ else
52
+ echo "✅ Versions match: $PACKAGE_VERSION"
53
+ fi
54
+ else
55
+ echo "⚠️ Warning: .claude-plugin/plugin.json not found"
56
+ exit 1
57
+ fi
58
+
59
+ - name: Test version command
60
+ run: |
61
+ # Test that our version command works correctly
62
+ node caffeine.js version
63
+
64
+ - name: Test other commands (syntax check)
65
+ run: |
66
+ # Test that other commands don't have syntax errors
67
+ node caffeine.js --help || true
68
+
69
+ - name: Run linting (if available)
70
+ run: npm run lint || echo "⚠️ Linting skipped (not configured)"
71
+
72
+ - name: Run formatting check (if available)
73
+ run: |
74
+ if command -v prettier &> /dev/null; then
75
+ npm run format
76
+ git diff --exit-code || echo "⚠️ Code formatting changes detected"
77
+ else
78
+ echo "⚠️ Formatting check skipped (prettier not available)"
79
+ fi
package/.prettierrc ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "semi": true,
3
+ "trailingComma": "none",
4
+ "singleQuote": true,
5
+ "printWidth": 100,
6
+ "tabWidth": 2,
7
+ "useTabs": false,
8
+ "bracketSpacing": true,
9
+ "arrowParens": "avoid",
10
+ "endOfLine": "lf"
11
+ }
package/CLAUDE.md ADDED
@@ -0,0 +1,307 @@
1
+ # CC-Caffeine: Claude Code Sleep Prevention System
2
+
3
+ A Node.js/Electron script that prevents your computer from going to sleep while using Claude Code through system tray integration and session management.
4
+
5
+ ## Architecture
6
+
7
+ The system consists of a modular architecture with the following components:
8
+
9
+ ### Core Modules
10
+
11
+ 1. **caffeine.js** - Main entry point that orchestrates all modules and handles command routing
12
+ 2. **src/commands.js** - Handles command-line interface functionality and process management
13
+ 3. **src/session.js** - Manages session persistence with file locking and timeout handling
14
+ 4. **src/server.js** - Handles server process management and Electron integration
15
+ 5. **src/system-tray.js** - Manages system tray functionality and sleep prevention
16
+ 6. **src/electron.js** - Wraps Electron-specific functionality and provides cross-platform support
17
+
18
+ ### User Commands
19
+
20
+ 1. **caffeinate command** - Adds session to JSON file and ensures server is running
21
+ 2. **uncaffeinate command** - Removes session from JSON file
22
+ 3. **server command** - Starts Electron system tray application that polls JSON file for active sessions
23
+ 4. **version command** - Shows version information from package.json and plugin.json
24
+
25
+ ## Features
26
+
27
+ - Cross-platform support (Linux, macOS, Windows)
28
+ - Headless Electron system tray (no windows, only system tray)
29
+ - JSON file for session persistence with proper-lockfile for concurrency
30
+ - Automatic session timeout (15 minutes of inactivity)
31
+ - Auto-server startup when not running
32
+ - Multiple concurrent session support
33
+ - Real-time status monitoring
34
+ - Lightweight client commands (no Electron dependency for caffeinate/uncaffeinate)
35
+ - Native sleep prevention using Electron's powerSaveBlocker API
36
+ - Hidden from macOS dock using app.dock.hide()
37
+
38
+ ## Technical Stack
39
+
40
+ - **Node.js 14+** - Runtime environment with modern JavaScript features
41
+ - **Electron 28+** - Cross-platform desktop application framework
42
+ - **proper-lockfile** - File locking for all concurrent access with retry logic
43
+ - **Electron powerSaveBlocker** - Native cross-platform sleep prevention
44
+ - **Electron Tray/Menu** - System tray functionality
45
+ - **JSON file** - Session storage and communication
46
+ - **setInterval** - Background polling for session changes
47
+
48
+ ## Commands Usage
49
+
50
+ ### caffeinate
51
+ Enables sleep prevention for the current session (lightweight, no system tray).
52
+ ```bash
53
+ node caffeine.js caffeinate
54
+ # or
55
+ npm run caffeinate
56
+ ```
57
+ Accepts JSON via stdin with session_id:
58
+ ```json
59
+ {"session_id": "abc123"}
60
+ ```
61
+
62
+ ### uncaffeinate
63
+ Disables sleep prevention for the current session (lightweight, no system tray).
64
+ ```bash
65
+ node caffeine.js uncaffeinate
66
+ # or
67
+ npm run uncaffeinate
68
+ ```
69
+ Accepts JSON via stdin with session_id:
70
+ ```json
71
+ {"session_id": "abc123"}
72
+ ```
73
+
74
+ ### server
75
+ Starts the headless Electron caffeine server with system tray only.
76
+ ```bash
77
+ node caffeine.js server
78
+ # or
79
+ npm run server
80
+ # or
81
+ npm start
82
+ ```
83
+
84
+ **Cross-platform background operation:**
85
+ ```bash
86
+ npm run server # Completely headless - no windows, only system tray
87
+ ```
88
+
89
+ ### version
90
+ Shows version information from both package.json and .claude-plugin/plugin.json.
91
+ ```bash
92
+ node caffeine.js version
93
+ # or
94
+ npm run version
95
+ ```
96
+
97
+ Output example:
98
+ ```
99
+ === CC-Caffeine Version ===
100
+ Package version: 0.1.1
101
+ Plugin version: 0.1.1
102
+ ```
103
+
104
+ ## Installation & Setup
105
+
106
+ 1. Install Node.js dependencies:
107
+ ```bash
108
+ npm install
109
+ ```
110
+
111
+ 2. Create config directory:
112
+ ```bash
113
+ mkdir -p ~/.claude/plugins/cc-caffeine
114
+ ```
115
+
116
+ 3. Make the script executable (optional):
117
+ ```bash
118
+ chmod +x caffeine.js
119
+ ```
120
+
121
+ 4. Configure Claude Code hooks (example):
122
+ ```json
123
+ {
124
+ "hooks": {
125
+ "UserPromptSubmit": [
126
+ {
127
+ "hooks": [
128
+ {
129
+ "type": "command",
130
+ "command": "node /path/to/caffeine.js caffeinate"
131
+ }
132
+ ]
133
+ }
134
+ ],
135
+ "Stop": [
136
+ {
137
+ "hooks": [
138
+ {
139
+ "type": "command",
140
+ "command": "node /path/to/caffeine.js uncaffeinate"
141
+ }
142
+ ]
143
+ }
144
+ ]
145
+ }
146
+ }
147
+ ```
148
+
149
+ Note: The server will be auto-started by the caffeinate command when needed.
150
+
151
+ ## JSON File Structure
152
+
153
+ JSON file located at: `~/.claude/plugins/cc-caffeine/sessions.json`
154
+
155
+ ```json
156
+ {
157
+ "sessions": {
158
+ "session_id_abc123": {
159
+ "created_at": "2025-01-08T10:30:00.000Z",
160
+ "last_activity": "2025-01-08T10:45:00.000Z"
161
+ }
162
+ },
163
+ "last_updated": "2025-01-08T10:45:00.000Z"
164
+ }
165
+ ```
166
+
167
+ Sessions are removed automatically after 15 minutes of inactivity.
168
+
169
+ ## File Concurrency
170
+
171
+ - **proper-lockfile** ensures atomic read/write operations
172
+ - File locking prevents corruption when multiple processes access simultaneously
173
+ - Short lock duration - Lock only held during actual read/write operations
174
+ - Built-in retry mechanism with configurable timeout
175
+ - Cross-platform file locking using OS primitives
176
+ - Atomic session operations (add/remove) within single lock to prevent race conditions
177
+
178
+ ## Session Management
179
+
180
+ - Sessions auto-expire after 15 minutes of inactivity
181
+ - Automatic cleanup of expired sessions during every add/remove operation
182
+ - Server polls JSON file every 10 seconds for active sessions (with file locking)
183
+ - Multiple sessions can be active simultaneously
184
+ - Sleep prevention is active when at least one session is active
185
+ - Commands auto-start server if not running
186
+ - Only server command loads Electron system tray (lightweight client commands)
187
+ - All session operations are atomic within file locks to prevent corruption
188
+ - Session timestamps: `created_at` preserved, `last_activity` updated on subsequent calls
189
+ - All JSON file operations (read/write) are protected with proper-lockfile
190
+ - Client commands (caffeinate/uncaffeinate) work without Electron dependency
191
+
192
+ ## System Tray
193
+
194
+ - Headless Electron application - no windows ever created
195
+ - Shows custom icon when caffeinated/inactive
196
+ - Context menu with Exit button
197
+ - Hidden from macOS dock using `app.dock.hide()`
198
+ - Cross-platform system tray support
199
+
200
+ ## Running Without Console Window
201
+
202
+ The Electron server is completely headless:
203
+
204
+ ```bash
205
+ # Start headless server (no windows, only system tray)
206
+ npm run server
207
+ # or
208
+ npm start
209
+ ```
210
+
211
+ ### Platform-Specific Background Operation:
212
+
213
+ **macOS:**
214
+ - Hidden from dock using `app.dock.hide()`
215
+ - System tray only operation
216
+ - Native sleep prevention
217
+
218
+ **Windows/Linux:**
219
+ - Background process with system tray
220
+ - No console windows created
221
+ - Native sleep prevention
222
+
223
+ ## Development Scripts
224
+
225
+ Additional npm scripts for development:
226
+
227
+ ```bash
228
+ npm run version # Show version information from package.json and plugin.json
229
+ npm run lint # Run ESLint (if installed)
230
+ npm run format # Format code with Prettier (if installed)
231
+ ```
232
+
233
+ ## Module Import Structure
234
+
235
+ The application uses CommonJS modules with clear dependency hierarchy:
236
+
237
+ - `caffeine.js` imports from `src/commands.js` and `src/server.js`
238
+ - `src/commands.js` imports from `src/session.js`
239
+ - `src/server.js` imports from `src/session.js`, `src/system-tray.js`, and `src/electron.js`
240
+ - `src/system-tray.js` imports from `src/session.js` and `src/electron.js`
241
+ - `src/electron.js` provides Electron functionality on-demand
242
+
243
+ ## Sleep Prevention
244
+
245
+ - Uses **Electron's powerSaveBlocker** for cross-platform sleep prevention
246
+ - `powerSaveBlocker.start('prevent-app-suspension')` blocks system sleep and app suspension
247
+ - Automatically activates when sessions are active
248
+ - Gracefully releases sleep prevention on shutdown
249
+ - Works on Windows, macOS, and Linux
250
+
251
+ ## File Structure
252
+
253
+ ```
254
+ caffeine.js - Main entry point and command routing
255
+ src/
256
+ └── commands.js - Command-line interface and process management
257
+ └── session.js - Session persistence and file locking
258
+ └── server.js - Server process management and Electron integration
259
+ └── system-tray.js - System tray functionality and sleep prevention
260
+ └── electron.js - Electron-specific functionality wrapper
261
+ package.json - Node.js dependencies and scripts
262
+ icon-coffee-full.png - Active caffeine icon (PNG)
263
+ icon-coffee-empty.png- Inactive caffeine icon (PNG)
264
+ icon-coffee-full.svg - Active caffeine icon (SVG)
265
+ icon-coffee-empty.svg- Inactive caffeine icon (SVG)
266
+ ~/.claude/plugins/cc-caffeine/
267
+ └── sessions.json - JSON file with session data
268
+ ```
269
+
270
+ **Modular architecture benefits:**
271
+ - Separation of concerns for better maintainability
272
+ - Individual modules can be tested independently
273
+ - Clear separation between Electron-dependent and lightweight client code
274
+ - Easier to extend and modify specific functionality
275
+ - Better code organization and readability
276
+
277
+ ## Error Handling
278
+
279
+ - Graceful server startup fallback if Electron unavailable
280
+ - JSON file read/write error recovery with proper-lockfile
281
+ - All operations protected by file locks to prevent race conditions
282
+ - Atomic session operations prevent data corruption during concurrent access
283
+ - Session cleanup on process termination
284
+ - Cross-platform path handling using Node.js path module
285
+ - Lock timeout handling with proper error messages
286
+ - Automatic expired session cleanup during every operation
287
+ - Proper powerSaveBlocker cleanup on server shutdown
288
+ - Graceful error handling for missing Electron APIs
289
+
290
+ ## Cross-platform
291
+
292
+ - Native MacOS/Windows/Linxe sleep prevention via Electron
293
+ - Compatible with OS security permissions and system tray
294
+ - Background process
295
+
296
+ ## Security Considerations
297
+
298
+ - Session validation and timeout protection
299
+ - No external network connections required
300
+ - File access restricted to user's home directory
301
+ - Process isolation between client commands and Electron server
302
+
303
+ ## Performance Considerations
304
+
305
+ - Minimal memory footprint
306
+ - Efficient polling with 5-second intervals
307
+ - Fast startup time (< 1 seconds for Electron)
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Samuel Berthe
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.