git-cracked 1.3.0 → 1.4.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.
Files changed (3) hide show
  1. package/README.md +93 -95
  2. package/package.json +1 -1
  3. package/src/index.js +84 -5
package/README.md CHANGED
@@ -1,26 +1,68 @@
1
+ <div align="center">
2
+
1
3
  # git-cracked
2
4
 
3
- Keep your GitHub contribution graph green automatically. Commits realistic-looking code changes to a private repo on a schedule completely free, no API key needed.
5
+ **Keep your GitHub contribution graph green — automatically.**
6
+
7
+ [![npm version](https://img.shields.io/npm/v/git-cracked?color=3fb950&label=npm)](https://www.npmjs.com/package/git-cracked)
8
+ [![node](https://img.shields.io/badge/node-18%2B-3fb950)](https://nodejs.org)
9
+ [![license](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
10
+ [![no api key](https://img.shields.io/badge/API%20key-not%20required-blue)](#)
11
+
12
+ [![stars](https://img.shields.io/github/stars/trentzx/git-cracked?style=flat&color=8b949e)](https://github.com/trentzx/git-cracked/stargazers)
13
+ [![forks](https://img.shields.io/github/forks/trentzx/git-cracked?style=flat&color=8b949e)](https://github.com/trentzx/git-cracked/network/members)
14
+ [![issues](https://img.shields.io/github/issues/trentzx/git-cracked?style=flat&color=f0a500)](https://github.com/trentzx/git-cracked/issues)
15
+ [![prs](https://img.shields.io/github/issues-pr/trentzx/git-cracked?style=flat&color=3fb950)](https://github.com/trentzx/git-cracked/pulls)
16
+
17
+ git-cracked makes small, realistic-looking code changes to a private repo on a
18
+ schedule and commits them for you — so your activity graph stays active without
19
+ you lifting a finger. Free, local, and no API key required.
20
+
21
+ </div>
22
+
23
+ <table>
24
+ <tr>
25
+ <td valign="top" width="50%">
26
+
27
+ **What it does**
28
+
29
+ - Commits on a schedule (e.g. 9am, 1pm, 4pm weekdays)
30
+ - Makes realistic code changes across 18 languages
31
+ - Generates matching commit messages
32
+ - Catches up missed commits after sleep/shutdown
33
+ - Pushes to your private repo automatically
34
+
35
+ </td>
36
+ <td valign="top" width="50%">
4
37
 
5
- ---
38
+ **What it uses**
6
39
 
7
- ## Quickstart
40
+ - Node.js (cross-platform: Win / macOS / Linux)
41
+ - `simple-git` for git operations
42
+ - `node-cron` for scheduling
43
+ - A built-in local web dashboard
44
+ - Zero external services or API keys
8
45
 
9
- ### You need
46
+ </td>
47
+ </tr>
48
+ </table>
10
49
 
11
- - [Node.js v18+](https://nodejs.org)
12
- - A GitHub account
13
- - A private repo cloned to your machine (with some source code files in it)
50
+ ## Quick Start
14
51
 
15
- ### One command
52
+ One command — it opens your browser to a 30-second setup form:
16
53
 
17
54
  ```bash
18
55
  npx git-cracked
19
56
  ```
20
57
 
21
- Your browser opens automatically. If this is your first time, you'll see a setup page fill in the path to your private repo and click save. That's it.
58
+ On the setup page, click **+** to browse for your private repo folder (or paste
59
+ the path), pick a schedule, and save. That's the whole install.
22
60
 
23
- ### Or install from source
61
+ > **You need:** Node.js 18+, a GitHub account, and a **private** repo cloned
62
+ > locally with a few source files in it. Don't have one?
63
+ > [Create one on GitHub](https://github.com/new).
64
+
65
+ ### Install from source instead
24
66
 
25
67
  ```bash
26
68
  git clone https://github.com/trentzx/git-cracked.git
@@ -29,40 +71,30 @@ npm install
29
71
  npm start
30
72
  ```
31
73
 
32
- ### Auto-start on boot *(so it keeps running after restarts)*
33
-
34
- From a source install:
74
+ ### Keep it running after reboots
35
75
 
36
76
  ```bash
37
- # Windows
38
- npm run install-windows
39
-
40
- # macOS
41
- npm run install-mac
42
-
43
- # Linux
44
- npm run install-linux
77
+ npm run install-windows # or: install-mac / install-linux
45
78
  ```
46
79
 
47
- ---
80
+ This registers git-cracked to start automatically on login and run quietly in
81
+ the background.
48
82
 
49
83
  ## Dashboard
50
84
 
51
- Once running, open **[http://localhost:4856](http://localhost:4856)** to see:
85
+ Once running, open **[localhost:4856](http://localhost:4856)** to see:
52
86
 
53
- - Total commits (all time + today)
54
- - Next scheduled commit times with countdown
55
- - Full commit history message, file changed, how long ago
56
- - **Commit Now** button to test instantly
57
- - Settings page to change your repo, schedule, or branch
87
+ - Total commits all time and today
88
+ - Next scheduled commit times with a live countdown
89
+ - Full commit history (message, file changed, when)
90
+ - A **⚡ Commit now** button to fire one instantly
91
+ - A **Settings** page to change repo, branch, or schedule
58
92
 
59
93
  The dashboard auto-refreshes every 30 seconds.
60
94
 
61
- ---
95
+ ## Schedule
62
96
 
63
- ## Changing the schedule
64
-
65
- Go to [http://localhost:4856/settings](http://localhost:4856/settings) and pick from the dropdown:
97
+ Change it any time on the [Settings page](http://localhost:4856/settings):
66
98
 
67
99
  | Option | Times |
68
100
  |---|---|
@@ -71,86 +103,52 @@ Go to [http://localhost:4856/settings](http://localhost:4856/settings) and pick
71
103
  | 4× per weekday | 9am, 12pm, 3pm, 6pm |
72
104
  | 1× per weekday | 10am |
73
105
 
74
- All times use your computer's local time zone, so it works the same anywhere in the world.
75
-
76
- ---
106
+ All times use your computer's local time zone, so it works the same anywhere in
107
+ the world. If your machine is asleep at a scheduled time, git-cracked commits as
108
+ soon as it wakes up so you don't miss a day.
77
109
 
78
110
  ## How it works
79
111
 
80
112
  1. At each scheduled time, a random source file in your repo is selected
81
- 2. A small, realistic change is applied — fixing whitespace, normalising quotes, adjusting a constant, sorting imports, etc.
82
- 3. A commit message is picked from a bank of 130+ realistic conventional commit messages that match the change type
83
- 4. The commit is pushed to your private repo automatically
113
+ 2. A small, realistic change is applied — whitespace, quote style, `let`→`const`,
114
+ strict equality, import sorting, an adjusted constant, etc.
115
+ 3. A matching message is chosen from a bank of 130+ conventional commit messages
116
+ 4. The change is committed and pushed to your private repo
84
117
 
85
- **Supported file types:** `.js` `.ts` `.jsx` `.tsx` `.mjs` `.py` `.go` `.java` `.rb` `.cs` `.cpp` `.c` `.rs` `.php` `.swift` `.kt` `.scala` `.sh`
118
+ **Supported file types:** `.js` `.ts` `.jsx` `.tsx` `.mjs` `.py` `.go` `.java`
119
+ `.rb` `.cs` `.cpp` `.c` `.rs` `.php` `.swift` `.kt` `.scala` `.sh`
86
120
 
87
- ---
88
-
89
- ## Stopping / removing
121
+ ## Show private commits on your graph
90
122
 
91
- **Kill the process** just close the terminal, or stop the background service:
123
+ Commits to private repos don't appear on your public graph by default. To count
124
+ them: profile → **Contribution settings** → enable **Private contributions**.
125
+ Visitors will see the activity, not the repo or code.
92
126
 
93
- **Windows** delete the startup file:
94
- ```
95
- del "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\git-cracked.vbs"
96
- ```
97
-
98
- **macOS:**
99
- ```bash
100
- launchctl unload ~/Library/LaunchAgents/com.gitcracked.autocommit.plist
101
- rm ~/Library/LaunchAgents/com.gitcracked.autocommit.plist
102
- ```
103
-
104
- **Linux:**
105
- ```bash
106
- systemctl --user disable --now git-cracked
107
- ```
127
+ ## Stopping / removing
108
128
 
109
- ---
129
+ | Platform | Command |
130
+ |---|---|
131
+ | Windows | `del "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\git-cracked.vbs"` |
132
+ | macOS | `launchctl unload ~/Library/LaunchAgents/com.gitcracked.autocommit.plist && rm ~/Library/LaunchAgents/com.gitcracked.autocommit.plist` |
133
+ | Linux | `systemctl --user disable --now git-cracked` |
110
134
 
111
135
  ## Troubleshooting
112
136
 
113
- **"No suitable files found to mutate"**
114
- Your private repo needs real source code files (`.js`, `.py`, `.ts`, etc.) that are at least 5 lines long and not minified.
115
-
116
- **Commits don't show on my GitHub graph**
117
- Make sure `git config user.email` in your private repo matches your GitHub account email:
118
- ```bash
119
- cd path/to/your/private/repo
120
- git config user.email "you@example.com"
121
- ```
137
+ **"No suitable files found to mutate"** — your repo needs real source files
138
+ (`.js`, `.py`, etc.) that are at least 5 lines long and not minified.
122
139
 
123
- **Push fails**
124
- You need GitHub credentials set up for HTTPS. Run `gh auth login` if you have the GitHub CLI, or set up SSH keys.
140
+ **Commits don't show on my graph** — make sure `git config user.email` in your
141
+ repo matches your GitHub account email, and enable private contributions (above).
125
142
 
126
- ---
143
+ **Push fails** — you need GitHub credentials for HTTPS. Run `gh auth login` or
144
+ set up SSH keys.
127
145
 
128
146
  ## Security
129
147
 
130
- - Your settings live in `~/.git-cracked/` on your machine and are never committed or uploaded
131
- - No data is sent anywhere commit messages are generated locally
148
+ - Settings live in `~/.git-cracked/` on your machine and are never uploaded
149
+ - The dashboard binds to localhost only and rejects cross-origin requests
132
150
  - The tool only touches files inside the repo path you configure
133
151
 
134
- ---
135
-
136
- ## Project structure
152
+ ## License
137
153
 
138
- ```
139
- git-cracked/
140
- ├── src/
141
- │ ├── cli.js Entry point — starts app and opens browser
142
- │ ├── index.js Scheduler
143
- │ ├── dashboard.js Web dashboard + setup wizard (port 4856)
144
- │ ├── committer.js Runs mutate → commit → push
145
- │ ├── mutator.js Applies realistic code changes
146
- │ ├── messages.js 130+ commit message bank
147
- │ ├── logger.js Saves activity to activity.json
148
- │ ├── config.js Loads and validates config.json
149
- │ └── setup.js CLI setup wizard (alternative to web UI)
150
- ├── scripts/
151
- │ ├── install-windows.js
152
- │ ├── install-mac.js
153
- │ └── install-linux.js
154
- ├── config.example.json
155
- └── package.json
156
- ```
154
+ MIT © [Trenton Scott](https://github.com/trentzx)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-cracked",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Auto-commits realistic-looking code changes to keep your GitHub green — free, no API key required",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/index.js CHANGED
@@ -3,6 +3,7 @@ import { existsSync } from 'fs';
3
3
  import { loadConfig } from './config.js';
4
4
  import { runCommit } from './committer.js';
5
5
  import { startDashboard } from './dashboard.js';
6
+ import { getActivity } from './logger.js';
6
7
  import { CONFIG_PATH } from './paths.js';
7
8
 
8
9
  const args = process.argv.slice(2);
@@ -21,13 +22,86 @@ if (runNow) {
21
22
  process.exit(0);
22
23
  }
23
24
 
25
+ // How often the catch-up checker runs (ms). Catches scheduled slots that were
26
+ // missed because the machine was asleep / shut down at the exact cron minute.
27
+ const CATCHUP_INTERVAL_MS = 15 * 60 * 1000;
28
+
24
29
  let scheduled = false;
30
+ let committing = false;
31
+ let activeConfig = null;
25
32
  const activeTasks = [];
33
+ let catchupTimer = null;
34
+
35
+ // Single-flight wrapper so the cron jobs and the catch-up checker can never
36
+ // run a commit at the same time (which would risk a double commit).
37
+ async function safeCommit(config, reason) {
38
+ if (committing) return;
39
+ committing = true;
40
+ try {
41
+ await runCommit(config);
42
+ } catch (err) {
43
+ console.error(`${reason} failed:`, err.message);
44
+ } finally {
45
+ committing = false;
46
+ }
47
+ }
48
+
49
+ // Parse a 5-field cron expression into { h, m, dows } for catch-up math.
50
+ // Returns null for expressions with ranges/lists in the minute or hour field,
51
+ // which the catch-up checker simply skips (the live cron job still covers them).
52
+ function parseExpr(expr) {
53
+ const parts = expr.trim().split(/\s+/);
54
+ if (parts.length !== 5) return null;
55
+ const [min, hour, , , dow] = parts;
56
+ const m = parseInt(min, 10);
57
+ const h = parseInt(hour, 10);
58
+ if (Number.isNaN(m) || Number.isNaN(h)) return null;
59
+
60
+ const dows = new Set();
61
+ if (dow === '*') {
62
+ for (let i = 0; i <= 6; i++) dows.add(i);
63
+ } else {
64
+ for (const p of dow.split(',')) {
65
+ if (p.includes('-')) {
66
+ const [a, b] = p.split('-').map(Number);
67
+ for (let i = a; i <= b; i++) dows.add(i % 7);
68
+ } else {
69
+ dows.add(Number(p) % 7);
70
+ }
71
+ }
72
+ }
73
+ return { h, m, dows };
74
+ }
75
+
76
+ // If a scheduled slot has already passed today (on a matching weekday) and no
77
+ // commit has happened since, commit once to catch up.
78
+ async function checkMissedCommits(config) {
79
+ const now = new Date();
80
+ let latestPassed = null;
81
+
82
+ for (const expr of config.schedule) {
83
+ const p = parseExpr(expr);
84
+ if (!p || !p.dows.has(now.getDay())) continue;
85
+ const slot = new Date(now);
86
+ slot.setHours(p.h, p.m, 0, 0);
87
+ if (slot <= now && (!latestPassed || slot > latestPassed)) latestPassed = slot;
88
+ }
89
+
90
+ if (!latestPassed) return; // nothing scheduled has passed today
91
+
92
+ const commits = getActivity().commits;
93
+ const last = commits[0] ? new Date(commits[0].timestamp) : null;
94
+ if (last && last >= latestPassed) return; // already committed since that slot
95
+
96
+ console.log(`[${now.toISOString()}] Catching up missed scheduled commit`);
97
+ await safeCommit(config, 'Catch-up commit');
98
+ }
26
99
 
27
100
  function startSchedule(config) {
28
101
  // Replace any previously registered jobs (e.g. after a settings change)
29
102
  for (const task of activeTasks) task.stop();
30
103
  activeTasks.length = 0;
104
+ activeConfig = config;
31
105
 
32
106
  for (const expression of config.schedule) {
33
107
  if (!cron.validate(expression)) {
@@ -36,16 +110,21 @@ function startSchedule(config) {
36
110
  }
37
111
  const task = cron.schedule(expression, async () => {
38
112
  console.log(`[${new Date().toISOString()}] Cron triggered`);
39
- try {
40
- await runCommit(config);
41
- } catch (err) {
42
- console.error('Commit failed:', err.message);
43
- }
113
+ await safeCommit(config, 'Scheduled commit');
44
114
  });
45
115
  activeTasks.push(task);
46
116
  }
117
+
47
118
  scheduled = true;
48
119
  console.log('Schedule active:', config.schedule.join(', '));
120
+
121
+ // Catch up anything missed while the machine was off, then poll periodically.
122
+ checkMissedCommits(config);
123
+ if (!catchupTimer) {
124
+ catchupTimer = setInterval(() => {
125
+ if (activeConfig) checkMissedCommits(activeConfig);
126
+ }, CATCHUP_INTERVAL_MS);
127
+ }
49
128
  }
50
129
 
51
130
  console.log('Git Cracked running.');