itsvertical 0.0.9 → 0.0.10

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
@@ -95,6 +95,16 @@ itsvertical layer status <file> <layer-id> done # Set status to "done"
95
95
  itsvertical layer status <file> <layer-id> none # Clear status
96
96
  ```
97
97
 
98
+ ### Board History
99
+
100
+ Vertical automatically tracks boards you create and open in `~/.vertical/history.json`.
101
+
102
+ ```
103
+ itsvertical history list # List all known boards
104
+ itsvertical history add <file> # Manually add a board to history
105
+ itsvertical history remove <name-or-file> # Remove a board from history
106
+ ```
107
+
98
108
  ### Browser UI
99
109
 
100
110
  `itsvertical open` (or just `itsvertical <file>`) starts a local server and opens the board in your browser. Changes are saved automatically.
@@ -108,6 +118,7 @@ Each box represents a vertical slice of work.
108
118
  - **Add tasks** by clicking the input at the bottom of a box
109
119
  - **Edit tasks** by clicking on them
110
120
  - **Mark tasks done** with the circle checkbox
121
+ - **Add notes** to a task by clicking the sticky note icon (rich text editor with formatting, slash commands, and code blocks)
111
122
  - **Drag tasks** between boxes and layers
112
123
  - **Split layers** with the scissor tool (click ✂ or press **S**, then click a task to split at that point)
113
124
  - **Unsplit layers** by focusing the dashed separator and pressing **Delete**
package/cli/dist/index.js CHANGED
@@ -1472,8 +1472,8 @@ var require_react = __commonJS({
1472
1472
  });
1473
1473
 
1474
1474
  // cli/index.ts
1475
- import fs4 from "fs";
1476
- import path4 from "path";
1475
+ import fs5 from "fs";
1476
+ import path5 from "path";
1477
1477
  import { dirname } from "path";
1478
1478
  import { fileURLToPath as fileURLToPath2 } from "url";
1479
1479
  import { Command } from "commander";
@@ -2105,10 +2105,70 @@ function showSummaryTable(state, boxId) {
2105
2105
  console.log(hLine("\u2514", "\u2534", "\u2518"));
2106
2106
  }
2107
2107
 
2108
- // cli/server.ts
2108
+ // cli/history.ts
2109
2109
  import fs2 from "fs";
2110
- import http from "http";
2110
+ import os from "os";
2111
2111
  import path2 from "path";
2112
+ function getHistoryDir() {
2113
+ return path2.join(os.homedir(), ".vertical");
2114
+ }
2115
+ function getHistoryPath() {
2116
+ return path2.join(getHistoryDir(), "history.json");
2117
+ }
2118
+ function ensureHistoryDir() {
2119
+ const dir = getHistoryDir();
2120
+ if (!fs2.existsSync(dir)) {
2121
+ fs2.mkdirSync(dir, { recursive: true });
2122
+ }
2123
+ }
2124
+ function loadHistory() {
2125
+ const historyPath = getHistoryPath();
2126
+ if (!fs2.existsSync(historyPath)) {
2127
+ return { version: 1, boards: [] };
2128
+ }
2129
+ const content = fs2.readFileSync(historyPath, "utf-8");
2130
+ return JSON.parse(content);
2131
+ }
2132
+ function saveHistory(history2) {
2133
+ ensureHistoryDir();
2134
+ fs2.writeFileSync(getHistoryPath(), JSON.stringify(history2, null, 2));
2135
+ }
2136
+ function slugify(name) {
2137
+ return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
2138
+ }
2139
+ function recordBoard(name, filePath) {
2140
+ const history2 = loadHistory();
2141
+ const slug = slugify(name);
2142
+ const existing = history2.boards.find((b) => slugify(b.name) === slug);
2143
+ if (existing && existing.filePath !== filePath) {
2144
+ throw new Error(
2145
+ `A board named "${existing.name}" is already tracked at: ${existing.filePath}`
2146
+ );
2147
+ }
2148
+ if (!existing) {
2149
+ history2.boards.push({ name, filePath });
2150
+ saveHistory(history2);
2151
+ }
2152
+ }
2153
+ function forgetBoard(nameOrPath) {
2154
+ const history2 = loadHistory();
2155
+ const slug = slugify(nameOrPath);
2156
+ const absolutePath = path2.resolve(nameOrPath);
2157
+ const index = history2.boards.findIndex(
2158
+ (b) => slugify(b.name) === slug || b.filePath === absolutePath
2159
+ );
2160
+ if (index === -1) {
2161
+ return false;
2162
+ }
2163
+ history2.boards.splice(index, 1);
2164
+ saveHistory(history2);
2165
+ return true;
2166
+ }
2167
+
2168
+ // cli/server.ts
2169
+ import fs3 from "fs";
2170
+ import http from "http";
2171
+ import path3 from "path";
2112
2172
  import readline from "readline";
2113
2173
  import { fileURLToPath } from "url";
2114
2174
  import getPort from "get-port";
@@ -2126,24 +2186,24 @@ var MIME_TYPES = {
2126
2186
  ".woff2": "font/woff2"
2127
2187
  };
2128
2188
  function getDistPath() {
2129
- const currentDir = path2.dirname(fileURLToPath(import.meta.url));
2130
- return path2.resolve(currentDir, "..", "..", "dist");
2189
+ const currentDir = path3.dirname(fileURLToPath(import.meta.url));
2190
+ return path3.resolve(currentDir, "..", "..", "dist");
2131
2191
  }
2132
2192
  function serveStaticFile(res, distPath, urlPath) {
2133
- const filePath = path2.join(distPath, urlPath);
2134
- const safePath = path2.resolve(filePath);
2193
+ const filePath = path3.join(distPath, urlPath);
2194
+ const safePath = path3.resolve(filePath);
2135
2195
  if (!safePath.startsWith(distPath)) {
2136
2196
  res.writeHead(403);
2137
2197
  res.end("Forbidden");
2138
2198
  return;
2139
2199
  }
2140
- if (!fs2.existsSync(safePath) || fs2.statSync(safePath).isDirectory()) {
2200
+ if (!fs3.existsSync(safePath) || fs3.statSync(safePath).isDirectory()) {
2141
2201
  return false;
2142
2202
  }
2143
- const ext = path2.extname(safePath);
2203
+ const ext = path3.extname(safePath);
2144
2204
  const contentType = MIME_TYPES[ext] || "application/octet-stream";
2145
2205
  res.writeHead(200, { "Content-Type": contentType });
2146
- fs2.createReadStream(safePath).pipe(res);
2206
+ fs3.createReadStream(safePath).pipe(res);
2147
2207
  return true;
2148
2208
  }
2149
2209
  function readRequestBody(req) {
@@ -2169,10 +2229,10 @@ function confirm(question) {
2169
2229
  });
2170
2230
  }
2171
2231
  async function startServer(filePath, options = {}) {
2172
- const absoluteFilePath = path2.resolve(filePath);
2232
+ const absoluteFilePath = path3.resolve(filePath);
2173
2233
  const distPath = getDistPath();
2174
2234
  let browserDirty = false;
2175
- if (!fs2.existsSync(distPath)) {
2235
+ if (!fs3.existsSync(distPath)) {
2176
2236
  console.error(
2177
2237
  "Error: dist/ directory not found. Run `pnpm run build` first."
2178
2238
  );
@@ -2181,14 +2241,14 @@ async function startServer(filePath, options = {}) {
2181
2241
  const server = http.createServer(async (req, res) => {
2182
2242
  const url2 = req.url || "/";
2183
2243
  if (url2 === "/api/project" && req.method === "GET") {
2184
- const content = fs2.readFileSync(absoluteFilePath, "utf-8");
2244
+ const content = fs3.readFileSync(absoluteFilePath, "utf-8");
2185
2245
  res.writeHead(200, { "Content-Type": "application/json" });
2186
2246
  res.end(content);
2187
2247
  return;
2188
2248
  }
2189
2249
  if (url2 === "/api/project" && req.method === "POST") {
2190
2250
  const body = await readRequestBody(req);
2191
- fs2.writeFileSync(absoluteFilePath, body);
2251
+ fs3.writeFileSync(absoluteFilePath, body);
2192
2252
  res.writeHead(200, { "Content-Type": "application/json" });
2193
2253
  res.end('{"ok":true}');
2194
2254
  return;
@@ -2212,10 +2272,10 @@ async function startServer(filePath, options = {}) {
2212
2272
  }
2213
2273
  if (serveStaticFile(res, distPath, url2))
2214
2274
  return;
2215
- const indexPath = path2.join(distPath, "index.html");
2216
- if (fs2.existsSync(indexPath)) {
2275
+ const indexPath = path3.join(distPath, "index.html");
2276
+ if (fs3.existsSync(indexPath)) {
2217
2277
  res.writeHead(200, { "Content-Type": "text/html" });
2218
- fs2.createReadStream(indexPath).pipe(res);
2278
+ fs3.createReadStream(indexPath).pipe(res);
2219
2279
  return;
2220
2280
  }
2221
2281
  res.writeHead(404);
@@ -2224,7 +2284,7 @@ async function startServer(filePath, options = {}) {
2224
2284
  const port = options.port ?? await getPort();
2225
2285
  const url = `http://localhost:${port}`;
2226
2286
  const sseClients = /* @__PURE__ */ new Set();
2227
- fs2.watch(absoluteFilePath, () => {
2287
+ fs3.watch(absoluteFilePath, () => {
2228
2288
  for (const client of sseClients) {
2229
2289
  client.write("data: file-changed\n\n");
2230
2290
  }
@@ -2257,11 +2317,11 @@ async function startServer(filePath, options = {}) {
2257
2317
 
2258
2318
  // cli/update.ts
2259
2319
  import { execFile } from "child_process";
2260
- import fs3 from "fs";
2261
- import os from "os";
2262
- import path3 from "path";
2263
- var CACHE_DIR = path3.join(os.homedir(), ".itsvertical");
2264
- var CACHE_FILE = path3.join(CACHE_DIR, "update-check.json");
2320
+ import fs4 from "fs";
2321
+ import os2 from "os";
2322
+ import path4 from "path";
2323
+ var CACHE_DIR = path4.join(os2.homedir(), ".itsvertical");
2324
+ var CACHE_FILE = path4.join(CACHE_DIR, "update-check.json");
2265
2325
  var CHECK_INTERVAL = 36e5;
2266
2326
  var FETCH_TIMEOUT = 5e3;
2267
2327
  var REGISTRY_URL = "https://registry.npmjs.org/itsvertical/latest";
@@ -2279,12 +2339,12 @@ function compareSemver(a, b) {
2279
2339
  return 0;
2280
2340
  }
2281
2341
  function isPathInside(childPath, parentPath) {
2282
- const relative = path3.relative(parentPath, childPath);
2283
- return relative !== "" && !relative.startsWith("..") && !path3.isAbsolute(relative);
2342
+ const relative = path4.relative(parentPath, childPath);
2343
+ return relative !== "" && !relative.startsWith("..") && !path4.isAbsolute(relative);
2284
2344
  }
2285
2345
  function resolveScriptPath(scriptPath) {
2286
2346
  try {
2287
- return fs3.realpathSync(scriptPath);
2347
+ return fs4.realpathSync(scriptPath);
2288
2348
  } catch {
2289
2349
  return scriptPath;
2290
2350
  }
@@ -2296,46 +2356,46 @@ function getNpmGlobalPackages() {
2296
2356
  );
2297
2357
  const envValue = envKey ? process.env[envKey] : void 0;
2298
2358
  if (envValue) {
2299
- const prefix2 = path3.resolve(envValue);
2300
- return path3.join(prefix2, isWindows ? "node_modules" : "lib/node_modules");
2359
+ const prefix2 = path4.resolve(envValue);
2360
+ return path4.join(prefix2, isWindows ? "node_modules" : "lib/node_modules");
2301
2361
  }
2302
2362
  let prefix;
2303
2363
  if (isWindows) {
2304
- prefix = process.env.APPDATA ? path3.join(process.env.APPDATA, "npm") : path3.dirname(process.execPath);
2364
+ prefix = process.env.APPDATA ? path4.join(process.env.APPDATA, "npm") : path4.dirname(process.execPath);
2305
2365
  } else if (process.execPath.includes("/Cellar/node")) {
2306
2366
  prefix = process.execPath.slice(0, process.execPath.indexOf("/Cellar/node"));
2307
2367
  } else {
2308
- prefix = path3.dirname(path3.dirname(process.execPath));
2368
+ prefix = path4.dirname(path4.dirname(process.execPath));
2309
2369
  }
2310
- return path3.join(prefix, isWindows ? "node_modules" : "lib/node_modules");
2370
+ return path4.join(prefix, isWindows ? "node_modules" : "lib/node_modules");
2311
2371
  }
2312
2372
  function getPnpmGlobalDir() {
2313
2373
  if (process.env.PNPM_HOME)
2314
2374
  return process.env.PNPM_HOME;
2315
2375
  if (process.env.XDG_DATA_HOME)
2316
- return path3.join(process.env.XDG_DATA_HOME, "pnpm");
2376
+ return path4.join(process.env.XDG_DATA_HOME, "pnpm");
2317
2377
  if (process.platform === "darwin")
2318
- return path3.join(os.homedir(), "Library/pnpm");
2378
+ return path4.join(os2.homedir(), "Library/pnpm");
2319
2379
  if (process.platform !== "win32")
2320
- return path3.join(os.homedir(), ".local/share/pnpm");
2380
+ return path4.join(os2.homedir(), ".local/share/pnpm");
2321
2381
  if (process.env.LOCALAPPDATA)
2322
- return path3.join(process.env.LOCALAPPDATA, "pnpm");
2323
- return path3.join(os.homedir(), ".pnpm");
2382
+ return path4.join(process.env.LOCALAPPDATA, "pnpm");
2383
+ return path4.join(os2.homedir(), ".pnpm");
2324
2384
  }
2325
2385
  function getYarnGlobalPackages() {
2326
2386
  const isWindows = process.platform === "win32";
2327
2387
  let dataDir;
2328
2388
  if (isWindows) {
2329
- dataDir = process.env.LOCALAPPDATA ? path3.join(process.env.LOCALAPPDATA, "Yarn/Data") : path3.join(os.homedir(), ".config/yarn");
2389
+ dataDir = process.env.LOCALAPPDATA ? path4.join(process.env.LOCALAPPDATA, "Yarn/Data") : path4.join(os2.homedir(), ".config/yarn");
2330
2390
  } else if (process.env.XDG_DATA_HOME) {
2331
- dataDir = path3.join(process.env.XDG_DATA_HOME, "yarn");
2391
+ dataDir = path4.join(process.env.XDG_DATA_HOME, "yarn");
2332
2392
  } else {
2333
- dataDir = path3.join(os.homedir(), ".config/yarn");
2393
+ dataDir = path4.join(os2.homedir(), ".config/yarn");
2334
2394
  }
2335
- return path3.join(dataDir, "global/node_modules");
2395
+ return path4.join(dataDir, "global/node_modules");
2336
2396
  }
2337
2397
  function getBunGlobalDir() {
2338
- return process.env.BUN_INSTALL || path3.join(os.homedir(), ".bun");
2398
+ return process.env.BUN_INSTALL || path4.join(os2.homedir(), ".bun");
2339
2399
  }
2340
2400
  function detectInstallContext(scriptPath) {
2341
2401
  const resolved = resolveScriptPath(scriptPath);
@@ -2343,24 +2403,24 @@ function detectInstallContext(scriptPath) {
2343
2403
  if (npxMatch) {
2344
2404
  return { type: "npx-cache", cachePath: npxMatch[1] };
2345
2405
  }
2346
- const bunDir = path3.resolve(getBunGlobalDir());
2406
+ const bunDir = path4.resolve(getBunGlobalDir());
2347
2407
  if (isPathInside(resolved, bunDir)) {
2348
- const bunCacheDir = path3.join(bunDir, "install", "cache");
2408
+ const bunCacheDir = path4.join(bunDir, "install", "cache");
2349
2409
  if (isPathInside(resolved, bunCacheDir)) {
2350
2410
  return { type: "bunx-cache", cacheDir: bunCacheDir };
2351
2411
  }
2352
2412
  return { type: "global", packageManager: "bun" };
2353
2413
  }
2354
- const pnpmDir = path3.resolve(getPnpmGlobalDir());
2414
+ const pnpmDir = path4.resolve(getPnpmGlobalDir());
2355
2415
  if (isPathInside(resolved, pnpmDir)) {
2356
2416
  return { type: "global", packageManager: "pnpm" };
2357
2417
  }
2358
- const yarnPackages = path3.resolve(getYarnGlobalPackages());
2418
+ const yarnPackages = path4.resolve(getYarnGlobalPackages());
2359
2419
  if (isPathInside(resolved, yarnPackages)) {
2360
2420
  return { type: "global", packageManager: "yarn" };
2361
2421
  }
2362
2422
  try {
2363
- const npmPackages = fs3.realpathSync(getNpmGlobalPackages());
2423
+ const npmPackages = fs4.realpathSync(getNpmGlobalPackages());
2364
2424
  if (isPathInside(resolved, npmPackages)) {
2365
2425
  return { type: "global", packageManager: "npm" };
2366
2426
  }
@@ -2373,15 +2433,15 @@ function detectInstallContext(scriptPath) {
2373
2433
  }
2374
2434
  function readCache() {
2375
2435
  try {
2376
- return JSON.parse(fs3.readFileSync(CACHE_FILE, "utf-8"));
2436
+ return JSON.parse(fs4.readFileSync(CACHE_FILE, "utf-8"));
2377
2437
  } catch {
2378
2438
  return null;
2379
2439
  }
2380
2440
  }
2381
2441
  function writeCache(cache) {
2382
2442
  try {
2383
- fs3.mkdirSync(CACHE_DIR, { recursive: true });
2384
- fs3.writeFileSync(CACHE_FILE, JSON.stringify(cache));
2443
+ fs4.mkdirSync(CACHE_DIR, { recursive: true });
2444
+ fs4.writeFileSync(CACHE_FILE, JSON.stringify(cache));
2385
2445
  } catch {
2386
2446
  }
2387
2447
  }
@@ -2470,7 +2530,7 @@ function getUpdateCommandString(context) {
2470
2530
  async function performUpdate(context) {
2471
2531
  if (context.type === "npx-cache") {
2472
2532
  try {
2473
- fs3.rmSync(context.cachePath, { recursive: true, force: true });
2533
+ fs4.rmSync(context.cachePath, { recursive: true, force: true });
2474
2534
  return {
2475
2535
  success: true,
2476
2536
  message: "Cleared npx cache. Next run will fetch the latest version."
@@ -2481,9 +2541,9 @@ async function performUpdate(context) {
2481
2541
  }
2482
2542
  if (context.type === "bunx-cache") {
2483
2543
  try {
2484
- for (const entry of fs3.readdirSync(context.cacheDir)) {
2544
+ for (const entry of fs4.readdirSync(context.cacheDir)) {
2485
2545
  if (entry.startsWith("itsvertical@")) {
2486
- fs3.rmSync(path3.join(context.cacheDir, entry), {
2546
+ fs4.rmSync(path4.join(context.cacheDir, entry), {
2487
2547
  recursive: true,
2488
2548
  force: true
2489
2549
  });
@@ -2542,8 +2602,8 @@ function getDirname() {
2542
2602
  throw new Error("Cannot determine directory path in current environment");
2543
2603
  }
2544
2604
  var packageJson = JSON.parse(
2545
- fs4.readFileSync(
2546
- path4.resolve(getDirname(), "..", "..", "package.json"),
2605
+ fs5.readFileSync(
2606
+ path5.resolve(getDirname(), "..", "..", "package.json"),
2547
2607
  "utf8"
2548
2608
  )
2549
2609
  );
@@ -2552,20 +2612,33 @@ program.name("itsvertical").description(
2552
2612
  "Tickets pile up, scopes get done. Project work isn't linear, it's Vertical.\n\nTip: itsvertical <file.vertical> is a shorthand for itsvertical open <file>."
2553
2613
  ).version(packageJson.version);
2554
2614
  program.command("new").description("Create a new .vertical project file").argument("<path>", "File path for the new .vertical file").argument("<name>", "Project name").option("--json", "Output as JSON").action((fileDest, name, options) => {
2555
- const filePath = path4.resolve(fileDest);
2556
- if (fs4.existsSync(filePath)) {
2615
+ const filePath = path5.resolve(fileDest);
2616
+ if (fs5.existsSync(filePath)) {
2557
2617
  fail(`File already exists: ${filePath}`, options.json);
2558
2618
  }
2559
- const dir = path4.dirname(filePath);
2560
- if (!fs4.existsSync(dir)) {
2561
- fs4.mkdirSync(dir, { recursive: true });
2619
+ const dir = path5.dirname(filePath);
2620
+ if (!fs5.existsSync(dir)) {
2621
+ fs5.mkdirSync(dir, { recursive: true });
2562
2622
  }
2563
2623
  const state = createBlankProject(name);
2564
- fs4.writeFileSync(filePath, serialize(state));
2624
+ fs5.writeFileSync(filePath, serialize(state));
2625
+ try {
2626
+ recordBoard(name, filePath);
2627
+ } catch (error) {
2628
+ fail(error.message, options.json);
2629
+ }
2565
2630
  output(state, Boolean(options.json), `Created: ${filePath}`);
2566
2631
  });
2567
2632
  program.command("open").description("Open an existing .vertical file in the browser").argument("<file>", "Path to the .vertical file").action(async (file) => {
2568
2633
  const filePath = resolveFilePath(file);
2634
+ const state = loadState(filePath);
2635
+ try {
2636
+ recordBoard(state.project.name, filePath);
2637
+ } catch (error) {
2638
+ console.warn(
2639
+ `Warning: could not track board: ${error.message}`
2640
+ );
2641
+ }
2569
2642
  await startServer(filePath);
2570
2643
  });
2571
2644
  program.command("dev").description("Start dev server (fixed port, no browser open)").argument("<file>", "Path to the .vertical file").action(async (file) => {
@@ -2597,6 +2670,53 @@ program.command("rename").description("Rename the project").argument("<file>", "
2597
2670
  const state = applyAction(filePath, { type: "RENAME_PROJECT", name });
2598
2671
  output(state, Boolean(options.json), `Project renamed to: ${name}`);
2599
2672
  });
2673
+ var history = program.command("history").description("Manage board history");
2674
+ history.command("list").description("List all known boards").option("--json", "Output as JSON").action((options) => {
2675
+ const boardHistory = loadHistory();
2676
+ if (options.json) {
2677
+ const entries = boardHistory.boards.map((b) => ({
2678
+ name: b.name,
2679
+ filePath: b.filePath,
2680
+ exists: fs5.existsSync(b.filePath)
2681
+ }));
2682
+ console.log(JSON.stringify(entries, null, 2));
2683
+ return;
2684
+ }
2685
+ if (boardHistory.boards.length === 0) {
2686
+ console.log("No boards known yet. Create or open a board to get started.");
2687
+ return;
2688
+ }
2689
+ for (const board of boardHistory.boards) {
2690
+ const exists = fs5.existsSync(board.filePath);
2691
+ const marker = exists ? "" : " (missing)";
2692
+ console.log(`${board.name} ${board.filePath}${marker}`);
2693
+ }
2694
+ });
2695
+ history.command("add").description("Add an existing .vertical file to history").argument("<file>", "Path to the .vertical file").option("--json", "Output as JSON").action((file, options) => {
2696
+ const filePath = resolveFilePath(file, options.json);
2697
+ const state = loadState(filePath);
2698
+ try {
2699
+ recordBoard(state.project.name, filePath);
2700
+ } catch (error) {
2701
+ fail(error.message, options.json);
2702
+ }
2703
+ output(
2704
+ state,
2705
+ Boolean(options.json),
2706
+ `Added to history: ${state.project.name} \u2192 ${filePath}`
2707
+ );
2708
+ });
2709
+ history.command("remove").description("Remove a board from history (does not delete the file)").argument("<name-or-file>", "Board name or file path").option("--json", "Output as JSON").action((nameOrFile, options) => {
2710
+ const removed = forgetBoard(nameOrFile);
2711
+ if (!removed) {
2712
+ fail(`Board not found in history: "${nameOrFile}"`, options.json);
2713
+ }
2714
+ if (options.json) {
2715
+ console.log(JSON.stringify({ success: true }));
2716
+ } else {
2717
+ console.log(`Removed from history: ${nameOrFile}`);
2718
+ }
2719
+ });
2600
2720
  var task = program.command("task").description("Manage tasks");
2601
2721
  task.command("add").description("Add a task to a layer").argument("<file>", "Path to the .vertical file").argument("<layer-id>", "Layer ID to add the task to").argument("<name>", "Task name").option("--json", "Output as JSON").option("--after <task-id>", "Insert after a specific task").action(
2602
2722
  (file, layerId, name, options) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "itsvertical",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "type": "module",
5
5
  "description": "Tickets pile up, scopes get done. Project work isn't linear, it's Vertical.",
6
6
  "license": "MIT",