gitwrit 0.2.7 → 0.2.9

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
@@ -4,7 +4,7 @@
4
4
 
5
5
  Made for `git`-ters and `writ`-ters.
6
6
 
7
- **gitwrit** watches your Markdown files and quietly commits and pushes them to your Git repository no manual `git add`, no `git commit`, no `git push`. You write. gitwrit handles the rest.
7
+ **gitwrit** watches your Markdown files and quietly commits and pushes them to your Git repository—no manual `git add`, no `git commit`, no `git push`. You write. gitwrit handles the rest.
8
8
 
9
9
  It is built for engineers writing internal specs, researchers building private knowledge bases, AI practitioners documenting models and experiments, and anyone who wants the safety of version control without the overhead of Git discipline. Your files stay in your own repository, on your own terms—not in someone else's cloud.
10
10
 
@@ -99,9 +99,9 @@ Run `gitwrit config` from inside a watched directory to set local overrides. Ove
99
99
 
100
100
  gitwrit supports two branch modes, configurable globally or per directory.
101
101
 
102
- **`current`** — Commits to whatever branch you currently have checked out. Switch branches freely; gitwrit follows you.
102
+ **`current`**—Commits to whatever branch you currently have checked out. Switch branches freely; gitwrit follows you.
103
103
 
104
- **`autogenerated`** — Creates a fresh named branch at the start of each session. Branch names are generated by combining a random adjective, noun, and verb like `crimson-walrus-stumbling` or `teal-fox-bouncing`. 64,000 possible combinations. Good for keeping autosave history separate from your main branch.
104
+ **`autogenerated`**—Creates a fresh named branch at the start of each session. Branch names are generated by combining a random adjective, noun, and verb—like `crimson-walrus-stumbling` or `teal-fox-bouncing`. 64,000 possible combinations. Good for keeping autosave history separate from your main branch.
105
105
 
106
106
  ---
107
107
 
@@ -113,16 +113,51 @@ gitwrit checks for updates automatically after every command. If a newer version
113
113
  · Update available: 0.2.1 → 0.3.0 Run npm install -g gitwrit to update.
114
114
  ```
115
115
 
116
-
117
116
  The check runs in the background, caches for 24 hours, and fails silently if you are offline. It will never interrupt or slow down your workflow.
118
117
 
119
118
  ---
120
119
 
120
+ ## Compatibility
121
+
122
+ | Platform | Status |
123
+ |---|---|
124
+ | macOS | ✅ Fully supported |
125
+ | Linux | ✅ Fully supported |
126
+ | Windows | ❌ Not currently supported |
127
+
128
+ gitwrit is built for macOS and Linux. Windows is not currently supported—the daemon process management and file system watching rely on POSIX signals (`SIGTERM`, `SIGCONT`) that are not available on Windows.
129
+
130
+ If you are a Windows user and would like to contribute Windows support, please open an issue on [GitHub](https://github.com/TBiddy/gitwrit)—it is a welcome contribution.
131
+
132
+ ---
133
+
121
134
  ## Requirements
122
135
 
123
136
  - Node.js ≥ 18
124
137
  - Git
125
- - A configured Git remote (`git remote add origin <url>`) gitwrit requires one before it will initialize a directory
138
+ - A configured Git remote (`git remote add origin <url>`)—gitwrit requires one before it will initialize a directory
139
+
140
+ ---
141
+
142
+ ## Troubleshooting
143
+
144
+ **gitwrit isn't committing my changes**
145
+
146
+ gitwrit watches for file save events. Make sure your editor is actually saving to disk—some terminal editors like Pico and Nano require an explicit save (`Ctrl+X` → `Y`) before changes hit the filesystem. gitwrit cannot commit changes that haven't been written to disk yet.
147
+
148
+ **Push failed notification**
149
+
150
+ If gitwrit notifies you that a push failed, first verify that git can push manually from your terminal:
151
+
152
+ ```sh
153
+ git push
154
+ ```
155
+
156
+ If that works, restart gitwrit with `gitwrit restart`. If it fails, fix your Git authentication first—gitwrit can only push if git itself can push from a non-interactive terminal session. Make sure your SSH key is configured and registered with your Git provider, or that your HTTPS credentials are cached.
157
+
158
+ **Something else feels off**
159
+
160
+ `gitwrit logs` is always your first stop. It shows a timestamped record of every commit, push, and error the daemon has encountered.
126
161
 
127
162
  ---
128
163
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitwrit",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "description": "Private, versioned writing for people who live in the terminal.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -43,9 +43,11 @@ async function editField(key, currentValue) {
43
43
  { name: '5 seconds', value: 5000 },
44
44
  { name: '10 seconds', value: 10000 },
45
45
  { name: 'Custom', value: 'custom' },
46
+ { name: 'Exit', value: 'exit' },
46
47
  ],
47
48
  default: currentValue,
48
49
  });
50
+ if (choice === 'exit') return currentValue; // no change
49
51
  if (choice === 'custom') {
50
52
  const raw = await input({ message: 'Seconds to wait:' });
51
53
  return parseFloat(raw) * 1000;
@@ -61,9 +63,11 @@ async function editField(key, currentValue) {
61
63
  { name: 'Every 10 minutes', value: 600000 },
62
64
  { name: 'Every 30 minutes', value: 1800000 },
63
65
  { name: 'Custom', value: 'custom' },
66
+ { name: 'Exit', value: 'exit' },
64
67
  ],
65
68
  default: currentValue,
66
69
  });
70
+ if (choice === 'exit') return currentValue; // no change
67
71
  if (choice === 'custom') {
68
72
  const raw = await input({ message: 'Minutes between pushes:' });
69
73
  return parseFloat(raw) * 60000;
@@ -72,14 +76,17 @@ async function editField(key, currentValue) {
72
76
  }
73
77
 
74
78
  if (key === 'branchMode') {
75
- return select({
79
+ const choice = await select({
76
80
  message: 'Default branch mode?',
77
81
  choices: [
78
82
  { name: "Current branch — commit to whatever branch you're on", value: 'current' },
79
83
  { name: 'Autogenerated — create a fresh named branch each session', value: 'autogenerated' },
84
+ { name: 'Exit', value: 'exit' },
80
85
  ],
81
86
  default: currentValue,
82
87
  });
88
+ if (choice === 'exit') return currentValue; // no change
89
+ return choice;
83
90
  }
84
91
  }
85
92
 
@@ -112,10 +119,11 @@ async function configureGlobal() {
112
119
  choices: [
113
120
  ...FIELDS.map(f => ({ name: f.label, value: f.key })),
114
121
  { name: 'Done', value: null },
122
+ { name: 'Exit', value: 'exit' },
115
123
  ],
116
124
  });
117
125
 
118
- if (!field) return;
126
+ if (!field || field === 'exit') return;
119
127
 
120
128
  const newValue = await editField(field, config[field]);
121
129
  config[field] = newValue;
@@ -167,10 +175,13 @@ async function configureLocal(dir) {
167
175
  { name: 'Edit an override', value: 'edit' },
168
176
  { name: 'Remove an override', value: 'remove' },
169
177
  { name: 'Add another override', value: 'add' },
178
+ { name: 'Exit', value: 'exit' },
170
179
  ],
171
180
  })
172
181
  : 'add';
173
182
 
183
+ if (action === 'exit') return;
184
+
174
185
  if (action === 'edit' || action === 'add') {
175
186
  const overriddenKeys = Object.keys(local);
176
187
  const choices = action === 'edit'
@@ -184,9 +195,14 @@ async function configureLocal(dir) {
184
195
 
185
196
  const field = await select({
186
197
  message: 'Which setting?',
187
- choices: choices.map(f => ({ name: f.label, value: f.key })),
198
+ choices: [
199
+ ...choices.map(f => ({ name: f.label, value: f.key })),
200
+ { name: 'Exit', value: 'exit' },
201
+ ],
188
202
  });
189
203
 
204
+ if (field === 'exit') return;
205
+
190
206
  const currentValue = local[field] ?? global[field];
191
207
  const newValue = await editField(field, currentValue);
192
208
  local[field] = newValue;
@@ -199,11 +215,16 @@ async function configureLocal(dir) {
199
215
  const overriddenKeys = Object.keys(local);
200
216
  const field = await select({
201
217
  message: 'Which override would you like to remove?',
202
- choices: FIELDS
203
- .filter(f => overriddenKeys.includes(f.key))
204
- .map(f => ({ name: f.label, value: f.key })),
218
+ choices: [
219
+ ...FIELDS
220
+ .filter(f => overriddenKeys.includes(f.key))
221
+ .map(f => ({ name: f.label, value: f.key })),
222
+ { name: 'Exit', value: 'exit' },
223
+ ],
205
224
  });
206
225
 
226
+ if (field === 'exit') return;
227
+
207
228
  delete local[field];
208
229
  await saveLocalConfig(dir, local);
209
230
  print.gap();
@@ -235,9 +256,15 @@ export async function config() {
235
256
  choices: [
236
257
  { name: 'Global defaults', value: 'global' },
237
258
  { name: `This directory (${dir})`, value: 'local' },
259
+ { name: 'Exit', value: 'exit' },
238
260
  ],
239
261
  });
240
262
 
263
+ if (scope === 'exit') {
264
+ print.gap();
265
+ return;
266
+ }
267
+
241
268
  print.gap();
242
269
 
243
270
  if (scope === 'global') {
@@ -247,4 +274,4 @@ export async function config() {
247
274
  }
248
275
 
249
276
  print.gap();
250
- }
277
+ }