hotsheet 0.2.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.
Files changed (3) hide show
  1. package/README.md +59 -3
  2. package/dist/cli.js +27 -8
  3. package/package.json +8 -2
package/README.md CHANGED
@@ -12,15 +12,32 @@ No cloud. No logins. No JIRA. Just tickets and a tight feedback loop.
12
12
 
13
13
  <br>
14
14
 
15
+ **Desktop app** (recommended) — download from [GitHub Releases](https://github.com/brianwestphal/hotsheet/releases):
16
+
17
+ | Platform | Download |
18
+ |----------|----------|
19
+ | macOS (Apple Silicon) | `.dmg` (arm64) |
20
+ | macOS (Intel) | `.dmg` (x64) |
21
+ | Linux | `.AppImage` / `.deb` |
22
+ | Windows | `.msi` / `.exe` |
23
+
24
+ After installing, open the app and click **Install CLI** to add the `hotsheet` command to your PATH.
25
+
26
+ **Or install via npm:**
27
+
15
28
  ```bash
16
29
  npm install -g hotsheet
17
30
  ```
18
31
 
32
+ Then, from any project directory:
33
+
19
34
  ```bash
20
35
  hotsheet
21
36
  ```
22
37
 
23
- That's it. Opens in your browser. Data stays local.
38
+ That's it. Data stays local.
39
+
40
+ > **Note:** We're actively developing and testing on macOS. Linux and Windows builds are provided but less tested — if you run into issues on those platforms, we'd love your help! Please [open an issue](https://github.com/brianwestphal/hotsheet/issues).
24
41
 
25
42
  </div>
26
43
 
@@ -154,6 +171,28 @@ TICKET HS-15:
154
171
 
155
172
  ## Install
156
173
 
174
+ ### Desktop app (recommended)
175
+
176
+ Download the latest release for your platform from [GitHub Releases](https://github.com/brianwestphal/hotsheet/releases).
177
+
178
+ On first launch, the app will prompt you to install the `hotsheet` CLI command. This creates a symlink so you can launch the desktop app from any project directory. You can also install it manually:
179
+
180
+ **macOS:**
181
+ ```bash
182
+ sudo ln -sf "/Applications/Hot Sheet.app/Contents/Resources/resources/hotsheet" /usr/local/bin/hotsheet
183
+ ```
184
+
185
+ **Linux:**
186
+ ```bash
187
+ ln -sf /path/to/hotsheet/resources/hotsheet-linux ~/.local/bin/hotsheet
188
+ ```
189
+
190
+ The desktop app includes automatic updates — new versions are downloaded and applied in the background.
191
+
192
+ ### npm
193
+
194
+ Alternatively, install via npm (runs in your browser instead of a native window):
195
+
157
196
  ```bash
158
197
  npm install -g hotsheet
159
198
  ```
@@ -165,14 +204,17 @@ Requires **Node.js 20+**.
165
204
  ## Usage
166
205
 
167
206
  ```bash
168
- # Start with defaults (port 4174, data in .hotsheet/)
207
+ # Start from your project directory
169
208
  hotsheet
170
209
 
171
- # Custom port
210
+ # Custom port (npm version only)
172
211
  hotsheet --port 8080
173
212
 
174
213
  # Custom data directory
175
214
  hotsheet --data-dir ~/projects/my-app/.hotsheet
215
+
216
+ # Force browser mode (desktop app)
217
+ hotsheet --browser
176
218
  ```
177
219
 
178
220
  ### Options
@@ -181,8 +223,21 @@ hotsheet --data-dir ~/projects/my-app/.hotsheet
181
223
  |------|-------------|
182
224
  | `--port <number>` | Port to run on (default: 4174) |
183
225
  | `--data-dir <path>` | Data directory (default: `.hotsheet/`) |
226
+ | `--browser` | Open in browser instead of desktop window |
184
227
  | `--help` | Show help |
185
228
 
229
+ ### Customizing the window title
230
+
231
+ When running multiple instances, you can customize the window title to tell them apart. Create `.hotsheet/settings.json` in your project:
232
+
233
+ ```json
234
+ {
235
+ "appName": "HS - My Project"
236
+ }
237
+ ```
238
+
239
+ Without a settings file, the window title defaults to the project folder name.
240
+
186
241
  ### Keyboard shortcuts
187
242
 
188
243
  | Shortcut | Action |
@@ -206,6 +261,7 @@ hotsheet --data-dir ~/projects/my-app/.hotsheet
206
261
 
207
262
  | Layer | Technology |
208
263
  |-------|-----------|
264
+ | Desktop | Tauri v2 (native window, auto-updates) |
209
265
  | CLI | TypeScript, Node.js |
210
266
  | Server | Hono |
211
267
  | Database | PGLite (embedded PostgreSQL) |
package/dist/cli.js CHANGED
@@ -2044,7 +2044,7 @@ function tryServe(fetch, port2) {
2044
2044
  });
2045
2045
  });
2046
2046
  }
2047
- async function startServer(port2, dataDir2) {
2047
+ async function startServer(port2, dataDir2, options) {
2048
2048
  const app = new Hono3();
2049
2049
  app.use("*", async (c, next) => {
2050
2050
  c.set("dataDir", dataDir2);
@@ -2068,8 +2068,17 @@ async function startServer(port2, dataDir2) {
2068
2068
  actualPort = await tryServe(app.fetch, port2 + attempt);
2069
2069
  break;
2070
2070
  } catch (err) {
2071
- if (err instanceof Error && err.code === "EADDRINUSE" && attempt < 19) {
2072
- continue;
2071
+ if (err instanceof Error && err.code === "EADDRINUSE") {
2072
+ if (options?.strictPort) {
2073
+ console.error(`
2074
+ Error: Port ${port2} is already in use.`);
2075
+ console.error(` In --strict-port mode, the server must start on the requested port`);
2076
+ console.error(` because the Tauri dev window is configured to connect to it.`);
2077
+ console.error(` Stop whatever is using port ${port2} and try again.
2078
+ `);
2079
+ process.exit(1);
2080
+ }
2081
+ if (attempt < 19) continue;
2073
2082
  }
2074
2083
  throw err;
2075
2084
  }
@@ -2081,8 +2090,10 @@ async function startServer(port2, dataDir2) {
2081
2090
  console.log(`
2082
2091
  Hot Sheet running at ${url}
2083
2092
  `);
2084
- const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
2085
- exec(`${openCmd} ${url}`);
2093
+ if (!options?.noOpen) {
2094
+ const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
2095
+ exec(`${openCmd} ${url}`);
2096
+ }
2086
2097
  return actualPort;
2087
2098
  }
2088
2099
 
@@ -2223,6 +2234,8 @@ function parseArgs(argv) {
2223
2234
  let dataDir2 = join7(process.cwd(), ".hotsheet");
2224
2235
  let demo = null;
2225
2236
  let forceUpdateCheck = false;
2237
+ let noOpen = false;
2238
+ let strictPort = false;
2226
2239
  for (let i = 0; i < args.length; i++) {
2227
2240
  const arg = args[i];
2228
2241
  if (arg.startsWith("--demo:")) {
@@ -2252,13 +2265,19 @@ function parseArgs(argv) {
2252
2265
  case "--check-for-updates":
2253
2266
  forceUpdateCheck = true;
2254
2267
  break;
2268
+ case "--no-open":
2269
+ noOpen = true;
2270
+ break;
2271
+ case "--strict-port":
2272
+ strictPort = true;
2273
+ break;
2255
2274
  default:
2256
2275
  console.error(`Unknown option: ${arg}`);
2257
2276
  printUsage();
2258
2277
  process.exit(1);
2259
2278
  }
2260
2279
  }
2261
- return { port: port2, dataDir: dataDir2, demo, forceUpdateCheck };
2280
+ return { port: port2, dataDir: dataDir2, demo, forceUpdateCheck, noOpen, strictPort };
2262
2281
  }
2263
2282
  async function main() {
2264
2283
  const parsed = parseArgs(process.argv);
@@ -2266,7 +2285,7 @@ async function main() {
2266
2285
  printUsage();
2267
2286
  process.exit(1);
2268
2287
  }
2269
- const { port: port2, demo, forceUpdateCheck } = parsed;
2288
+ const { port: port2, demo, forceUpdateCheck, noOpen, strictPort } = parsed;
2270
2289
  let { dataDir: dataDir2 } = parsed;
2271
2290
  await checkForUpdates(forceUpdateCheck);
2272
2291
  if (demo !== null) {
@@ -2297,7 +2316,7 @@ async function main() {
2297
2316
  await cleanupAttachments();
2298
2317
  }
2299
2318
  console.log(` Data directory: ${dataDir2}`);
2300
- const actualPort = await startServer(port2, dataDir2);
2319
+ const actualPort = await startServer(port2, dataDir2, { noOpen, strictPort });
2301
2320
  initMarkdownSync(dataDir2, actualPort);
2302
2321
  scheduleAllSync();
2303
2322
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hotsheet",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "A lightweight local project management tool. Create, categorize, and prioritize tickets with a fast bullet-list interface, then export an Up Next worklist for AI tools.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -33,8 +33,13 @@
33
33
  "build:client": "mkdir -p dist/client && npx esbuild src/client/app.ts --bundle --format=iife --outfile=dist/client/app.global.js --target=es2020 --jsx=automatic --jsx-import-source=#jsx --alias:#jsx/jsx-runtime=./src/jsx-runtime.ts && npx sass src/client/styles.scss dist/client/styles.css --style compressed --no-source-map",
34
34
  "lint": "eslint src/",
35
35
  "clean": "rm -rf dist node_modules/.cache",
36
+ "tauri:clean": "rm -rf src-tauri/target",
36
37
  "release": "bash scripts/release.sh",
37
- "prepublishOnly": "npm run build"
38
+ "prepublishOnly": "npm run build",
39
+ "dev:server": "npm run build:client && tsx --tsconfig tsconfig.json src/cli.ts --no-open --strict-port",
40
+ "tauri": "tauri",
41
+ "tauri:dev": "bash scripts/ensure-sidecar-stub.sh && tauri dev",
42
+ "tauri:build": "bash scripts/build-sidecar.sh && tauri build"
38
43
  },
39
44
  "files": [
40
45
  "dist",
@@ -57,6 +62,7 @@
57
62
  "tsup": "^8.5.1",
58
63
  "tsx": "^4.21.0",
59
64
  "typescript": "^5.9.3",
65
+ "@tauri-apps/cli": "^2",
60
66
  "typescript-eslint": "^8.56.1"
61
67
  }
62
68
  }