@launchchair/agent 0.4.0 → 0.4.2

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/AGENTS.md CHANGED
@@ -28,7 +28,7 @@ Fresh LaunchChair projects often do not have a local repo yet. Before Stack Setu
28
28
 
29
29
  ## Bridge And Runner Files
30
30
 
31
- Download these into a stable local folder such as `~/launchchair-agent` or `~/.hermes/launchchair-mcp`:
31
+ Download these into a stable local folder such as `~/launchchair-agent`:
32
32
 
33
33
  ```bash
34
34
  mkdir -p "$HOME/launchchair-agent"
@@ -57,28 +57,37 @@ fi
57
57
 
58
58
  The final block creates a tiny project-local `AGENTS.md` pointer only when the target folder does not already have one. It helps fresh Codex chats auto-load the LaunchChair instructions without overwriting a real project instruction file.
59
59
 
60
- ## Optional CLI
60
+ ## CLI
61
61
 
62
- MCP-only setup is still supported. Use `mcp-bridge-server.mjs` when the desktop agent exposes LaunchChair MCP tools. Use `launchchair-cli.mjs` when you need quick diagnostics, project discovery, retry-safe project creation, MCP config output, or a simple way to start the local bridge.
62
+ The npm CLI is the recommended setup path for Codex Desktop and Claude Desktop. It can log in through LaunchChair, save the token locally, print paste-ready MCP config, write Claude Desktop config, and start the local bridge.
63
63
 
64
64
  ```bash
65
- node "$HOME/launchchair-agent/launchchair-cli.mjs" doctor
66
- node "$HOME/launchchair-agent/launchchair-cli.mjs" login
67
- node "$HOME/launchchair-agent/launchchair-cli.mjs" projects --query LeafLore
68
- node "$HOME/launchchair-agent/launchchair-cli.mjs" create --name SignalLift --one-liner "Distribution workspace for technical founders" --project-type b2b --idempotency-key signallift-v1
69
- node "$HOME/launchchair-agent/launchchair-cli.mjs" run-once
70
- node "$HOME/launchchair-agent/launchchair-cli.mjs" bridge
71
- node "$HOME/launchchair-agent/launchchair-cli.mjs" mcp-config codex
65
+ npm install -g @launchchair/agent
66
+ launchchair login
67
+ launchchair setup codex --cwd /absolute/path/to/repo-or-empty-folder --write-config
68
+ launchchair setup claude --cwd /absolute/path/to/repo-or-empty-folder --write-config
69
+ launchchair projects --query LeafLore
70
+ launchchair create --name SignalLift --one-liner "Distribution workspace for technical founders" --project-type b2b --idempotency-key signallift-v1
71
+ launchchair run-once
72
+ launchchair bridge
73
+ launchchair mcp-config codex --ui-fields
72
74
  ```
73
75
 
74
- ## Required Environment Variables
76
+ If Codex Desktop is being configured through the custom MCP form instead of `~/.codex/config.toml`, run:
77
+
78
+ ```bash
79
+ launchchair setup codex --cwd /absolute/path/to/repo-or-empty-folder --copy-config
80
+ ```
81
+
82
+ ## Environment Variables
75
83
 
76
84
  ```bash
77
85
  LAUNCHCHAIR_BASE_URL="https://www.launchchair.io"
78
- LAUNCHCHAIR_AGENT_TOKEN="<full lc_at token from LaunchChair Settings API Access>"
79
86
  LAUNCHCHAIR_PROJECT_ID="optional project UUID; omit or leave blank if creating or discovering a project"
80
87
  ```
81
88
 
89
+ `launchchair login` is the recommended token path. It saves the token to `~/.launchchair/config.json`, and `launchchair mcp-server` reads that saved token. Use `LAUNCHCHAIR_AGENT_TOKEN` only as a manual fallback when browser login is skipped or a per-client token override is needed.
90
+
82
91
  For Codex Desktop local runs:
83
92
 
84
93
  ```bash
@@ -101,18 +110,26 @@ The build folder can be an empty scratch folder until Stack Setup creates or rec
101
110
 
102
111
  ```toml
103
112
  [mcp_servers.launchchair]
104
- command = "node"
105
- args = ["/Users/you/launchchair-agent/mcp-bridge-server.mjs"]
113
+ command = "launchchair"
114
+ args = ["mcp-server"]
115
+ required = true
116
+ startup_timeout_sec = 20
117
+ tool_timeout_sec = 3600
118
+ default_tools_approval_mode = "approve"
106
119
 
107
120
  [mcp_servers.launchchair.env]
108
121
  LAUNCHCHAIR_BASE_URL = "https://www.launchchair.io"
109
- LAUNCHCHAIR_AGENT_TOKEN = "<full lc_at token from Settings API Access>"
110
122
  LAUNCHCHAIR_PROJECT_ID = ""
111
123
  LC_AGENT_ROUTER_GPT_TARGET = "codex"
112
124
  LC_AGENT_ROUTER_CODEX_TARGET = "codex"
113
125
  LC_AGENT_CODEX_CWD = "/absolute/path/to/the-folder-codex-should-build-into"
126
+
127
+ # Optional fallback if launchchair login was skipped:
128
+ # LAUNCHCHAIR_AGENT_TOKEN = "<full lc_at token from Settings API Access>"
114
129
  ```
115
130
 
131
+ If the desktop app cannot find `launchchair`, run `which launchchair` in Terminal and use that absolute path as the MCP command.
132
+
116
133
  ## What To Do First In A Fresh Chat
117
134
 
118
135
  1. If LaunchChair MCP tools are available, call `launchchair_heartbeat`.
@@ -229,7 +246,7 @@ Call launchchair_run_once.
229
246
  Run one queued UI job from CLI:
230
247
 
231
248
  ```bash
232
- node "$HOME/launchchair-agent/launchchair-cli.mjs" run-once
249
+ launchchair run-once
233
250
  ```
234
251
 
235
252
  Select a generated wedge:
package/README.md CHANGED
@@ -49,18 +49,24 @@ Tokens are masked in CLI output. Do not paste real tokens into public docs, scre
49
49
 
50
50
  ## Guided Setup
51
51
 
52
- Use `setup` as the easiest path. It saves the build folder, writes a small `AGENTS.md` pointer into that folder, starts browser login when no token is saved yet, prints the MCP config for your desktop agent, and tells you exactly what to do next.
52
+ Use `setup` as the easiest path. It saves the build folder, writes a small `AGENTS.md` pointer into that folder, starts browser login when no token is saved yet, writes or prints the MCP config for your desktop agent, and tells you exactly what to do next.
53
53
 
54
54
  Codex Desktop:
55
55
 
56
56
  ```bash
57
- launchchair setup codex --cwd /absolute/path/to/repo-or-empty-folder
57
+ launchchair setup codex --cwd /absolute/path/to/repo-or-empty-folder --write-config
58
+ ```
59
+
60
+ If you prefer Codex Desktop's custom MCP form, copy paste-ready fields instead:
61
+
62
+ ```bash
63
+ launchchair setup codex --cwd /absolute/path/to/repo-or-empty-folder --copy-config
58
64
  ```
59
65
 
60
66
  Claude Desktop + Claude Code:
61
67
 
62
68
  ```bash
63
- launchchair setup claude --cwd /absolute/path/to/repo-or-empty-folder
69
+ launchchair setup claude --cwd /absolute/path/to/repo-or-empty-folder --write-config
64
70
  ```
65
71
 
66
72
  Terminal / CLI agents:
@@ -83,8 +89,8 @@ Use `setup terminal` when the agent runs inside a normal shell instead of Codex
83
89
  ## Common Commands
84
90
 
85
91
  ```bash
86
- launchchair setup codex --cwd /absolute/path/to/repo-or-empty-folder
87
- launchchair setup claude --cwd /absolute/path/to/repo-or-empty-folder
92
+ launchchair setup codex --cwd /absolute/path/to/repo-or-empty-folder --write-config
93
+ launchchair setup claude --cwd /absolute/path/to/repo-or-empty-folder --write-config
88
94
  launchchair setup terminal --cwd /absolute/path/to/repo-or-empty-folder
89
95
  launchchair projects
90
96
  launchchair projects --query LeafLore
@@ -94,6 +100,7 @@ launchchair continue --completion-target "rerun Product Ideation until ICP Pain
94
100
  launchchair run-once
95
101
  launchchair bridge
96
102
  launchchair mcp-config codex
103
+ launchchair mcp-config codex --ui-fields --copy-config
97
104
  launchchair mcp-config claude
98
105
  launchchair install-agent-md --cwd /absolute/path/to/repo-or-empty-folder
99
106
  ```
@@ -127,6 +134,7 @@ Print a Codex MCP config example:
127
134
 
128
135
  ```bash
129
136
  launchchair mcp-config codex
137
+ launchchair mcp-config codex --ui-fields
130
138
  ```
131
139
 
132
140
  Print a Claude Desktop MCP config example:
@@ -135,9 +143,9 @@ Print a Claude Desktop MCP config example:
135
143
  launchchair mcp-config claude
136
144
  ```
137
145
 
138
- The printed config intentionally uses a token placeholder. Paste your real `lc_at_` token into your MCP client config when the desktop client launches MCP directly, or use `launchchair login` for CLI-started bridge sessions.
146
+ The recommended config launches `launchchair mcp-server`. That process reads the token saved by `launchchair login`, so Codex and Claude users do not need to paste tokens into MCP config after browser login.
139
147
 
140
- Desktop MCP clients do not automatically inherit the token saved by `launchchair login` unless they launch through a CLI-managed bridge process. For direct MCP config, put the token in that client config's `env` block.
148
+ Use `LAUNCHCHAIR_AGENT_TOKEN` only as a manual fallback when you skip `launchchair login`, need a per-client token override, or your desktop app cannot read the saved CLI config. If a desktop app cannot find `launchchair`, run `which launchchair` and use that absolute path as the MCP command.
141
149
 
142
150
  ## Local Bridge
143
151
 
@@ -8,14 +8,14 @@
8
8
  * project discovery/creation, and local bridge control.
9
9
  */
10
10
 
11
- import { spawn } from "node:child_process";
12
- import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
11
+ import { spawn, spawnSync } from "node:child_process";
12
+ import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
13
13
  import os from "node:os";
14
14
  import path from "node:path";
15
15
  import process from "node:process";
16
16
  import { fileURLToPath } from "node:url";
17
17
 
18
- const VERSION = "0.4.0";
18
+ const VERSION = "0.4.2";
19
19
  const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url));
20
20
  const DEFAULT_BASE_URL = "https://www.launchchair.io";
21
21
  const CONFIG_DIR = process.env.LAUNCHCHAIR_CONFIG_DIR?.trim()
@@ -163,11 +163,13 @@ Commands:
163
163
  continue [--project-id ID] Ask LaunchChair to continue the project loop once
164
164
  run-once Claim and run one queued LaunchChair job through the local bridge
165
165
  bridge Start the long-running local bridge for Run with Agent
166
+ mcp-server Run the stdio MCP server using saved CLI config
166
167
  setup codex|claude|terminal [options]
167
168
  Guided setup for CLI, CWD, AGENTS.md, MCP config, and bridge
168
169
  config Show local CLI config without printing the token
169
170
  config set KEY VALUE Save base-url, project-id, codex-cwd, or claude-code-cwd
170
- mcp-config codex|claude Print MCP config with current paths/defaults
171
+ mcp-config codex|claude [options]
172
+ Print MCP config or Codex custom MCP form fields
171
173
  install-agent-md [--cwd PATH] Create a small AGENTS.md pointer in a fresh repo
172
174
 
173
175
  Create options:
@@ -207,6 +209,9 @@ Setup options:
207
209
  --no-open During setup login, print the approval URL instead of opening a browser
208
210
  --timeout SECONDS During setup login, approval timeout. Default: 600
209
211
  --start-bridge Start the local bridge after setup
212
+ --copy-config Copy generated MCP setup output to clipboard on macOS
213
+ --ui-fields Print Codex custom MCP form fields instead of raw config
214
+ --write-config Write/update Codex or Claude Desktop MCP config when supported
210
215
 
211
216
  Login options:
212
217
  --token TOKEN Manual fallback: save an existing lc_at token
@@ -223,6 +228,10 @@ Env:
223
228
  LC_AGENT_CODEX_CWD Folder Codex should build into
224
229
  LC_AGENT_CLAUDE_CODE_CWD Folder Claude Code should build into
225
230
 
231
+ MCP config options:
232
+ --ui-fields Print fields for Codex Desktop's custom MCP form
233
+ --copy-config Copy generated output to clipboard on macOS
234
+
226
235
  Config:
227
236
  ${CONFIG_PATH}
228
237
  `);
@@ -731,51 +740,185 @@ function spawnBridge(extraArgs = []) {
731
740
  });
732
741
  }
733
742
 
734
- function renderMcpConfig(target) {
743
+ function spawnMcpServer(extraArgs = []) {
735
744
  const bridgePath = path.join(SCRIPT_DIR, "mcp-bridge-server.mjs");
736
- const agentTokenPlaceholder = "<full lc_at token from LaunchChair Settings API Access>";
737
- const projectId = defaultProjectId() || "optional-if-agent-creates-project";
738
- if (target === "claude") {
745
+ const child = spawn(process.execPath, [bridgePath, ...extraArgs], {
746
+ stdio: "inherit",
747
+ env: buildBridgeEnv(),
748
+ });
749
+ child.on("exit", (code) => {
750
+ process.exit(code ?? 0);
751
+ });
752
+ }
753
+
754
+ function normalizedMcpTarget(target) {
755
+ return targetDetails(target || "codex").mcpTarget || "codex";
756
+ }
757
+
758
+ function tomlString(value) {
759
+ return JSON.stringify(String(value ?? ""));
760
+ }
761
+
762
+ function mcpEnvForTarget(target, options = {}) {
763
+ const includeTokenPlaceholder = options.includeTokenPlaceholder !== false;
764
+ const details = targetDetails(target || "codex");
765
+ const projectId = defaultProjectId();
766
+ const cwd = configValue(details.cwdConfigKey, [details.cwdEnvName], "/absolute/path/to/repo-or-empty-folder");
767
+ const envBlock = {
768
+ LAUNCHCHAIR_BASE_URL: baseUrl(),
769
+ ...(token() || !includeTokenPlaceholder ? {} : { LAUNCHCHAIR_AGENT_TOKEN: "<optional full lc_at token when launchchair login was not used>" }),
770
+ ...(projectId ? { LAUNCHCHAIR_PROJECT_ID: projectId } : {}),
771
+ LC_AGENT_ROUTER_GPT_TARGET: details.routerTarget,
772
+ LC_AGENT_ROUTER_CODEX_TARGET: details.routerTarget,
773
+ [details.cwdEnvName]: cwd,
774
+ };
775
+ return Object.fromEntries(Object.entries(envBlock).filter(([, value]) => String(value ?? "").trim()));
776
+ }
777
+
778
+ function mcpServerConfig(target, options = {}) {
779
+ return {
780
+ command: "launchchair",
781
+ args: ["mcp-server"],
782
+ env: mcpEnvForTarget(target, options),
783
+ };
784
+ }
785
+
786
+ function renderMcpConfig(target, options = {}) {
787
+ const normalized = normalizedMcpTarget(target);
788
+ const server = mcpServerConfig(normalized, options);
789
+ if (normalized === "claude") {
739
790
  return JSON.stringify(
740
791
  {
741
792
  mcpServers: {
742
- launchchair: {
743
- command: "node",
744
- args: [bridgePath],
745
- env: {
746
- LAUNCHCHAIR_BASE_URL: baseUrl(),
747
- LAUNCHCHAIR_AGENT_TOKEN: agentTokenPlaceholder,
748
- LAUNCHCHAIR_PROJECT_ID: projectId,
749
- LC_AGENT_ROUTER_GPT_TARGET: "claude_code",
750
- LC_AGENT_ROUTER_CODEX_TARGET: "claude_code",
751
- LC_AGENT_CLAUDE_CODE_CWD: configValue("claudeCodeCwd", ["LC_AGENT_CLAUDE_CODE_CWD"], "/absolute/path/to/repo-or-empty-folder"),
752
- },
753
- },
793
+ launchchair: server,
754
794
  },
755
795
  },
756
796
  null,
757
797
  2,
758
798
  );
759
799
  }
800
+ const envLines = Object.entries(server.env)
801
+ .map(([key, value]) => `${key} = ${tomlString(value)}`)
802
+ .join("\n");
760
803
  return `[mcp_servers.launchchair]
761
- command = "node"
762
- args = ["${bridgePath}"]
763
- required = true
804
+ command = "launchchair"
805
+ args = ["mcp-server"]
806
+ required = false
764
807
  startup_timeout_sec = 20
765
808
  tool_timeout_sec = 3600
766
809
  default_tools_approval_mode = "approve"
767
810
 
768
811
  [mcp_servers.launchchair.env]
769
- LAUNCHCHAIR_BASE_URL = "${baseUrl()}"
770
- LAUNCHCHAIR_AGENT_TOKEN = "${agentTokenPlaceholder}"
771
- LAUNCHCHAIR_PROJECT_ID = "${projectId}"
772
- LC_AGENT_ROUTER_GPT_TARGET = "codex"
773
- LC_AGENT_ROUTER_CODEX_TARGET = "codex"
774
- LC_AGENT_CODEX_CWD = "${configValue("codexCwd", ["LC_AGENT_CODEX_CWD"], "/absolute/path/to/repo-or-empty-folder")}"`;
812
+ ${envLines}`;
813
+ }
814
+
815
+ function renderMcpUiFields(target) {
816
+ const normalized = normalizedMcpTarget(target);
817
+ const details = targetDetails(normalized);
818
+ const server = mcpServerConfig(normalized);
819
+ const envLines =
820
+ Object.entries(server.env)
821
+ .map(([key, value]) => ` ${key} = ${value}`)
822
+ .join("\n") || " (none)";
823
+ const workingDir = server.env[details.cwdEnvName] || process.cwd();
824
+ return `Name
825
+ launchchair
826
+
827
+ Type
828
+ STDIO
829
+
830
+ Command to launch
831
+ ${server.command}
832
+
833
+ Arguments
834
+ ${server.args.join(" ")}
835
+
836
+ Environment variables
837
+ ${envLines}
838
+
839
+ Working directory
840
+ ${workingDir}`;
841
+ }
842
+
843
+ function copyToClipboard(text) {
844
+ if (process.platform !== "darwin") return false;
845
+ const result = spawnSync("pbcopy", { input: text, encoding: "utf8" });
846
+ return result.status === 0;
847
+ }
848
+
849
+ function claudeDesktopConfigPath() {
850
+ return path.join(os.homedir() || process.cwd(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
851
+ }
852
+
853
+ function codexConfigPath() {
854
+ return path.join(os.homedir() || process.cwd(), ".codex", "config.toml");
775
855
  }
776
856
 
777
- function printMcpConfig(target) {
778
- print(renderMcpConfig(target));
857
+ function removeCodexLaunchChairTables(raw) {
858
+ const lines = String(raw || "").split(/\r?\n/);
859
+ const kept = [];
860
+ let skipping = false;
861
+
862
+ for (const line of lines) {
863
+ const tableName = line.match(/^\s*\[([^\]]+)\]\s*$/)?.[1] ?? "";
864
+ if (tableName) {
865
+ if (tableName === "mcp_servers.launchchair" || tableName === "mcp_servers.launchchair.env") {
866
+ skipping = true;
867
+ continue;
868
+ }
869
+ skipping = false;
870
+ }
871
+ if (!skipping) kept.push(line);
872
+ }
873
+
874
+ return kept.join("\n").replace(/\n{3,}$/g, "\n\n").trimEnd();
875
+ }
876
+
877
+ function writeCodexConfig() {
878
+ const configPath = codexConfigPath();
879
+ mkdirSync(path.dirname(configPath), { recursive: true });
880
+ let current = "";
881
+ if (existsSync(configPath)) {
882
+ current = readFileSync(configPath, "utf8");
883
+ const backupPath = `${configPath}.launchchair-backup-${Date.now()}`;
884
+ copyFileSync(configPath, backupPath);
885
+ ok(`Backed up existing Codex config to ${backupPath}`);
886
+ }
887
+ const preserved = removeCodexLaunchChairTables(current);
888
+ const next = `${preserved ? `${preserved}\n\n` : ""}${renderMcpConfig("codex", { includeTokenPlaceholder: false })}\n`;
889
+ writeFileSync(configPath, next);
890
+ return configPath;
891
+ }
892
+
893
+ function writeClaudeDesktopConfig() {
894
+ const configPath = claudeDesktopConfigPath();
895
+ mkdirSync(path.dirname(configPath), { recursive: true });
896
+ let current = {};
897
+ if (existsSync(configPath)) {
898
+ const raw = readFileSync(configPath, "utf8");
899
+ current = raw.trim() ? JSON.parse(raw) : {};
900
+ const backupPath = `${configPath}.launchchair-backup-${Date.now()}`;
901
+ copyFileSync(configPath, backupPath);
902
+ ok(`Backed up existing Claude config to ${backupPath}`);
903
+ }
904
+ const next = {
905
+ ...current,
906
+ mcpServers: {
907
+ ...(current.mcpServers ?? {}),
908
+ launchchair: mcpServerConfig("claude", { includeTokenPlaceholder: false }),
909
+ },
910
+ };
911
+ writeFileSync(configPath, `${JSON.stringify(next, null, 2)}\n`);
912
+ return configPath;
913
+ }
914
+
915
+ function printMcpConfig(target, args = {}) {
916
+ const output = args["ui-fields"] === true || args["print-ui-fields"] === true ? renderMcpUiFields(target) : renderMcpConfig(target);
917
+ print(output);
918
+ if (args["copy-config"] === true) {
919
+ if (copyToClipboard(output)) ok("Copied MCP setup output to clipboard.");
920
+ else warn("Could not copy MCP setup output automatically on this platform.");
921
+ }
779
922
  }
780
923
 
781
924
  function showConfig() {
@@ -947,8 +1090,23 @@ async function setup(args) {
947
1090
  print(` ${paint("launchchair run-once", "cyan")}`);
948
1091
  print(` ${paint("launchchair bridge", "cyan")}`);
949
1092
  } else {
950
- title("MCP config to paste");
951
- print(renderMcpConfig(details.mcpTarget));
1093
+ if (details.mcpTarget === "codex" && args["write-config"] === true) {
1094
+ const configPath = writeCodexConfig();
1095
+ title("Codex MCP config updated");
1096
+ ok(`Wrote LaunchChair MCP server to ${configPath}`);
1097
+ } else if (details.mcpTarget === "claude" && args["write-config"] === true) {
1098
+ const configPath = writeClaudeDesktopConfig();
1099
+ title("Claude MCP config updated");
1100
+ ok(`Wrote LaunchChair MCP server to ${configPath}`);
1101
+ } else {
1102
+ const output = details.mcpTarget === "codex" || args["ui-fields"] === true ? renderMcpUiFields(details.mcpTarget) : renderMcpConfig(details.mcpTarget);
1103
+ title(details.mcpTarget === "codex" || args["ui-fields"] === true ? "MCP fields to paste" : "MCP config to paste");
1104
+ print(output);
1105
+ if (args["copy-config"] === true) {
1106
+ if (copyToClipboard(output)) ok("Copied MCP setup output to clipboard.");
1107
+ else warn("Could not copy MCP setup output automatically on this platform.");
1108
+ }
1109
+ }
952
1110
  }
953
1111
 
954
1112
  print("");
@@ -964,11 +1122,23 @@ async function setup(args) {
964
1122
  print("3. For product/project work, have it use launchchair projects/create/continue before local code discovery.");
965
1123
  print("4. Keep launchchair bridge running only when LaunchChair UI Run with agent jobs should be picked up.");
966
1124
  } else {
967
- print(`1. Paste the MCP config above into ${details.label}.`);
968
- print(`2. Restart or reload ${details.label} so the MCP server is exposed to fresh chats.`);
969
- print("3. Keep this bridge running when you want LaunchChair's Run with agent button to work:");
1125
+ if (details.mcpTarget === "codex" && args["write-config"] === true) {
1126
+ print("1. Restart or reload Codex Desktop so the MCP server is exposed to fresh chats.");
1127
+ print("2. Keep the generated config file under your user profile; it launches the saved LaunchChair CLI token.");
1128
+ } else if (details.mcpTarget === "codex") {
1129
+ print("1. Fill the Codex custom MCP form with the fields above.");
1130
+ print("2. Restart or reload Codex Desktop so the MCP server is exposed to fresh chats.");
1131
+ } else if (details.mcpTarget === "claude" && args["write-config"] === true) {
1132
+ print("1. Restart or reload Claude Desktop so the MCP server is exposed to fresh chats.");
1133
+ print("2. Keep the generated config file under your user profile; it launches the saved LaunchChair CLI token.");
1134
+ } else {
1135
+ print(`1. Paste the MCP config above into ${details.label}.`);
1136
+ print(`2. Restart or reload ${details.label} so the MCP server is exposed to fresh chats.`);
1137
+ }
1138
+ print("3. If the desktop app cannot find launchchair, run `which launchchair` and use that absolute path as the command.");
1139
+ print("4. Keep this bridge running when you want LaunchChair's Run with agent button to work:");
970
1140
  print(` ${paint("launchchair bridge", "cyan")}`);
971
- print("4. Start a fresh agent chat. Codex will discover the LaunchChair skill and MCP server instructions automatically.");
1141
+ print("5. Start a fresh agent chat. The agent should discover the LaunchChair skill and MCP server instructions automatically.");
972
1142
  }
973
1143
  print("");
974
1144
  row("Build folder", cwd, "cyan");
@@ -999,10 +1169,11 @@ async function main() {
999
1169
  if (command === "continue") return continueProject(args);
1000
1170
  if (command === "run-once") return spawnBridge(["--once", "--verbose"]);
1001
1171
  if (command === "bridge") return spawnBridge(["--verbose"]);
1172
+ if (command === "mcp-server") return spawnMcpServer();
1002
1173
  if (command === "setup") return setup(args);
1003
1174
  if (command === "config" && args._[0] === "set") return setConfig({ ...args, _: args._.slice(1) });
1004
1175
  if (command === "config") return showConfig();
1005
- if (command === "mcp-config") return printMcpConfig(args._[0] || "codex");
1176
+ if (command === "mcp-config") return printMcpConfig(args._[0] || "codex", args);
1006
1177
  if (command === "install-agent-md") return installAgentMd(args);
1007
1178
  throw new Error(`Unknown command: ${command}`);
1008
1179
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@launchchair/agent",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "LaunchChair Agent CLI, MCP bridge, local bridge, and runners for Codex, Claude Code, ChatGPT, Claude, and Hermes workflows.",
5
5
  "type": "module",
6
6
  "bin": {