threadnote 0.3.4 → 0.3.5

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
@@ -50,13 +50,13 @@ Install with one command:
50
50
  curl -fsSL https://raw.githubusercontent.com/Kashkovsky/threadnote/main/scripts/install.sh | sh
51
51
  ```
52
52
 
53
- This installs the published package from npmjs and runs `threadnote install`. It does not use npm `postinstall`,
54
- because setup writes local machine config and should be an explicit action.
53
+ This installs the published package from npmjs and runs `threadnote install`. The install command sets up local config,
54
+ repairs the OpenViking Python environment, and starts the local server so health problems surface immediately. It does
55
+ not use npm `postinstall`, because setup writes local machine config and should be an explicit action.
55
56
 
56
- Start the local server and confirm it is healthy:
57
+ Confirm it is healthy:
57
58
 
58
59
  ```bash
59
- threadnote start
60
60
  threadnote doctor --dry-run
61
61
  ```
62
62
 
@@ -74,7 +74,6 @@ Or install manually:
74
74
  ```bash
75
75
  npm install --global threadnote
76
76
  threadnote install
77
- threadnote start
78
77
  threadnote doctor --dry-run
79
78
  ```
80
79
 
@@ -194,7 +193,8 @@ This is it! Start working with your agents as usual. The agent will automaticall
194
193
 
195
194
  - `doctor`: checks prerequisites, the generated command shim, manifest shape, templates, and local OpenViking health.
196
195
  - `install`: installs `openviking[local-embed]==0.3.12` if missing, creates `~/.openviking` config files if absent,
197
- writes the command shim, and upserts user-level agent instructions.
196
+ writes the command shim, upserts user-level agent instructions, and starts/checks OpenViking health by default. Use
197
+ `--no-start` to skip the health check.
198
198
  - `update`: updates the published Threadnote package, then runs `repair` so shims and MCP config point at the new
199
199
  version.
200
200
  - `repair`: fixes install/config/shim/manifest/server health issues and rewrites Codex/Claude/Cursor MCP configs from the
@@ -240,7 +240,6 @@ any repo or working directory:
240
240
  ```bash
241
241
  threadnote doctor --dry-run
242
242
  threadnote init-manifest --repo ~/src/my-service --repo ~/work/mobile-app
243
- threadnote start
244
243
  threadnote seed --dry-run
245
244
  threadnote seed-skills --dry-run
246
245
  ```
@@ -7903,12 +7903,13 @@ Summary: ${failureCount} failure(s), ${warningCount} warning(s)`);
7903
7903
  }
7904
7904
  async function runInstall(config, options) {
7905
7905
  const repairInvalidConfigs = options.repairInvalidConfigs === true;
7906
- await ensureDirectory(config.agentContextHome, options.dryRun === true);
7907
- await ensureDirectory((0, import_node_path6.join)(config.agentContextHome, "logs"), options.dryRun === true);
7908
- await ensureDirectory((0, import_node_path6.join)(config.agentContextHome, "redacted"), options.dryRun === true);
7909
- await ensureDirectory((0, import_node_path6.join)(config.agentContextHome, "mcp"), options.dryRun === true);
7910
- await installCommandShim(options.dryRun === true);
7911
- await installUserAgentInstructions(options.dryRun === true);
7906
+ const dryRun = options.dryRun === true;
7907
+ await ensureDirectory(config.agentContextHome, dryRun);
7908
+ await ensureDirectory((0, import_node_path6.join)(config.agentContextHome, "logs"), dryRun);
7909
+ await ensureDirectory((0, import_node_path6.join)(config.agentContextHome, "redacted"), dryRun);
7910
+ await ensureDirectory((0, import_node_path6.join)(config.agentContextHome, "mcp"), dryRun);
7911
+ await installCommandShim(dryRun);
7912
+ await installUserAgentInstructions(dryRun);
7912
7913
  const serverPath = await findExecutable([OPENVIKING_SERVER_COMMAND]);
7913
7914
  if (serverPath) {
7914
7915
  console.log(`OpenViking server already installed: ${serverPath}`);
@@ -7921,37 +7922,49 @@ async function runInstall(config, options) {
7921
7922
  repairReasons.push("Python system certificate bridge is missing");
7922
7923
  }
7923
7924
  console.log(`OpenViking install needs repair: ${repairReasons.join("; ")}.`);
7924
- await runInstallCommands(config, options.packageManager, true, options.dryRun === true);
7925
+ await runInstallCommands(config, options.packageManager, true, dryRun);
7925
7926
  } else if (pythonSystemCertificatesMissing) {
7926
7927
  console.log("OpenViking install needs repair: Python system certificate bridge is missing.");
7927
7928
  const installCommand = await getPythonSystemCertificatesInstallCommand(serverPath);
7928
- await maybeRun(options.dryRun === true, installCommand.executable, installCommand.args);
7929
+ await maybeRun(dryRun, installCommand.executable, installCommand.args);
7929
7930
  }
7930
7931
  } else {
7931
- await runInstallCommands(config, options.packageManager, false, options.dryRun === true);
7932
+ await runInstallCommands(config, options.packageManager, false, dryRun);
7932
7933
  }
7933
7934
  await writeTemplateIfMissing({
7934
7935
  config,
7935
7936
  destinationPath: (0, import_node_path6.join)(config.agentContextHome, "ov.conf"),
7936
- dryRun: options.dryRun === true,
7937
+ dryRun,
7937
7938
  shouldRepair: (content) => shouldRepairOpenVikingConfig(content, config) || repairInvalidConfigs && parseJsonConfigObject(content) === void 0,
7938
7939
  templatePath: (0, import_node_path6.join)(toolRoot(), "config", "ov.conf.template.json")
7939
7940
  });
7940
7941
  await writeTemplateIfMissing({
7941
7942
  config,
7942
7943
  destinationPath: (0, import_node_path6.join)(config.agentContextHome, "ovcli.conf"),
7943
- dryRun: options.dryRun === true,
7944
+ dryRun,
7944
7945
  shouldRepair: (content) => shouldRepairLegacyOvCliConfig(content) || repairInvalidConfigs && parseJsonConfigObject(content) === void 0,
7945
7946
  templatePath: (0, import_node_path6.join)(toolRoot(), "config", "ovcli.conf.template.json")
7946
7947
  });
7947
- console.log("Install complete. Run start, then doctor:");
7948
- console.log(" threadnote start");
7949
- console.log(" threadnote doctor");
7948
+ if (options.start !== false) {
7949
+ const healthy = await repairServerHealth(config, dryRun);
7950
+ if (!healthy && !dryRun) {
7951
+ throw new Error(`OpenViking did not become healthy. Check logs: ${openVikingLogPath(config)}`);
7952
+ }
7953
+ }
7954
+ if (options.printNextSteps !== false) {
7955
+ printInstallNextSteps({ dryRun, startsServer: options.start !== false });
7956
+ }
7950
7957
  }
7951
7958
  async function runRepair(config, options) {
7952
7959
  const dryRun = options.dryRun === true;
7953
7960
  console.log("Repairing local OpenViking agent context from this checkout.");
7954
- await runInstall(config, { dryRun, packageManager: options.packageManager, repairInvalidConfigs: true });
7961
+ await runInstall(config, {
7962
+ dryRun,
7963
+ packageManager: options.packageManager,
7964
+ printNextSteps: false,
7965
+ repairInvalidConfigs: true,
7966
+ start: false
7967
+ });
7955
7968
  await repairManifest(config, dryRun);
7956
7969
  if (options.start !== false) {
7957
7970
  await repairServerHealth(config, dryRun);
@@ -8047,13 +8060,15 @@ async function repairServerHealth(config, dryRun) {
8047
8060
  const existingHealth = await readOpenVikingHealthIfAvailable(config, 800);
8048
8061
  if (existingHealth) {
8049
8062
  console.log(`OpenViking health OK at http://${config.host}:${config.port}/health`);
8050
- return;
8063
+ return true;
8051
8064
  }
8052
8065
  console.log(`OpenViking health is not responding at http://${config.host}:${config.port}/health; starting server.`);
8053
8066
  try {
8054
8067
  await runStart(config, { dryRun });
8068
+ return true;
8055
8069
  } catch (err) {
8056
8070
  console.log(`WARN could not repair OpenViking health: ${errorMessage(err)}`);
8071
+ return false;
8057
8072
  }
8058
8073
  }
8059
8074
  async function runStart(config, options) {
@@ -8385,14 +8400,28 @@ async function getInstallCommands(config, preferred, force) {
8385
8400
  return [{ executable: "python3", args: pipArgs }];
8386
8401
  }
8387
8402
  async function detectPackageManager() {
8388
- if (await findExecutable(["pipx"])) {
8389
- return "pipx";
8390
- }
8391
8403
  if (await findExecutable(["uv"])) {
8392
8404
  return "uv";
8393
8405
  }
8406
+ if (await findExecutable(["pipx"])) {
8407
+ return "pipx";
8408
+ }
8394
8409
  return "pip";
8395
8410
  }
8411
+ function printInstallNextSteps(options) {
8412
+ if (options.dryRun) {
8413
+ console.log("Dry run complete. Run without --dry-run to install and start OpenViking.");
8414
+ return;
8415
+ }
8416
+ if (options.startsServer) {
8417
+ console.log("Install complete. OpenViking health is ready. Next:");
8418
+ console.log(" threadnote doctor --dry-run");
8419
+ return;
8420
+ }
8421
+ console.log("Install complete. Run start, then doctor:");
8422
+ console.log(" threadnote start");
8423
+ console.log(" threadnote doctor --dry-run");
8424
+ }
8396
8425
  async function writeTemplateIfMissing(options) {
8397
8426
  if (await exists(options.destinationPath)) {
8398
8427
  const currentContent = await (0, import_promises6.readFile)(options.destinationPath, "utf8");
@@ -8946,7 +8975,7 @@ async function main() {
8946
8975
  await runDoctor(config, options);
8947
8976
  await maybeNotifyUpdate(config, { dryRun: options.dryRun === true });
8948
8977
  });
8949
- program2.command("install").description("Install OpenViking, local config files, command shim, and user-level agent instructions").option("--dry-run", "Print the actions without making changes").option("--package-manager <manager>", "pipx, uv, or pip", parsePackageManager).action(async (options) => {
8978
+ program2.command("install").description("Install OpenViking, local config files, command shim, and user-level agent instructions").option("--dry-run", "Print the actions without making changes").option("--no-start", "Do not start OpenViking or check server health after installing").option("--package-manager <manager>", "uv, pipx, or pip", parsePackageManager).action(async (options) => {
8950
8979
  const config = getRuntimeConfig(program2);
8951
8980
  await runInstall(config, options);
8952
8981
  await maybeNotifyUpdate(config, { dryRun: options.dryRun === true });
@@ -8958,7 +8987,7 @@ async function main() {
8958
8987
  "--mcp <clients>",
8959
8988
  "MCP clients to repair: available, all, none, codex, claude, cursor, or comma-separated list",
8960
8989
  "available"
8961
- ).option("--no-start", "Do not start OpenViking if health is failing").option("--package-manager <manager>", "pipx, uv, or pip", parsePackageManager).action(async (options) => {
8990
+ ).option("--no-start", "Do not start OpenViking if health is failing").option("--package-manager <manager>", "uv, pipx, or pip", parsePackageManager).action(async (options) => {
8962
8991
  const config = getRuntimeConfig(program2);
8963
8992
  await runRepair(config, options);
8964
8993
  await maybeNotifyUpdate(config, { dryRun: options.dryRun === true });
package/docs/migration.md CHANGED
@@ -90,10 +90,9 @@ paths.
90
90
  `--repo` can be repeated. Paths may be anywhere on the machine. If no `--repo` is provided, the current git repo is
91
91
  used. The manifest is written to `~/.openviking/seed-manifest.yaml` by default and is intentionally not checked in.
92
92
 
93
- 4. Start the local service:
93
+ 4. Verify the local service:
94
94
 
95
95
  ```bash
96
- threadnote start
97
96
  threadnote doctor --dry-run
98
97
  ```
99
98
 
@@ -8,7 +8,7 @@ Run:
8
8
  threadnote install
9
9
  ```
10
10
 
11
- The installer prefers `pipx`, then `uv`, then `python3 -m pip install --user`.
11
+ The installer prefers `uv`, then `pipx`, then `python3 -m pip install --user`.
12
12
 
13
13
  ## `uv` Fails With `UnknownIssuer`
14
14
 
@@ -30,13 +30,13 @@ threadnote install --package-manager pip
30
30
 
31
31
  ## Model Download Fails With `CERTIFICATE_VERIFY_FAILED`
32
32
 
33
- On first start, OpenViking may download the local embedding model from Hugging Face. If `~/.openviking/logs/server.log`
34
- shows `SSLCertVerificationError`, `self-signed certificate in certificate chain`, or `Failed to download local embedding
35
- model`, repair the OpenViking Python environment and start again:
33
+ On install or first start, OpenViking may download the local embedding model from Hugging Face. If
34
+ `~/.openviking/logs/server.log` shows `SSLCertVerificationError`, `self-signed certificate in certificate chain`, or
35
+ `Failed to download local embedding model`, repair the OpenViking Python environment and start again:
36
36
 
37
37
  ```bash
38
38
  threadnote repair --package-manager uv
39
- threadnote start
39
+ threadnote doctor --dry-run
40
40
  ```
41
41
 
42
42
  Threadnote installs `pip-system-certs` into the OpenViking environment so Python `requests` can use certificates trusted
@@ -63,8 +63,8 @@ The installer repairs this by installing `openviking[local-embed]`.
63
63
 
64
64
  ## Server Health Fails
65
65
 
66
- If `doctor` reports `WARN openviking health: connect ECONNREFUSED 127.0.0.1:1933`, the local server is not running.
67
- Start it and recheck:
66
+ Current Threadnote installs start the local server by default. If `doctor` reports
67
+ `WARN openviking health: connect ECONNREFUSED 127.0.0.1:1933`, the local server is not running. Start it and recheck:
68
68
 
69
69
  ```bash
70
70
  threadnote start
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "threadnote",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "type": "commonjs",
5
5
  "main": "dist/threadnote.cjs",
6
6
  "description": "Shared local context and handoffs for development agents",
@@ -126,7 +126,6 @@ fi
126
126
 
127
127
  say ""
128
128
  say "Threadnote is installed. Next:"
129
- say " threadnote start"
130
129
  say " threadnote doctor --dry-run"
131
130
  say " threadnote mcp-install codex --apply # if you use Codex"
132
131
  say " threadnote mcp-install claude --apply # if you use Claude"