claude-tempo 0.3.0-beta.1 → 0.3.0-beta.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/README.md CHANGED
@@ -4,31 +4,7 @@ Multi-session [Claude Code](https://claude.ai/code) coordination via [Temporal](
4
4
 
5
5
  Multiple Claude Code sessions discover each other, exchange messages in real time, and coordinate work — across machines, not just localhost.
6
6
 
7
- ```
8
- You (CLI / Discord / Telegram / Claude Code)
9
-
10
-
11
- ┌─────────────────────────────────────────────┐
12
- │ Temporal Server │
13
- │ │
14
- │ ┌───────────┐ │
15
- │ │ Conductor │──cue──┬──────┬──────┐ │
16
- │ └───────────┘ │ │ │ │
17
- │ ▼ ▼ ▼ │
18
- │ ┌────┐ ┌────┐ ┌────┐ │
19
- │ │ A │ │ B │ │ C │ │
20
- │ └──┬─┘ └──┬─┘ └──┬─┘ │
21
- │ │ │ │ │
22
- └──────────────────────┼──────┼──────┼────────┘
23
- │ │ │
24
- ┌────────┘ │ └────────┐
25
- ▼ ▼ ▼
26
- ┌─────────┐ ┌─────────┐ ┌─────────┐
27
- │ Host 1 │ │ Host 1 │ │ Host 2 │
28
- │ Claude │ │ Claude │ │ Claude │
29
- │ Session │ │ Session │ │ Session │
30
- └─────────┘ └─────────┘ └─────────┘
31
- ```
7
+ Each Claude Code session registers as a **player** in Temporal. Players discover each other with `ensemble`, exchange messages with `cue`, and coordinate work — across machines, not just localhost. An optional **conductor** orchestrates the group and connects to external interfaces like Discord, Telegram, or a dashboard.
32
8
 
33
9
  ## Installation
34
10
 
@@ -42,6 +42,7 @@ const config_1 = require("../config");
42
42
  const connection_1 = require("../connection");
43
43
  const config_2 = require("../config");
44
44
  const out = __importStar(require("./output"));
45
+ const SECRET_KEYS = new Set(['temporalApiKey']);
45
46
  /** Read a line from stdin with a prompt and optional default value. */
46
47
  function ask(prompt, defaultVal, mask = false) {
47
48
  return new Promise((resolve) => {
@@ -178,21 +179,24 @@ function configSet(key, value) {
178
179
  /** Show current config: `claude-tempo config show` */
179
180
  function configShow() {
180
181
  out.heading('claude-tempo config');
181
- const config = (0, config_1.loadConfigFile)();
182
- const resolved = (0, config_2.getConfig)();
183
- const rows = [
184
- ['temporalAddress', resolved.temporalAddress, config.temporalAddress || ''],
185
- ['temporalNamespace', resolved.temporalNamespace, config.temporalNamespace || ''],
186
- ['temporalApiKey', resolved.temporalApiKey ? '****' : '(not set)', config.temporalApiKey ? '****' : ''],
187
- ['temporalTlsCertPath', resolved.temporalTlsCertPath || '(not set)', config.temporalTlsCertPath || ''],
188
- ['temporalTlsKeyPath', resolved.temporalTlsKeyPath || '(not set)', config.temporalTlsKeyPath || ''],
182
+ const { config, sources } = (0, config_1.getConfigWithSources)();
183
+ const keys = [
184
+ { key: 'temporalAddress', configKey: 'temporalAddress' },
185
+ { key: 'temporalNamespace', configKey: 'temporalNamespace' },
186
+ { key: 'temporalApiKey', configKey: 'temporalApiKey' },
187
+ { key: 'temporalTlsCertPath', configKey: 'temporalTlsCertPath' },
188
+ { key: 'temporalTlsKeyPath', configKey: 'temporalTlsKeyPath' },
189
189
  ];
190
190
  out.log(` Config file: ${out.dim(config_1.CONFIG_FILE_PATH)}`);
191
191
  console.log();
192
- out.log(` ${'Key'.padEnd(22)} ${'Resolved'.padEnd(35)} ${out.dim('Config file')}`);
193
- out.log(` ${'─'.repeat(22)} ${'─'.repeat(35)} ${'─'.repeat(20)}`);
194
- for (const [key, resolved, file] of rows) {
195
- out.log(` ${key.padEnd(22)} ${resolved.padEnd(35)} ${out.dim(file || '-')}`);
192
+ out.log(` ${'Key'.padEnd(22)} ${'Value'.padEnd(30)} ${out.dim('Source')}`);
193
+ out.log(` ${'─'.repeat(22)} ${'─'.repeat(30)} ${'─'.repeat(15)}`);
194
+ for (const { key, configKey } of keys) {
195
+ const value = config[configKey];
196
+ const source = sources[configKey];
197
+ const isSecret = SECRET_KEYS.has(key);
198
+ const display = !value ? '(not set)' : isSecret ? '****' : value;
199
+ out.log(` ${key.padEnd(22)} ${display.padEnd(30)} ${out.dim(source)}`);
196
200
  }
197
201
  console.log();
198
202
  }
package/dist/config.d.ts CHANGED
@@ -70,6 +70,16 @@ export interface CliOverrides {
70
70
  * CLI flag > env var > claude-tempo config file > temporal CLI config > defaults
71
71
  */
72
72
  export declare function getConfig(overrides?: CliOverrides): Config;
73
+ export type ConfigSource = 'flag' | 'env' | 'config' | 'temporal-cli' | 'default' | 'none';
74
+ export interface ConfigWithSources {
75
+ config: Config;
76
+ sources: Record<string, ConfigSource>;
77
+ }
78
+ /**
79
+ * Like getConfig(), but also returns which source each value came from.
80
+ * Used by `claude-tempo config show` to help users debug.
81
+ */
82
+ export declare function getConfigWithSources(overrides?: CliOverrides): ConfigWithSources;
73
83
  /** Build a workflow ID for a player session: claude-session-{ensemble}-{playerId} */
74
84
  export declare function sessionWorkflowId(ensemble: string, playerId: string): string;
75
85
  /** Build a workflow ID for a conductor: claude-session-{ensemble}-conductor */
package/dist/config.js CHANGED
@@ -6,6 +6,7 @@ exports.saveConfigFile = saveConfigFile;
6
6
  exports.loadTemporalCliConfig = loadTemporalCliConfig;
7
7
  exports.parseTemporalYaml = parseTemporalYaml;
8
8
  exports.getConfig = getConfig;
9
+ exports.getConfigWithSources = getConfigWithSources;
9
10
  exports.sessionWorkflowId = sessionWorkflowId;
10
11
  exports.conductorWorkflowId = conductorWorkflowId;
11
12
  const fs_1 = require("fs");
@@ -182,6 +183,50 @@ function getConfig(overrides = {}) {
182
183
  ensemble: process.env[exports.ENV.ENSEMBLE] ?? 'default',
183
184
  };
184
185
  }
186
+ /**
187
+ * Like getConfig(), but also returns which source each value came from.
188
+ * Used by `claude-tempo config show` to help users debug.
189
+ */
190
+ function getConfigWithSources(overrides = {}) {
191
+ const temporalCli = loadTemporalCliConfig();
192
+ const configFile = loadConfigFile();
193
+ function resolveWithSource(key, cliVal, envKey, fileVal, temporalCliVal, defaultVal) {
194
+ if (cliVal)
195
+ return { value: cliVal, source: 'flag' };
196
+ if (process.env[envKey])
197
+ return { value: process.env[envKey], source: 'env' };
198
+ if (fileVal)
199
+ return { value: fileVal, source: 'config' };
200
+ if (temporalCliVal)
201
+ return { value: temporalCliVal, source: 'temporal-cli' };
202
+ if (defaultVal)
203
+ return { value: defaultVal, source: 'default' };
204
+ return { value: undefined, source: 'none' };
205
+ }
206
+ const address = resolveWithSource('temporalAddress', overrides.temporalAddress, exports.ENV.TEMPORAL_ADDRESS, configFile.temporalAddress, temporalCli.temporalAddress, 'localhost:7233');
207
+ const namespace = resolveWithSource('temporalNamespace', overrides.temporalNamespace, exports.ENV.TEMPORAL_NAMESPACE, configFile.temporalNamespace, temporalCli.temporalNamespace, 'default');
208
+ const apiKey = resolveWithSource('temporalApiKey', overrides.temporalApiKey, exports.ENV.TEMPORAL_API_KEY, configFile.temporalApiKey, temporalCli.temporalApiKey);
209
+ const tlsCert = resolveWithSource('temporalTlsCertPath', overrides.temporalTlsCertPath, exports.ENV.TEMPORAL_TLS_CERT_PATH, configFile.temporalTlsCertPath, temporalCli.temporalTlsCertPath);
210
+ const tlsKey = resolveWithSource('temporalTlsKeyPath', overrides.temporalTlsKeyPath, exports.ENV.TEMPORAL_TLS_KEY_PATH, configFile.temporalTlsKeyPath, temporalCli.temporalTlsKeyPath);
211
+ return {
212
+ config: {
213
+ temporalAddress: address.value,
214
+ temporalNamespace: namespace.value,
215
+ temporalApiKey: apiKey.value,
216
+ temporalTlsCertPath: tlsCert.value,
217
+ temporalTlsKeyPath: tlsKey.value,
218
+ taskQueue: process.env[exports.ENV.TASK_QUEUE] ?? 'claude-tempo',
219
+ ensemble: process.env[exports.ENV.ENSEMBLE] ?? 'default',
220
+ },
221
+ sources: {
222
+ temporalAddress: address.source,
223
+ temporalNamespace: namespace.source,
224
+ temporalApiKey: apiKey.source,
225
+ temporalTlsCertPath: tlsCert.source,
226
+ temporalTlsKeyPath: tlsKey.source,
227
+ },
228
+ };
229
+ }
185
230
  /** Build a workflow ID for a player session: claude-session-{ensemble}-{playerId} */
186
231
  function sessionWorkflowId(ensemble, playerId) {
187
232
  return `claude-session-${ensemble}-${playerId}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-tempo",
3
- "version": "0.3.0-beta.1",
3
+ "version": "0.3.0-beta.2",
4
4
  "description": "MCP server for multi-session Claude Code coordination via Temporal",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,6 +26,10 @@
26
26
  "types": "./dist/workflows/signals.d.ts",
27
27
  "default": "./dist/workflows/signals.js"
28
28
  },
29
+ "./connection": {
30
+ "types": "./dist/connection.d.ts",
31
+ "default": "./dist/connection.js"
32
+ },
29
33
  "./workflow-bundle": "./workflow-bundle.js",
30
34
  "./package.json": "./package.json"
31
35
  },
@@ -60,7 +64,8 @@
60
64
  "types": ["dist/types.d.ts"],
61
65
  "config": ["dist/config.d.ts"],
62
66
  "spawn": ["dist/spawn.d.ts"],
63
- "signals": ["dist/workflows/signals.d.ts"]
67
+ "signals": ["dist/workflows/signals.d.ts"],
68
+ "connection": ["dist/connection.d.ts"]
64
69
  }
65
70
  },
66
71
  "files": [