agendex-cli 1.1.0 → 1.2.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 +3 -0
  2. package/dist/cli.js +188 -26
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -23,6 +23,9 @@ agendex configure # Select which agents/adapters to index
23
23
  agendex start # Start daemon (backgrounds itself)
24
24
  agendex stop # Stop the running daemon
25
25
  agendex sync # One-shot scan + sync to cloud
26
+ agendex upload <path> # Upload a single Markdown plan file to the cloud
27
+ agendex upload <path> --agent <name> # Override the uploaded plan's agent label
28
+ agendex upload <path> --open # Open the uploaded plan in the browser after upload
26
29
  agendex cleanup # Interactively remove cloud daemons
27
30
  agendex cleanup --stale # Auto-remove all stale daemons
28
31
  agendex status # Show config state, daemon status, uptime & hostname
package/dist/cli.js CHANGED
@@ -1059,8 +1059,8 @@ var init_cleanup = __esm(() => {
1059
1059
 
1060
1060
  // src/cli.ts
1061
1061
  import { spawn as spawn4 } from "node:child_process";
1062
- import { existsSync as existsSync12, statSync as statSync2, writeSync } from "node:fs";
1063
- import { resolve as resolve9 } from "node:path";
1062
+ import { existsSync as existsSync13, statSync as statSync2, writeSync } from "node:fs";
1063
+ import { resolve as resolve10 } from "node:path";
1064
1064
  import { fileURLToPath as fileURLToPath3 } from "node:url";
1065
1065
 
1066
1066
  // ../shared/src/adapters/catalog.ts
@@ -2822,6 +2822,7 @@ function normalizeStoredConfig(raw) {
2822
2822
  const token = typeof raw.token === "string" && raw.token.trim() ? raw.token : undefined;
2823
2823
  const cloudToken = typeof raw.cloudToken === "string" && raw.cloudToken.trim() ? raw.cloudToken : undefined;
2824
2824
  const convexUrl = typeof raw.convexUrl === "string" && raw.convexUrl.trim() ? raw.convexUrl : undefined;
2825
+ const siteUrl = typeof raw.siteUrl === "string" && raw.siteUrl.trim() ? raw.siteUrl : undefined;
2825
2826
  const deviceId = typeof raw.deviceId === "string" && raw.deviceId.trim() ? raw.deviceId : undefined;
2826
2827
  const collectLocalIpAddress = typeof raw.collectLocalIpAddress === "boolean" ? raw.collectLocalIpAddress : undefined;
2827
2828
  return {
@@ -2829,6 +2830,7 @@ function normalizeStoredConfig(raw) {
2829
2830
  token,
2830
2831
  cloudToken,
2831
2832
  convexUrl,
2833
+ siteUrl,
2832
2834
  deviceId,
2833
2835
  collectLocalIpAddress,
2834
2836
  enabledAdapters: normalizeAdapterIds(raw.enabledAdapters),
@@ -2845,6 +2847,7 @@ function saveConfig(config) {
2845
2847
  token: config.token,
2846
2848
  cloudToken: config.cloudToken,
2847
2849
  convexUrl: config.convexUrl,
2850
+ siteUrl: config.siteUrl,
2848
2851
  deviceId: config.deviceId,
2849
2852
  collectLocalIpAddress: config.collectLocalIpAddress,
2850
2853
  enabledAdapters: sanitizeEnabledAdapterIds(config.enabledAdapters),
@@ -2923,6 +2926,7 @@ async function loadOrInitConfig(options = {}) {
2923
2926
  token: tokenFromEnv ? existing?.token : currentToken,
2924
2927
  cloudToken: existing?.cloudToken,
2925
2928
  convexUrl: existing?.convexUrl,
2929
+ siteUrl: existing?.siteUrl,
2926
2930
  deviceId,
2927
2931
  enabledAdapters,
2928
2932
  customPlanDirs: existing?.customPlanDirs ?? []
@@ -3870,7 +3874,8 @@ function parseSyncSuccess(body) {
3870
3874
  return {
3871
3875
  ok: true,
3872
3876
  skippedLowValue: result.skippedLowValue === true,
3873
- deleted: result.deleted === true
3877
+ deleted: result.deleted === true,
3878
+ ...typeof result.planId === "string" && { planId: result.planId }
3874
3879
  };
3875
3880
  } catch {
3876
3881
  return { ok: true };
@@ -3905,7 +3910,7 @@ async function syncPlan(plan) {
3905
3910
  }
3906
3911
  }
3907
3912
  if (res.status < 200 || res.status >= 300) {
3908
- return { ok: false, error: `${res.status}: ${res.body}` };
3913
+ return { ok: false, status: res.status, error: `${res.status}: ${res.body}` };
3909
3914
  }
3910
3915
  return parseSyncSuccess(res.body);
3911
3916
  }
@@ -4191,6 +4196,12 @@ function getDefaultSiteUrl() {
4191
4196
  return process.env.AGENDEX_SITE_URL;
4192
4197
  return isDevMode() ? DEV_SITE_URL : PROD_SITE_URL;
4193
4198
  }
4199
+ function getSiteUrl() {
4200
+ const config = loadConfig();
4201
+ if (config?.siteUrl)
4202
+ return config.siteUrl;
4203
+ return getDefaultSiteUrl();
4204
+ }
4194
4205
  function launchBrowser(url, label) {
4195
4206
  console.log(`[agendex] Opening ${label}...`);
4196
4207
  console.log(`[agendex] If it doesn't open, visit: ${url}`);
@@ -4203,15 +4214,16 @@ function launchBrowser(url, label) {
4203
4214
  async function login(siteUrlOverride) {
4204
4215
  const { port, result } = await startCallbackServer();
4205
4216
  const callbackUrl = `http://127.0.0.1:${port}/callback`;
4206
- const siteUrl = siteUrlOverride ?? getDefaultSiteUrl();
4217
+ const existing = loadConfig();
4218
+ const siteUrl = siteUrlOverride ?? existing?.siteUrl ?? getDefaultSiteUrl();
4207
4219
  const authUrl = `${siteUrl}/auth/cli?callback=${encodeURIComponent(callbackUrl)}`;
4208
4220
  launchBrowser(authUrl, "browser for authentication");
4209
4221
  const callback = await result;
4210
- const existing = loadConfig();
4211
4222
  const config = {
4212
4223
  configVersion: 3,
4213
4224
  cloudToken: callback.token,
4214
4225
  convexUrl: callback.convexUrl,
4226
+ siteUrl,
4215
4227
  enabledAdapters: existing?.enabledAdapters ?? [],
4216
4228
  customPlanDirs: existing?.customPlanDirs ?? [],
4217
4229
  ...existing?.token ? { token: existing.token } : {},
@@ -4232,7 +4244,8 @@ function logout() {
4232
4244
  enabledAdapters: existing.enabledAdapters,
4233
4245
  customPlanDirs: existing.customPlanDirs,
4234
4246
  ...existing.token ? { token: existing.token } : {},
4235
- ...existing.deviceId ? { deviceId: existing.deviceId } : {}
4247
+ ...existing.deviceId ? { deviceId: existing.deviceId } : {},
4248
+ ...existing.siteUrl ? { siteUrl: existing.siteUrl } : {}
4236
4249
  };
4237
4250
  saveConfig(config);
4238
4251
  console.log("[agendex] Logged out. Cloud token removed.");
@@ -4376,7 +4389,7 @@ function spawnBrowser(command, args, options = {}) {
4376
4389
  // src/daemon.ts
4377
4390
  import { spawn as spawn2 } from "node:child_process";
4378
4391
  import { hostname as osHostname2 } from "node:os";
4379
- import { resolve as resolve6 } from "node:path";
4392
+ import { resolve as resolve7 } from "node:path";
4380
4393
  import { fileURLToPath } from "node:url";
4381
4394
 
4382
4395
  // src/adapters.ts
@@ -4521,6 +4534,7 @@ function isIpv4Address(address) {
4521
4534
  }
4522
4535
 
4523
4536
  // src/payload.ts
4537
+ import { basename as basename6, resolve as resolve6 } from "node:path";
4524
4538
  var SYNC_METADATA_KEY = "agendexSync";
4525
4539
  function isRecord4(value) {
4526
4540
  return typeof value === "object" && value !== null;
@@ -4539,6 +4553,36 @@ function withSyncDeviceMetadata(metadata, deviceId, hostname2, ipAddress) {
4539
4553
  }
4540
4554
  };
4541
4555
  }
4556
+ function parseUploadFile(filePath, content, agentOverride) {
4557
+ const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n/);
4558
+ const override = agentOverride?.trim();
4559
+ let agent = override || "uploaded";
4560
+ if (!override && fmMatch) {
4561
+ const agentLine = fmMatch[1]?.match(/^agent:\s*(.+)$/m);
4562
+ if (agentLine?.[1])
4563
+ agent = agentLine[1].trim();
4564
+ }
4565
+ const body = fmMatch ? content.slice(fmMatch[0].length) : content;
4566
+ const titleMatch = body.match(/^#\s+(.+)/m);
4567
+ const title = titleMatch?.[1]?.trim() || basename6(filePath).replace(/\.md$/i, "") || "Untitled";
4568
+ return { title, agent, body };
4569
+ }
4570
+ function fileToSyncPayload(filePath, content, options = {}) {
4571
+ const absolutePath = resolve6(filePath);
4572
+ const { title, agent, body } = parseUploadFile(absolutePath, content, options.agentOverride);
4573
+ const now = Date.now();
4574
+ return {
4575
+ localPlanId: hashPath(absolutePath),
4576
+ agent,
4577
+ title,
4578
+ content: body,
4579
+ format: "md",
4580
+ filePath: absolutePath,
4581
+ metadata: withSyncDeviceMetadata({ uploaded: true, userCreated: true }, options.deviceId, options.hostname, options.ipAddress),
4582
+ createdAt: options.createdAt ?? now,
4583
+ updatedAt: options.updatedAt ?? now
4584
+ };
4585
+ }
4542
4586
  function planToSyncPayload(plan, deviceId, hostname2, ipAddress) {
4543
4587
  return {
4544
4588
  localPlanId: plan.id,
@@ -4981,7 +5025,7 @@ async function startSupervisor() {
4981
5025
  };
4982
5026
  process.on("SIGTERM", shutdown);
4983
5027
  process.on("SIGINT", shutdown);
4984
- const scriptPath = resolve6(process.argv[1] ?? fileURLToPath(new URL("./cli.ts", import.meta.url)));
5028
+ const scriptPath = resolve7(process.argv[1] ?? fileURLToPath(new URL("./cli.ts", import.meta.url)));
4985
5029
  const restartTimes = [];
4986
5030
  while (!stopping) {
4987
5031
  const workerArgs = [scriptPath, "start", "--worker"];
@@ -4991,11 +5035,11 @@ async function startSupervisor() {
4991
5035
  stdio: ["ignore", "inherit", "inherit"],
4992
5036
  env: { ...process.env, ...isDevMode() ? { AGENDEX_DEV: "1" } : {} }
4993
5037
  });
4994
- const exitCode = await new Promise((resolve7) => {
4995
- workerProc?.once("exit", (code) => resolve7(code));
5038
+ const exitCode = await new Promise((resolve8) => {
5039
+ workerProc?.once("exit", (code) => resolve8(code));
4996
5040
  workerProc?.once("error", (error) => {
4997
5041
  console.error("[agendex] failed to spawn worker:", error);
4998
- resolve7(1);
5042
+ resolve8(1);
4999
5043
  });
5000
5044
  });
5001
5045
  workerProc = null;
@@ -5021,7 +5065,7 @@ async function startSupervisor() {
5021
5065
  import { existsSync as existsSync10, readFileSync as readFileSync7 } from "node:fs";
5022
5066
  import { mkdir as mkdir2, rm, writeFile as writeFile4 } from "node:fs/promises";
5023
5067
  import { homedir as homedir10 } from "node:os";
5024
- import { dirname as dirname4, join as join14, resolve as resolve7 } from "node:path";
5068
+ import { dirname as dirname4, join as join14, resolve as resolve8 } from "node:path";
5025
5069
  var SUPPORTED_AGENTS = ["claude-code", "codex", "pi"];
5026
5070
  var MANAGED_MARKER = "agendex-plan-review";
5027
5071
  var HOOK_TIMEOUT_SECONDS = 345600;
@@ -5033,7 +5077,7 @@ function commandFor(cliEntry, agent) {
5033
5077
  return `${shellQuote(process.execPath)} ${shellQuote(cliEntry)} review-plan --hook --agent ${agent}`;
5034
5078
  }
5035
5079
  function scopeRoot(scope) {
5036
- return scope === "repo" ? resolve7(process.env.PWD || process.cwd()) : homedir10();
5080
+ return scope === "repo" ? resolve8(process.env.PWD || process.cwd()) : homedir10();
5037
5081
  }
5038
5082
  function hooksJsonPath(agent, scope) {
5039
5083
  const root = scopeRoot(scope);
@@ -5358,7 +5402,7 @@ async function runHooksCommand(args, cliEntry) {
5358
5402
  for (const agent of agents) {
5359
5403
  if (agent === "claude-code")
5360
5404
  printClaudePreviewWarning(dryRun);
5361
- const path = await installAgent(agent, scope, resolve7(cliEntry), dryRun);
5405
+ const path = await installAgent(agent, scope, resolve8(cliEntry), dryRun);
5362
5406
  console.log(`[agendex] ${dryRun ? "would install" : "installed"} ${agent} hook: ${path}`);
5363
5407
  }
5364
5408
  return 0;
@@ -5448,7 +5492,7 @@ async function syncAll(force = false) {
5448
5492
  // src/upgrade.ts
5449
5493
  import { spawn as spawn3, spawnSync } from "node:child_process";
5450
5494
  import { realpathSync as realpathSync2 } from "node:fs";
5451
- import { dirname as dirname5, resolve as resolve8, sep as sep4 } from "node:path";
5495
+ import { dirname as dirname5, resolve as resolve9, sep as sep4 } from "node:path";
5452
5496
  import { fileURLToPath as fileURLToPath2 } from "node:url";
5453
5497
 
5454
5498
  // src/version.ts
@@ -5458,7 +5502,7 @@ import { join as join15 } from "node:path";
5458
5502
  // package.json
5459
5503
  var package_default = {
5460
5504
  name: "agendex-cli",
5461
- version: "1.1.0",
5505
+ version: "1.2.0",
5462
5506
  description: "Agendex CLI for login, sync, and daemon workflows",
5463
5507
  homepage: "https://github.com/Tyru5/Agendex#readme",
5464
5508
  bugs: {
@@ -5581,9 +5625,9 @@ var PACKAGE_NAME = "agendex-cli";
5581
5625
  var moduleDir = dirname5(fileURLToPath2(import.meta.url));
5582
5626
  function getPackageRoot() {
5583
5627
  try {
5584
- return realpathSync2(resolve8(moduleDir, ".."));
5628
+ return realpathSync2(resolve9(moduleDir, ".."));
5585
5629
  } catch {
5586
- return resolve8(moduleDir, "..");
5630
+ return resolve9(moduleDir, "..");
5587
5631
  }
5588
5632
  }
5589
5633
  function detectPackageManager(packageRoot) {
@@ -5765,9 +5809,120 @@ async function runUpgrade(opts) {
5765
5809
  });
5766
5810
  }
5767
5811
 
5812
+ // src/upload.ts
5813
+ import { readFile as readFile8, stat as stat8 } from "node:fs/promises";
5814
+ import { existsSync as existsSync12 } from "node:fs";
5815
+ import { hostname as osHostname4 } from "node:os";
5816
+ function resolveAgentOverride(args) {
5817
+ const idx = args.indexOf("--agent");
5818
+ if (idx === -1)
5819
+ return;
5820
+ const value = args[idx + 1];
5821
+ if (value === undefined || value.startsWith("--"))
5822
+ return "missing";
5823
+ return value;
5824
+ }
5825
+ function resolvePathArg(args) {
5826
+ for (let i = 0;i < args.length; i++) {
5827
+ const a = args[i];
5828
+ if (a === undefined)
5829
+ continue;
5830
+ if (a === "upload" || a === "--dev" || a === "--open")
5831
+ continue;
5832
+ if (a === "--agent") {
5833
+ i++;
5834
+ continue;
5835
+ }
5836
+ if (a.startsWith("--"))
5837
+ continue;
5838
+ return a;
5839
+ }
5840
+ return;
5841
+ }
5842
+ async function runUpload(args, deps) {
5843
+ const syncPlanFn = deps?.syncPlan ?? syncPlan;
5844
+ const log = deps?.log ?? ((m) => console.log(m));
5845
+ const error = deps?.error ?? ((m) => console.error(m));
5846
+ const openBrowser2 = deps?.openBrowser ?? launchBrowser;
5847
+ const pathArg = resolvePathArg(args);
5848
+ if (!pathArg || !pathArg.trim()) {
5849
+ error("[agendex] usage: agendex upload <path> [--agent <name>] [--open]");
5850
+ return 1;
5851
+ }
5852
+ const absolutePath = resolveCustomPlanDirPath(pathArg);
5853
+ if (!existsSync12(absolutePath)) {
5854
+ error(`[agendex] path does not exist: ${absolutePath}`);
5855
+ return 1;
5856
+ }
5857
+ let stats;
5858
+ try {
5859
+ stats = await stat8(absolutePath);
5860
+ } catch (err) {
5861
+ error(`[agendex] could not read path: ${err instanceof Error ? err.message : String(err)}`);
5862
+ return 1;
5863
+ }
5864
+ if (stats.isDirectory()) {
5865
+ error(`[agendex] path is a directory, expected a single file: ${absolutePath}`);
5866
+ return 1;
5867
+ }
5868
+ if (!/\.md$/i.test(absolutePath)) {
5869
+ error(`[agendex] only Markdown (.md) files are supported: ${absolutePath}`);
5870
+ return 1;
5871
+ }
5872
+ const config = loadConfig();
5873
+ if (!config?.cloudToken || !config?.convexUrl) {
5874
+ error("[agendex] not logged in. Run `agendex login` first.");
5875
+ return 1;
5876
+ }
5877
+ let content;
5878
+ try {
5879
+ content = await readFile8(absolutePath, "utf-8");
5880
+ } catch (err) {
5881
+ error(`[agendex] could not read file: ${err instanceof Error ? err.message : String(err)}`);
5882
+ return 1;
5883
+ }
5884
+ const agentOverride = resolveAgentOverride(args);
5885
+ if (agentOverride === "missing") {
5886
+ error("[agendex] usage: agendex upload <path> [--agent <name>] [--open]");
5887
+ error("[agendex] --agent requires a name");
5888
+ return 1;
5889
+ }
5890
+ const ipAddress = await shouldIncludeLocalIpAddressInSync() ? getLocalIpAddress() : undefined;
5891
+ const payload = fileToSyncPayload(absolutePath, content, {
5892
+ agentOverride,
5893
+ deviceId: config.deviceId ?? loadOrCreateDeviceId(),
5894
+ hostname: osHostname4(),
5895
+ ipAddress,
5896
+ createdAt: stats.birthtime.getTime(),
5897
+ updatedAt: stats.mtime.getTime()
5898
+ });
5899
+ const result = await syncPlanFn(payload);
5900
+ if (!result.ok) {
5901
+ if (result.status === 403) {
5902
+ error(`[agendex] ${result.error ?? "Cloud Pro subscription required"}`);
5903
+ error(`[agendex] View plans and pricing: ${getSiteUrl().replace(/\/$/, "")}/#pricing`);
5904
+ return 1;
5905
+ }
5906
+ error(`[agendex] upload failed: ${result.error ?? "unknown error"}`);
5907
+ return 1;
5908
+ }
5909
+ if (result.skippedLowValue) {
5910
+ log(`[agendex] "${payload.title}" was skipped as a low-value plan and was not stored in the cloud.`);
5911
+ return 0;
5912
+ }
5913
+ const site = getSiteUrl().replace(/\/$/, "");
5914
+ const planUrl = result.planId ? `${site}/dashboard?plan=${encodeURIComponent(result.planId)}` : `${site}/dashboard`;
5915
+ log(`[agendex] uploaded "${payload.title}"`);
5916
+ log(`[agendex] ${planUrl}`);
5917
+ if (args.includes("--open")) {
5918
+ openBrowser2(planUrl, "uploaded plan in your browser");
5919
+ }
5920
+ return 0;
5921
+ }
5922
+
5768
5923
  // src/web.ts
5769
5924
  async function openAgendexWeb(siteUrlOverride) {
5770
- const base = siteUrlOverride ?? getDefaultSiteUrl();
5925
+ const base = siteUrlOverride ?? getSiteUrl();
5771
5926
  const url = base.replace(/\/$/, "");
5772
5927
  launchBrowser(url, "Agendex in your browser");
5773
5928
  }
@@ -5802,7 +5957,7 @@ function firstCommandToken(argv) {
5802
5957
  return;
5803
5958
  }
5804
5959
  var command = firstCommandToken(args) ?? "start";
5805
- var cliEntry = resolve9(process.argv[1] ?? fileURLToPath3(import.meta.url));
5960
+ var cliEntry = resolve10(process.argv[1] ?? fileURLToPath3(import.meta.url));
5806
5961
  async function main() {
5807
5962
  const isInternal = args.includes("--daemon") || args.includes("--worker");
5808
5963
  if (command === "--version" || command === "-v") {
@@ -5822,6 +5977,7 @@ async function main() {
5822
5977
  "add-dir",
5823
5978
  "remove-dir",
5824
5979
  "list-dirs",
5980
+ "upload",
5825
5981
  "upgrade",
5826
5982
  "help",
5827
5983
  "--help",
@@ -5922,6 +6078,9 @@ async function main() {
5922
6078
  await syncAll(force);
5923
6079
  return 0;
5924
6080
  }
6081
+ case "upload": {
6082
+ return await runUpload(args);
6083
+ }
5925
6084
  case "hooks": {
5926
6085
  return await runHooksCommand(args, cliEntry);
5927
6086
  }
@@ -6010,7 +6169,7 @@ async function main() {
6010
6169
  return 1;
6011
6170
  }
6012
6171
  const resolved = resolveCustomPlanDirPath(dirPath);
6013
- if (!existsSync12(resolved)) {
6172
+ if (!existsSync13(resolved)) {
6014
6173
  writeStderr(`[agendex] path does not exist: ${resolved}`);
6015
6174
  return 1;
6016
6175
  }
@@ -6029,7 +6188,7 @@ async function main() {
6029
6188
  const { request } = await import("node:http");
6030
6189
  const body = JSON.stringify({ path: resolved });
6031
6190
  try {
6032
- const res = await new Promise((resolve10, reject) => {
6191
+ const res = await new Promise((resolve11, reject) => {
6033
6192
  const req = request(`http://localhost:${port}/api/v1/plan-sources`, {
6034
6193
  method: "POST",
6035
6194
  headers: {
@@ -6043,7 +6202,7 @@ async function main() {
6043
6202
  res2.on("data", (chunk) => {
6044
6203
  data += chunk;
6045
6204
  });
6046
- res2.on("end", () => resolve10({ status: res2.statusCode ?? 0, body: data }));
6205
+ res2.on("end", () => resolve11({ status: res2.statusCode ?? 0, body: data }));
6047
6206
  res2.on("error", reject);
6048
6207
  });
6049
6208
  req.on("error", reject);
@@ -6203,6 +6362,9 @@ Usage:
6203
6362
  agendex list-dirs List custom plan directories
6204
6363
  agendex sync One-shot scan + sync to cloud (skips unchanged plans)
6205
6364
  agendex sync --force Re-sync all plans, ignoring cache
6365
+ agendex upload <path> Upload a single Markdown plan file to the cloud
6366
+ agendex upload <path> --agent <name> Override the uploaded plan's agent label
6367
+ agendex upload <path> --open Open the uploaded plan in the browser after upload
6206
6368
  agendex cleanup Interactively remove cloud daemons
6207
6369
  agendex cleanup --stale Auto-remove all stale daemons
6208
6370
  agendex status Show current config state + daemon status
@@ -6236,13 +6398,13 @@ function flushStream(stream) {
6236
6398
  if (stream.destroyed || !stream.writable) {
6237
6399
  return Promise.resolve();
6238
6400
  }
6239
- return new Promise((resolve10, reject) => {
6401
+ return new Promise((resolve11, reject) => {
6240
6402
  stream.write("", (error) => {
6241
6403
  if (error) {
6242
6404
  reject(error);
6243
6405
  return;
6244
6406
  }
6245
- resolve10();
6407
+ resolve11();
6246
6408
  });
6247
6409
  });
6248
6410
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agendex-cli",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Agendex CLI for login, sync, and daemon workflows",
5
5
  "homepage": "https://github.com/Tyru5/Agendex#readme",
6
6
  "repository": {