claude-lock 0.1.0 → 0.2.1

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
@@ -5,22 +5,14 @@ Lock yourself out of the `claude` CLI. Think Cold Turkey / Screen Time, but for
5
5
  > Claude Code is addictive. You start a quick session, then suddenly it's midnight and you cancelled dinner with friends because you just had to ship one more feature. cc-lock gives you a hard stop — set a limit before you open it, and let it hold the line when you won't.
6
6
 
7
7
  ```
8
- ___________
9
- / _________ \
10
- | | | |
11
- | | | |
12
- ____|_|_________|_|___
13
- | |
14
- | ██████╗ ██████╗ |
15
- | ██╔═══╝ ██╔═══╝ |
16
- | ██║ ██║ |
17
- | ██║ ██║ |
18
- | ██████╗ ██████╗ |
19
- | ╚═════╝ ╚═════╝ |
20
- | L O C K |
21
- |______________________|
22
- | O O O O |
23
- |______________|
8
+ ╭──────╮
9
+ │ │
10
+ ╔═══╧══════╧═══╗
11
+ ║ ║
12
+ ║ cc · lock ║
13
+ ║ ║
14
+ ║ ○ ○ ○ ○ ║
15
+ ╚══════════════╝
24
16
  ```
25
17
 
26
18
  ## How it works
@@ -49,7 +41,7 @@ Each unlock attempt during a lock period gets progressively harder:
49
41
  | 4 | 120s cooldown, then write a 50-word justification |
50
42
  | 5+ | 300s cooldown + 5 math problems + 80-char string backwards |
51
43
 
52
- Successful bypass grants a **15-minute grace window**, then the lock re-engages.
44
+ Successful bypass grants a **10-minute grace window** (configurable), then the lock re-engages.
53
45
 
54
46
  ### Payment bypass
55
47
 
@@ -101,7 +93,7 @@ When hard-locked, `cc-lock unlock` will refuse and the shim shows "Hard lock is
101
93
  ### npm (recommended)
102
94
 
103
95
  ```bash
104
- npm install -g claude-lock
96
+ npm install -g cc-lock
105
97
  cc-lock install
106
98
  ```
107
99
 
@@ -218,7 +210,7 @@ cc-lock uninstall
218
210
 
219
211
  | Key | Type | Default | Description |
220
212
  |-----|------|---------|-------------|
221
- | `graceMinutes` | integer (1–120) | `5` | How long the grace period lasts after a successful bypass before the lock re-engages |
213
+ | `graceMinutes` | integer (1–120) | `10` | How long the grace period lasts after a successful bypass before the lock re-engages |
222
214
  | `chmodGuard` | boolean | `false` | Removes write permission from the shim so it can't be trivially replaced |
223
215
  | `weekendDays` | `sat-sun` \| `fri-sat` \| `0,6` | `sat-sun` | Which days count as "weekend" for weekend-type schedules |
224
216
  | `challengeBypassEnabled` | boolean | `true` | Allow free challenge-based bypass. Set to `false` to require payment (or block bypass entirely if no payment method is configured) |
@@ -242,6 +234,8 @@ $ claude
242
234
 
243
235
  🔒 Claude Code is locked by cc-lock
244
236
 
237
+ The shim script has more self-control than you do.
238
+
245
239
  Lock expires at: 18:43:24
246
240
  Bypass attempts this period: 0
247
241
 
@@ -255,6 +249,8 @@ $ claude
255
249
 
256
250
  🔒 Claude Code is locked by cc-lock
257
251
 
252
+ Your future self is sighing right now.
253
+
258
254
  Lock expires at: 18:43:24
259
255
  Hard lock is active — bypass is not allowed.
260
256
  Wait for the lock to expire.
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+
3
+ // ../core/dist/index.js
4
+ import { homedir } from "os";
5
+ import { join } from "path";
6
+ var CC_LOCK_DIR = join(homedir(), ".cc-lock");
7
+ var STATE_FILE = join(CC_LOCK_DIR, "state.json");
8
+ var CONFIG_FILE = join(CC_LOCK_DIR, "config.json");
9
+ var DB_FILE = join(CC_LOCK_DIR, "stats.db");
10
+ var SOCKET_PATH = process.platform === "win32" ? "\\\\.\\pipe\\cc-lock" : "/tmp/cc-lock.sock";
11
+ var PID_FILE = join(CC_LOCK_DIR, "daemon.pid");
12
+ var CLAUDE_STANDALONE_BIN = join(homedir(), ".local", "bin", "claude");
13
+ var CLAUDE_STANDALONE_VERSIONS_DIR = join(
14
+ homedir(),
15
+ ".local",
16
+ "share",
17
+ "claude",
18
+ "versions"
19
+ );
20
+ var LAUNCHD_PLIST_PATH = join(
21
+ homedir(),
22
+ "Library",
23
+ "LaunchAgents",
24
+ "com.cc-lock.daemon.plist"
25
+ );
26
+ var LAUNCHD_LABEL = "com.cc-lock.daemon";
27
+ var TASK_SCHEDULER_NAME = "cc-lock-daemon";
28
+
29
+ export {
30
+ CC_LOCK_DIR,
31
+ SOCKET_PATH,
32
+ LAUNCHD_PLIST_PATH,
33
+ LAUNCHD_LABEL,
34
+ TASK_SCHEDULER_NAME
35
+ };
36
+ //# sourceMappingURL=chunk-GSDKZKKT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../core/src/constants.ts","../../core/src/challenges.ts"],"sourcesContent":["import { homedir } from \"os\";\nimport { join } from \"path\";\n\nexport const CC_LOCK_DIR = join(homedir(), \".cc-lock\");\nexport const STATE_FILE = join(CC_LOCK_DIR, \"state.json\");\nexport const CONFIG_FILE = join(CC_LOCK_DIR, \"config.json\");\nexport const DB_FILE = join(CC_LOCK_DIR, \"stats.db\");\nexport const SOCKET_PATH =\n process.platform === \"win32\" ? \"\\\\\\\\.\\\\pipe\\\\cc-lock\" : \"/tmp/cc-lock.sock\";\nexport const PID_FILE = join(CC_LOCK_DIR, \"daemon.pid\");\n\nexport const CLAUDE_STANDALONE_BIN = join(homedir(), \".local\", \"bin\", \"claude\");\nexport const CLAUDE_STANDALONE_VERSIONS_DIR = join(\n homedir(),\n \".local\",\n \"share\",\n \"claude\",\n \"versions\"\n);\n\nexport const LAUNCHD_PLIST_PATH = join(\n homedir(),\n \"Library\",\n \"LaunchAgents\",\n \"com.cc-lock.daemon.plist\"\n);\nexport const LAUNCHD_LABEL = \"com.cc-lock.daemon\";\nexport const TASK_SCHEDULER_NAME = \"cc-lock-daemon\";\n\nexport const DEFAULT_GRACE_MINUTES = 5;\nexport const BYPASS_COOLDOWNS = [0, 60, 0, 120, 300]; // seconds per attempt\nexport const PROCESS_POLL_INTERVAL_MS = 10_000;\nexport const VERSION_WATCH_DEBOUNCE_MS = 2_000;\n","import { randomBytes } from \"crypto\";\nimport type { Challenge } from \"./types.js\";\nimport { BYPASS_COOLDOWNS } from \"./constants.js\";\n\nfunction randomString(length: number): string {\n const chars =\n \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%&*\";\n const bytes = randomBytes(length);\n return Array.from(bytes)\n .map((b: number) => chars[b % chars.length])\n .join(\"\");\n}\n\nfunction randomMathProblem(): { prompt: string; answer: string } {\n const ops = [\n { sym: \"*\", fn: (a: number, b: number) => a * b },\n { sym: \"+\", fn: (a: number, b: number) => a + b },\n { sym: \"-\", fn: (a: number, b: number) => a - b },\n ];\n const op = ops[Math.floor(Math.random() * ops.length)]!;\n const a = Math.floor(Math.random() * 900) + 100;\n const b = Math.floor(Math.random() * 90) + 10;\n return {\n prompt: `${a} ${op.sym} ${b}`,\n answer: String(op.fn(a, b)),\n };\n}\n\nexport function generateChallenges(attemptNumber: number): Challenge[] {\n const cooldown =\n BYPASS_COOLDOWNS[Math.min(attemptNumber - 1, BYPASS_COOLDOWNS.length - 1)]!;\n\n if (attemptNumber === 1) {\n return [\n {\n type: \"typing\",\n prompt: randomString(30),\n cooldownSeconds: cooldown,\n },\n ];\n }\n\n if (attemptNumber === 2) {\n return [\n {\n type: \"typing\",\n prompt: randomString(50),\n cooldownSeconds: cooldown,\n },\n ];\n }\n\n if (attemptNumber === 3) {\n const problems = Array.from({ length: 3 }, () => {\n const { prompt, answer } = randomMathProblem();\n return { type: \"math\" as const, prompt, answer, cooldownSeconds: 0 };\n });\n return [{ type: \"cooldown\", prompt: \"\", cooldownSeconds: cooldown }, ...problems];\n }\n\n if (attemptNumber === 4) {\n return [\n {\n type: \"justification\",\n prompt:\n \"Write a 50+ word justification for why you need to use Claude right now:\",\n cooldownSeconds: cooldown,\n },\n ];\n }\n\n // 5+: everything\n const problems = Array.from({ length: 5 }, () => {\n const { prompt, answer } = randomMathProblem();\n return { type: \"math\" as const, prompt, answer, cooldownSeconds: 0 };\n });\n return [\n { type: \"cooldown\", prompt: \"\", cooldownSeconds: cooldown },\n ...problems,\n {\n type: \"typing\",\n prompt: randomString(80),\n cooldownSeconds: 0,\n },\n ];\n}\n"],"mappings":";;;AAAA,SAAS,eAAe;AACxB,SAAS,YAAY;AAEd,IAAM,cAAc,KAAK,QAAQ,GAAG,UAAU;AAC9C,IAAM,aAAa,KAAK,aAAa,YAAY;AACjD,IAAM,cAAc,KAAK,aAAa,aAAa;AACnD,IAAM,UAAU,KAAK,aAAa,UAAU;AAC5C,IAAM,cACX,QAAQ,aAAa,UAAU,yBAAyB;AACnD,IAAM,WAAW,KAAK,aAAa,YAAY;AAE/C,IAAM,wBAAwB,KAAK,QAAQ,GAAG,UAAU,OAAO,QAAQ;AACvE,IAAM,iCAAiC;EAC5C,QAAQ;EACR;EACA;EACA;EACA;AACF;AAEO,IAAM,qBAAqB;EAChC,QAAQ;EACR;EACA;EACA;AACF;AACO,IAAM,gBAAgB;AACtB,IAAM,sBAAsB;","names":[]}