overmux 0.0.3 → 0.0.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.
Files changed (159) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +2 -2
  3. package/dist/auth/.vite/manifest.json +2 -2
  4. package/dist/auth/assets/{index-Bx8JhwVi.css → index-BM9gETvx.css} +1 -1
  5. package/dist/auth/assets/{index-CHIE7qYj.js → index-DabAfcs1.js} +1 -1
  6. package/dist/auth/index.html +2 -2
  7. package/dist/bin.js +219 -126
  8. package/dist/bin.js.map +1 -1
  9. package/dist/docs/000-index.md +2 -4
  10. package/dist/docs/100-introduction/200-how-overmux-works.md +126 -2
  11. package/{docs/100-introduction/300-why-overmux.md → dist/docs/100-introduction/300-why-i-built-overmux.md} +1 -1
  12. package/dist/docs/200-getting-started/100-install-and-run-overmux.md +2 -2
  13. package/dist/docs/200-getting-started/400-secure-with-https/200-tailscale-serve.md +3 -3
  14. package/dist/docs/200-getting-started/400-secure-with-https/300-cloudflare-tunnel.md +2 -2
  15. package/dist/docs/200-getting-started/400-secure-with-https/400-self-hosted-reverse-proxy.md +2 -2
  16. package/dist/docs/400-reference/100-project-structure.md +83 -0
  17. package/dist/docs/400-reference/200-configuration.md +257 -0
  18. package/dist/docs/400-reference/300-storage-locations.md +46 -0
  19. package/dist/docs/400-reference/400-authentication-and-security.md +37 -0
  20. package/dist/docs/400-reference/500-server/000-index.md +13 -0
  21. package/dist/docs/400-reference/500-server/100-resources.md +191 -0
  22. package/dist/docs/400-reference/500-server/200-operations.md +111 -0
  23. package/dist/docs/400-reference/500-server/300-streams.md +140 -0
  24. package/dist/docs/400-reference/500-server/400-notifications.md +32 -0
  25. package/dist/docs/400-reference/500-server/500-api.md +118 -0
  26. package/dist/docs/400-reference/600-client/000-index.md +9 -0
  27. package/dist/docs/400-reference/600-client/100-api.md +370 -0
  28. package/dist/docs/400-reference/600-client/200-theming.md +94 -0
  29. package/dist/docs/400-reference/600-client/300-tech-stack-recommendations.md +12 -0
  30. package/{docs/400-reference/400-cli → dist/docs/400-reference/700-cli}/050-init.md +2 -4
  31. package/dist/docs/400-reference/{400-cli → 700-cli}/100-serve.md +9 -4
  32. package/{docs/400-reference/400-cli → dist/docs/400-reference/700-cli}/200-auth.md +1 -4
  33. package/{docs/400-reference/400-cli → dist/docs/400-reference/700-cli}/300-call.md +1 -4
  34. package/dist/docs/400-reference/700-cli/350-instance.md +21 -0
  35. package/dist/docs/400-reference/700-cli/600-docs.md +128 -0
  36. package/{docs/400-reference/400-cli → dist/docs/400-reference/700-cli}/700-desktop.md +1 -3
  37. package/dist/docs/500-hosted-pages.md +0 -1
  38. package/dist/exports/client.d.ts +19 -15
  39. package/dist/exports/client.d.ts.map +1 -1
  40. package/dist/exports/client.js +240 -58
  41. package/dist/exports/client.js.map +1 -1
  42. package/dist/exports/{index-D3_Dpy_T.d.ts → index-Cz3xkCa4.d.ts} +62 -36
  43. package/dist/exports/index-Cz3xkCa4.d.ts.map +1 -0
  44. package/dist/exports/index.d.ts +2 -2
  45. package/dist/exports/index.js +19 -5
  46. package/dist/exports/index.js.map +1 -1
  47. package/dist/exports/{notifications-kDp16bU_.js → notifications-BFAD3QQl.js} +34 -4
  48. package/dist/exports/notifications-BFAD3QQl.js.map +1 -0
  49. package/dist/exports/server.d.ts +1 -44
  50. package/dist/exports/server.d.ts.map +1 -1
  51. package/dist/exports/server.js +8 -1018
  52. package/dist/exports/server.js.map +1 -1
  53. package/dist/internal/server/coordinator/server-child.js +153 -85
  54. package/dist/internal/server/coordinator/server-child.js.map +1 -1
  55. package/docs/000-index.md +2 -4
  56. package/docs/100-introduction/200-how-overmux-works.md +126 -2
  57. package/{dist/docs/100-introduction/300-why-overmux.md → docs/100-introduction/300-why-i-built-overmux.md} +1 -1
  58. package/docs/200-getting-started/100-install-and-run-overmux.md +2 -2
  59. package/docs/200-getting-started/400-secure-with-https/200-tailscale-serve.md +3 -3
  60. package/docs/200-getting-started/400-secure-with-https/300-cloudflare-tunnel.md +2 -2
  61. package/docs/200-getting-started/400-secure-with-https/400-self-hosted-reverse-proxy.md +2 -2
  62. package/docs/400-reference/100-project-structure.md +83 -0
  63. package/docs/400-reference/200-configuration.md +257 -0
  64. package/docs/400-reference/300-storage-locations.md +46 -0
  65. package/docs/400-reference/400-authentication-and-security.md +37 -0
  66. package/docs/400-reference/500-server/000-index.md +13 -0
  67. package/docs/400-reference/500-server/100-resources.md +191 -0
  68. package/docs/400-reference/500-server/200-operations.md +111 -0
  69. package/docs/400-reference/500-server/300-streams.md +140 -0
  70. package/docs/400-reference/500-server/400-notifications.md +32 -0
  71. package/docs/400-reference/500-server/500-api.md +118 -0
  72. package/docs/400-reference/600-client/000-index.md +9 -0
  73. package/docs/400-reference/600-client/100-api.md +370 -0
  74. package/docs/400-reference/600-client/200-theming.md +94 -0
  75. package/docs/400-reference/600-client/300-tech-stack-recommendations.md +12 -0
  76. package/{dist/docs/400-reference/400-cli → docs/400-reference/700-cli}/050-init.md +2 -4
  77. package/docs/400-reference/{400-cli → 700-cli}/100-serve.md +9 -4
  78. package/{dist/docs/400-reference/400-cli → docs/400-reference/700-cli}/200-auth.md +1 -4
  79. package/{dist/docs/400-reference/400-cli → docs/400-reference/700-cli}/300-call.md +1 -4
  80. package/docs/400-reference/700-cli/350-instance.md +21 -0
  81. package/docs/400-reference/700-cli/600-docs.md +128 -0
  82. package/{dist/docs/400-reference/400-cli → docs/400-reference/700-cli}/700-desktop.md +1 -3
  83. package/docs/500-hosted-pages.md +0 -1
  84. package/package.json +3 -2
  85. package/src/internal/cli/app.ts +5 -5
  86. package/src/internal/cli/commands/docs-ai-context.ts +33 -0
  87. package/src/internal/cli/commands/docs.ts +19 -2
  88. package/src/internal/cli/commands/init-template.ts +1 -1
  89. package/src/internal/cli/commands/instance.ts +58 -0
  90. package/src/internal/cli/commands/serve.ts +3 -0
  91. package/src/internal/cli/login.ts +9 -9
  92. package/src/internal/cli/parse-port.ts +2 -1
  93. package/src/internal/client/auth/auth-shell.css +17 -1
  94. package/src/internal/client/auth/auth-shell.tsx +2 -11
  95. package/src/internal/client/auth/login-code-input.tsx +140 -0
  96. package/src/internal/client/browser-api.ts +17 -3
  97. package/src/internal/client/client-definition.ts +6 -8
  98. package/src/internal/client/host/deep-link-navigation.ts +75 -0
  99. package/src/internal/client/host/desktop-host.ts +3 -0
  100. package/src/internal/client/host/environment.ts +67 -0
  101. package/src/internal/client/host/instance-forwarding.ts +21 -0
  102. package/src/internal/client/host/overmux-host.tsx +17 -0
  103. package/src/internal/client/index.ts +0 -6
  104. package/src/internal/client/overmux-react.ts +95 -42
  105. package/src/internal/client/websocket.ts +32 -12
  106. package/src/internal/server/auth/auth-service.ts +2 -2
  107. package/src/internal/server/auth/instance-control.ts +89 -17
  108. package/src/internal/server/coordinator/ipc-protocol.ts +0 -1
  109. package/src/internal/server/runtime/create-runtime.ts +15 -2
  110. package/src/internal/server/runtime/runtime-instance.ts +47 -0
  111. package/src/internal/server/runtime/runtime-operations.ts +9 -3
  112. package/src/internal/server/runtime/runtime-resources.ts +15 -32
  113. package/src/internal/server/runtime/runtime-streams.ts +5 -6
  114. package/src/internal/server/server-logger.ts +5 -10
  115. package/src/internal/server/server-startup-options.ts +14 -14
  116. package/src/internal/server/start-application-server.ts +24 -19
  117. package/src/internal/server/websocket-server.ts +7 -0
  118. package/src/internal/shared/index.ts +2 -0
  119. package/src/internal/shared/protocol.ts +10 -1
  120. package/src/public/ai-context.ts +7 -29
  121. package/src/public/client.ts +1 -6
  122. package/src/public/config.ts +163 -31
  123. package/src/public/index.ts +2 -0
  124. package/src/public/server.ts +1 -16
  125. package/dist/docs/100-introduction/100-what-is-overmux.md +0 -7
  126. package/dist/docs/300-fundamentals/100-project-structure.md +0 -23
  127. package/dist/docs/300-fundamentals/200-configuration.md +0 -3
  128. package/dist/docs/300-fundamentals/300-theming.md +0 -3
  129. package/dist/docs/300-fundamentals/400-server.md +0 -3
  130. package/dist/docs/300-fundamentals/500-client.md +0 -3
  131. package/dist/docs/300-fundamentals/600-operations.md +0 -3
  132. package/dist/docs/300-fundamentals/700-resources.md +0 -3
  133. package/dist/docs/300-fundamentals/800-streams.md +0 -3
  134. package/dist/docs/300-fundamentals/900-authentication-and-security.md +0 -3
  135. package/dist/docs/400-reference/100-configuration.md +0 -3
  136. package/dist/docs/400-reference/200-server-api.md +0 -3
  137. package/dist/docs/400-reference/300-client-api.md +0 -20
  138. package/dist/docs/400-reference/400-cli/400-check.md +0 -20
  139. package/dist/docs/400-reference/400-cli/500-ai-context.md +0 -102
  140. package/dist/docs/400-reference/400-cli/600-docs.md +0 -23
  141. package/dist/exports/index-D3_Dpy_T.d.ts.map +0 -1
  142. package/dist/exports/notifications-kDp16bU_.js.map +0 -1
  143. package/docs/100-introduction/100-what-is-overmux.md +0 -7
  144. package/docs/300-fundamentals/100-project-structure.md +0 -23
  145. package/docs/300-fundamentals/200-configuration.md +0 -3
  146. package/docs/300-fundamentals/300-theming.md +0 -3
  147. package/docs/300-fundamentals/400-server.md +0 -3
  148. package/docs/300-fundamentals/500-client.md +0 -3
  149. package/docs/300-fundamentals/600-operations.md +0 -3
  150. package/docs/300-fundamentals/700-resources.md +0 -3
  151. package/docs/300-fundamentals/800-streams.md +0 -3
  152. package/docs/300-fundamentals/900-authentication-and-security.md +0 -3
  153. package/docs/400-reference/100-configuration.md +0 -3
  154. package/docs/400-reference/200-server-api.md +0 -3
  155. package/docs/400-reference/300-client-api.md +0 -20
  156. package/docs/400-reference/400-cli/400-check.md +0 -20
  157. package/docs/400-reference/400-cli/500-ai-context.md +0 -102
  158. package/docs/400-reference/400-cli/600-docs.md +0 -23
  159. package/src/internal/cli/commands/ai.ts +0 -44
@@ -1,10 +1,11 @@
1
1
  import { z } from "zod";
2
+ import { instanceIdSchema } from "@overmux/shared";
2
3
 
3
4
  import { notificationSchema } from "../../public/notifications";
4
5
 
5
6
  // Compatibility gate, not negotiation: open tabs may still run older client assets.
6
7
  // The exact version rejects incompatible runtime manifest and wire formats before later traffic.
7
- export const protocolVersion = 9 as const;
8
+ export const protocolVersion = 10 as const;
8
9
 
9
10
  // Application-defined WebSocket close codes shared by server and browser transports.
10
11
  export const webSocketCloseCode = {
@@ -139,7 +140,15 @@ export const protocolErrorMessageSchema = z.object({
139
140
  type: z.literal("error"),
140
141
  });
141
142
 
143
+ export const serverInfoMessageSchema = z
144
+ .object({
145
+ type: z.literal("server-info"),
146
+ instanceId: instanceIdSchema,
147
+ })
148
+ .strict();
149
+
142
150
  export const serverProtocolMessageSchema = z.discriminatedUnion("type", [
151
+ serverInfoMessageSchema,
143
152
  resourceResultMessageSchema,
144
153
  resourceInvalidatedMessageSchema,
145
154
  streamOpenedMessageSchema,
@@ -1,38 +1,16 @@
1
1
  import {
2
- packageSourceSnippet,
3
- techStackRecommendationsSnippet,
4
- type AiContextSnippet,
5
- } from "@overmux/shared";
2
+ aiContextContentBySnippet,
3
+ type AiContextSnippetDefinition,
4
+ } from "@overmux/ai-context";
6
5
 
7
6
  export {
7
+ coreAiContextSnippets,
8
+ defaultAiContextSnippets,
8
9
  packageSourceSnippet,
9
10
  techStackRecommendationsSnippet,
10
11
  type AiContextSnippet,
11
- };
12
- export type AiContextSnippetDefinition = readonly AiContextSnippet[];
13
-
14
- export const coreAiContextSnippets = [
15
- packageSourceSnippet,
16
- ] as const satisfies AiContextSnippetDefinition;
17
- export const defaultAiContextSnippets = [
18
- ...coreAiContextSnippets,
19
- techStackRecommendationsSnippet,
20
- ] as const satisfies AiContextSnippetDefinition;
21
-
22
- const packageSourceSnippetContent = `Overmux ships with documentation and TypeScript source.
23
-
24
- Run \`overmux docs\` to find the installed documentation and source for the overmux cli.
25
-
26
- E.g. \`node_modules/overmux\` and \`node_modules/@overmux/xterm\`.
27
-
28
- Inspect these files so guidance matches the versions used by the application.`;
29
-
30
- const techStackRecommendationsSnippetContent = `Prefer pnpm as the package manager, TanStack Router for routing, shadcn/ui for UI components, and Zod for schemas and runtime validation. Follow the application's established stack when it already differs.`;
31
-
32
- const aiContextContentBySnippet: Record<AiContextSnippet, string> = {
33
- [packageSourceSnippet]: packageSourceSnippetContent,
34
- [techStackRecommendationsSnippet]: techStackRecommendationsSnippetContent,
35
- };
12
+ type AiContextSnippetDefinition,
13
+ } from "@overmux/ai-context";
36
14
 
37
15
  export const composeAiContext = (snippets: AiContextSnippetDefinition) =>
38
16
  snippets.length === 0
@@ -7,6 +7,7 @@ export {
7
7
  writeClipboardText,
8
8
  } from "../internal/client/clipboard";
9
9
  export type { OvermuxServerApi } from "../internal/client/browser-api";
10
+ export type { InstanceIdentity } from "@overmux/shared";
10
11
  export {
11
12
  createOvermuxHooks,
12
13
  type ResourceResult,
@@ -27,15 +28,9 @@ export type {
27
28
  OvermuxThemeToken,
28
29
  } from "../internal/client/theme-scope";
29
30
  export {
30
- chordPrefixSchema,
31
- commandBindingSchema,
32
31
  defineCommandRegistry,
33
32
  defineOvermuxClient,
34
- formatKeyBinding,
35
33
  formatShortcutBinding,
36
- keyBindingSchema,
37
- matchesKeyBinding,
38
- shortcutBindingSchema,
39
34
  } from "../internal/client/client-definition";
40
35
  export {
41
36
  skipToken,
@@ -6,39 +6,56 @@ import type { ResourceContract, StreamContract } from "./contracts";
6
6
 
7
7
  export type RuntimeDisposer = () => Promise<void> | void;
8
8
 
9
- export type HandlerContext = {
10
- invalidate: (contract: ResourceContract, input?: unknown) => void;
11
- signal: AbortSignal;
9
+ export type InstanceContext = {
10
+ getInstanceId: () => string;
11
+ getDeepLinkPrefix: () => string;
12
12
  };
13
13
 
14
- export type OperationContext = HandlerContext & {
15
- notifications: Notifications;
14
+ type ResourceInputMap = Readonly<Record<string, unknown>>;
15
+
16
+ // Keep IDs paired with their raw inputs when checking calls and reusable handlers.
17
+ type InvalidationArguments<TInputs extends ResourceInputMap> = {
18
+ [TId in keyof TInputs & string]: [resourceId: TId, input?: TInputs[TId]];
19
+ }[keyof TInputs & string];
20
+
21
+ export type HandlerContext<TInputs extends ResourceInputMap = {}> = {
22
+ instance: InstanceContext;
23
+ invalidate: (...args: InvalidationArguments<TInputs>) => void;
24
+ signal: AbortSignal;
16
25
  };
17
26
 
27
+ export type OperationContext<TInputs extends ResourceInputMap = {}> =
28
+ HandlerContext<TInputs> & {
29
+ notifications: Notifications;
30
+ };
31
+
18
32
  export type OperationDefinition<
19
33
  TInput extends z.ZodType = z.ZodType,
20
34
  TOutput extends z.ZodType = z.ZodVoid,
35
+ TContext = OperationContext,
21
36
  > = {
22
37
  handle: (
23
38
  input: z.output<TInput>,
24
- context: OperationContext,
39
+ context: TContext,
25
40
  ) => Promise<z.input<NoInfer<TOutput>>> | z.input<NoInfer<TOutput>>;
26
41
  input: TInput;
27
42
  output: TOutput;
28
43
  };
29
44
 
45
+ // Infer schemas from this definition, not a surrounding operation map's broad constraint.
30
46
  export const defineOperation = <
31
47
  TInput extends z.ZodType,
32
48
  TOutput extends z.ZodType = z.ZodVoid,
49
+ TContext = OperationContext,
33
50
  >({
34
51
  handle,
35
52
  input,
36
53
  output,
37
54
  }: {
38
- handle: OperationDefinition<TInput, TOutput>["handle"];
55
+ handle: OperationDefinition<TInput, TOutput, TContext>["handle"];
39
56
  input: TInput;
40
57
  output?: TOutput;
41
- }): OperationDefinition<TInput, TOutput> => ({
58
+ }): OperationDefinition<NoInfer<TInput>, NoInfer<TOutput>, TContext> => ({
42
59
  handle,
43
60
  input,
44
61
  output: (output ?? z.void()) as TOutput,
@@ -47,26 +64,28 @@ export const defineOperation = <
47
64
  export type QueryResourceDefinition<
48
65
  TInput extends z.ZodType = z.ZodType,
49
66
  TOutput extends z.ZodType = z.ZodType,
67
+ TContext = HandlerContext,
50
68
  > = {
51
69
  contract: ResourceContract<TInput, TOutput>;
52
70
  kind: "query";
53
71
  read: (
54
72
  input: z.output<TInput>,
55
- context: HandlerContext,
73
+ context: TContext,
56
74
  ) => Promise<z.input<NoInfer<TOutput>>> | z.input<NoInfer<TOutput>>;
57
75
  };
58
76
 
59
77
  export type SubscriptionResourceDefinition<
60
78
  TInput extends z.ZodType = z.ZodType,
61
79
  TOutput extends z.ZodType = z.ZodType,
80
+ TContext = HandlerContext,
62
81
  > = {
63
82
  contract: ResourceContract<TInput, TOutput>;
64
83
  kind: "subscription";
65
- read: QueryResourceDefinition<TInput, TOutput>["read"];
84
+ read: QueryResourceDefinition<TInput, TOutput, TContext>["read"];
66
85
  subscribe: (
67
86
  input: z.output<TInput>,
68
87
  invalidate: () => void,
69
- context: HandlerContext,
88
+ context: TContext,
70
89
  ) => RuntimeDisposer;
71
90
  };
72
91
 
@@ -87,8 +106,16 @@ export type DerivedResourceDefinition<
87
106
  type AnyZodType = z.ZodType<any, any, any>;
88
107
 
89
108
  export type ResourceDefinition =
90
- | QueryResourceDefinition<AnyZodType, AnyZodType>
91
- | SubscriptionResourceDefinition<AnyZodType, AnyZodType>
109
+ | QueryResourceDefinition<
110
+ AnyZodType,
111
+ AnyZodType,
112
+ HandlerContext<ResourceInputMap>
113
+ >
114
+ | SubscriptionResourceDefinition<
115
+ AnyZodType,
116
+ AnyZodType,
117
+ HandlerContext<ResourceInputMap>
118
+ >
92
119
  | DerivedResourceDefinition<AnyZodType, AnyZodType, any, any>;
93
120
 
94
121
  export type StreamSession<TClientMessage = unknown> = {
@@ -100,11 +127,12 @@ export type StreamHandlerDefinition<
100
127
  TInput extends z.ZodType = z.ZodType,
101
128
  TClientMessage extends z.ZodType = z.ZodType,
102
129
  TServerMessage extends z.ZodType = z.ZodType,
130
+ TContext = HandlerContext,
103
131
  > = {
104
132
  contract: StreamContract<TInput, TClientMessage, TServerMessage>;
105
133
  open: (
106
134
  input: z.output<TInput>,
107
- context: HandlerContext & {
135
+ context: TContext & {
108
136
  emit: (message: z.input<NoInfer<TServerMessage>>) => void;
109
137
  fail: (cause: unknown) => void;
110
138
  },
@@ -117,10 +145,21 @@ export const defineStreamHandler = <
117
145
  TInput extends z.ZodType,
118
146
  TClientMessage extends z.ZodType,
119
147
  TServerMessage extends z.ZodType,
148
+ TContext = HandlerContext,
120
149
  >(
121
150
  contract: StreamContract<TInput, TClientMessage, TServerMessage>,
122
- open: StreamHandlerDefinition<TInput, TClientMessage, TServerMessage>["open"],
123
- ): StreamHandlerDefinition<TInput, TClientMessage, TServerMessage> => ({
151
+ open: StreamHandlerDefinition<
152
+ TInput,
153
+ TClientMessage,
154
+ TServerMessage,
155
+ TContext
156
+ >["open"],
157
+ ): StreamHandlerDefinition<
158
+ TInput,
159
+ TClientMessage,
160
+ TServerMessage,
161
+ TContext
162
+ > => ({
124
163
  contract,
125
164
  open,
126
165
  });
@@ -130,6 +169,10 @@ type ResourceContracts = Record<
130
169
  ResourceContract<AnyZodType, AnyZodType>
131
170
  >;
132
171
 
172
+ type ResourceInputs<TContracts extends ResourceContracts> = {
173
+ [TId in keyof TContracts]: z.input<TContracts[TId]["input"]>;
174
+ };
175
+
133
176
  type DependencyOutputs<
134
177
  TContracts extends ResourceContracts,
135
178
  TDependencies extends Record<string, unknown>,
@@ -148,17 +191,29 @@ type DependencySource<TDependencies> = {
148
191
  : { dependencies?: never };
149
192
  };
150
193
 
151
- type QueryFor<TContract extends ResourceContract<AnyZodType, AnyZodType>> = {
194
+ type QueryFor<
195
+ TContract extends ResourceContract<AnyZodType, AnyZodType>,
196
+ TContracts extends ResourceContracts,
197
+ > = {
152
198
  contract: TContract;
153
199
  } & Omit<
154
- QueryResourceDefinition<TContract["input"], TContract["output"]>,
200
+ QueryResourceDefinition<
201
+ TContract["input"],
202
+ TContract["output"],
203
+ HandlerContext<ResourceInputs<NoInfer<TContracts>>>
204
+ >,
155
205
  "contract"
156
206
  >;
157
207
 
158
208
  type SubscriptionFor<
159
209
  TContract extends ResourceContract<AnyZodType, AnyZodType>,
210
+ TContracts extends ResourceContracts,
160
211
  > = { contract: TContract } & Omit<
161
- SubscriptionResourceDefinition<TContract["input"], TContract["output"]>,
212
+ SubscriptionResourceDefinition<
213
+ TContract["input"],
214
+ TContract["output"],
215
+ HandlerContext<ResourceInputs<NoInfer<TContracts>>>
216
+ >,
162
217
  "contract"
163
218
  >;
164
219
 
@@ -180,8 +235,8 @@ type ConfiguredResource<
180
235
  TDependencies,
181
236
  TId extends keyof TContracts,
182
237
  > =
183
- | QueryFor<TContracts[TId]>
184
- | SubscriptionFor<TContracts[TId]>
238
+ | QueryFor<TContracts[TId], TContracts>
239
+ | SubscriptionFor<TContracts[TId], TContracts>
185
240
  | (TId extends keyof TDependencies
186
241
  ? TDependencies[TId] extends Record<
187
242
  string,
@@ -207,26 +262,97 @@ export type AuthDuration = `${number}${"m" | "h" | "d"}`;
207
262
  export type AuthConfigDefinition = {
208
263
  mode: "cli-login";
209
264
  origins?: string[];
210
- sessionLifetime?: "never" | AuthDuration;
265
+ sessionLifetime?: "forever" | AuthDuration;
211
266
  trustedProxyPeer?: string;
212
267
  };
213
268
 
214
269
  export type ServerConfigDefinition = {
215
270
  host?: string;
216
- logFile?: string;
217
271
  port?: number;
218
272
  productionWebAssetsDir?: string;
219
273
  watch?: boolean;
220
274
  };
221
275
 
222
- type StreamDefinitions = Readonly<
223
- Record<string, StreamHandlerDefinition<AnyZodType, AnyZodType, AnyZodType>>
276
+ type StreamDefinitions<TContext = HandlerContext<ResourceInputMap>> = Readonly<
277
+ Record<
278
+ string,
279
+ StreamHandlerDefinition<AnyZodType, AnyZodType, AnyZodType, TContext>
280
+ >
224
281
  >;
225
282
 
226
283
  type OperationDefinitions = Readonly<
227
- Record<string, OperationDefinition<AnyZodType, AnyZodType>>
284
+ Record<
285
+ string,
286
+ OperationDefinition<
287
+ AnyZodType,
288
+ AnyZodType,
289
+ OperationContext<ResourceInputMap>
290
+ >
291
+ >
228
292
  >;
229
293
 
294
+ type OperationInputs = Record<string, AnyZodType>;
295
+
296
+ type OperationOutputSchema<
297
+ TOutputs,
298
+ TId extends PropertyKey,
299
+ > = TId extends keyof TOutputs
300
+ ? TOutputs[TId] extends z.ZodType
301
+ ? TOutputs[TId]
302
+ : z.ZodVoid
303
+ : z.ZodVoid;
304
+
305
+ type ConfiguredOperations<
306
+ TInputs extends OperationInputs,
307
+ TOutputs,
308
+ TContracts extends ResourceContracts,
309
+ > = {
310
+ [TId in keyof TInputs]: {
311
+ input: TInputs[TId];
312
+ output?: OperationOutputSchema<TOutputs, TId>;
313
+ handle: OperationDefinition<
314
+ TInputs[TId],
315
+ OperationOutputSchema<TOutputs, TId>,
316
+ OperationContext<ResourceInputs<TContracts>>
317
+ >["handle"];
318
+ };
319
+ } & {
320
+ [TId in keyof TOutputs]: TOutputs[TId] extends z.ZodType
321
+ ? { output: TOutputs[TId] }
322
+ : { output?: never };
323
+ };
324
+
325
+ type NormalizedOperations<
326
+ TInputs extends OperationInputs,
327
+ TOutputs,
328
+ TContracts extends ResourceContracts,
329
+ > = {
330
+ [TId in keyof TInputs]: OperationDefinition<
331
+ TInputs[TId],
332
+ OperationOutputSchema<TOutputs, TId>,
333
+ OperationContext<ResourceInputs<TContracts>>
334
+ >;
335
+ };
336
+
337
+ const normalizeOperations = <
338
+ TInputs extends OperationInputs,
339
+ TOutputs,
340
+ TContracts extends ResourceContracts,
341
+ >(
342
+ operations: ConfiguredOperations<TInputs, TOutputs, TContracts> | undefined,
343
+ ): NormalizedOperations<TInputs, TOutputs, TContracts> | undefined => {
344
+ if (operations === undefined) {
345
+ return undefined;
346
+ }
347
+ // Preserve every key and handler; only absent output schemas become ZodVoid.
348
+ return Object.fromEntries(
349
+ Object.entries(operations).map(([id, definition]) => [
350
+ id,
351
+ { ...definition, output: definition.output ?? z.void() },
352
+ ]),
353
+ ) as NormalizedOperations<TInputs, TOutputs, TContracts>;
354
+ };
355
+
230
356
  export type ConfigDefinition<
231
357
  TResources extends Readonly<Record<string, unknown>> = Readonly<
232
358
  Record<string, ResourceDefinition>
@@ -245,6 +371,7 @@ export type OvermuxConfigDefinition<
245
371
  aiContextSnippets?: AiContextSnippetDefinition;
246
372
  auth: AuthConfigDefinition;
247
373
  debug?: boolean;
374
+ instanceId?: string | ((context: { port: number }) => string);
248
375
  server: TServer;
249
376
  vite?: string;
250
377
  };
@@ -271,16 +398,21 @@ export const defineOvermuxServer = <
271
398
  const TContracts extends ResourceContracts = {},
272
399
  const TDependencies = {},
273
400
  const TStreams extends StreamDefinitions = {},
274
- const TOperations extends OperationDefinitions = {},
401
+ const TInputs extends OperationInputs = {},
402
+ const TOutputs = {},
275
403
  >(definition: {
276
- operations?: TOperations;
404
+ operations?: ConfiguredOperations<TInputs, TOutputs, NoInfer<TContracts>>;
277
405
  resources: ConfiguredResources<TContracts, TDependencies>;
278
- streams?: TStreams;
406
+ streams?: TStreams &
407
+ StreamDefinitions<HandlerContext<ResourceInputs<NoInfer<TContracts>>>>;
279
408
  }): ConfigDefinition<
280
409
  ConfiguredResources<TContracts, TDependencies>,
281
410
  TStreams,
282
- TOperations
283
- > => definition;
411
+ NormalizedOperations<TInputs, TOutputs, TContracts>
412
+ > => ({
413
+ ...definition,
414
+ operations: normalizeOperations(definition.operations),
415
+ });
284
416
 
285
417
  export const defineOvermuxConfig = <const TServer extends ConfigDefinition>(
286
418
  definition: OvermuxConfigDefinition<TServer>,
@@ -21,6 +21,7 @@ export type {
21
21
  ConfigDefinition,
22
22
  DerivedResourceDefinition,
23
23
  HandlerContext,
24
+ InstanceContext,
24
25
  OperationContext,
25
26
  OperationDefinition,
26
27
  OvermuxConfigDefinition,
@@ -49,6 +50,7 @@ export type {
49
50
  } from "./contracts";
50
51
  export { notificationLinkSchema, notificationSchema } from "./notifications";
51
52
  export type { Notification, Notifications } from "./notifications";
53
+ export type { InstanceIdentity } from "@overmux/shared";
52
54
  export {
53
55
  createOvermuxSettingsPath,
54
56
  overmuxLogoutPath,
@@ -1,16 +1 @@
1
- export {
2
- checkOvermux,
3
- type CheckDiagnostic,
4
- type CheckOvermuxOptions,
5
- type CheckResult,
6
- } from "../internal/server/check-overmux";
7
- export {
8
- getOvermuxPaths,
9
- type GetOvermuxPathsOptions,
10
- type OvermuxPaths,
11
- } from "../internal/server/paths";
12
- export {
13
- startOvermuxServer,
14
- type OvermuxServer,
15
- type OvermuxServerOptions,
16
- } from "../internal/server/start-overmux-server";
1
+ export { getOvermuxPaths } from "../internal/server/paths";
@@ -1,7 +0,0 @@
1
- ---
2
- title: What is Overmux?
3
- ---
4
-
5
- Overmux is a web-based, customizable dev environment. Designed for coding using Agents.
6
-
7
-
@@ -1,23 +0,0 @@
1
- ---
2
- title: Project Structure
3
- ---
4
-
5
- `overmux init` creates this minimal userland application:
6
-
7
- ```text
8
- .gitignore
9
- mise.toml Mise installations only
10
- package.json
11
- pnpm-lock.yaml
12
- overmux.config.ts authentication, server, Vite, and production settings
13
- src/server/index.ts trusted resources, streams, and operations
14
- src/ui/app.tsx browser application definition
15
- src/ui/index.html browser document
16
- src/ui/main.tsx React and Overmux host entry point
17
- src/ui/styles.css application styles
18
- vite.config.ts browser development and production build configuration
19
- ```
20
-
21
- The server and UI are separate trust boundaries. `src/server/index.ts` runs as trusted Node.js code. Files under `src/ui` run in the browser and communicate with the server through Overmux's public APIs.
22
-
23
- The generated application has no shared directory. Add browser-safe shared schemas only when both sides need them.
@@ -1,3 +0,0 @@
1
- ---
2
- title: Configuration
3
- ---
@@ -1,3 +0,0 @@
1
- ---
2
- title: Theming
3
- ---
@@ -1,3 +0,0 @@
1
- ---
2
- title: Server
3
- ---
@@ -1,3 +0,0 @@
1
- ---
2
- title: Client
3
- ---
@@ -1,3 +0,0 @@
1
- ---
2
- title: Operations
3
- ---
@@ -1,3 +0,0 @@
1
- ---
2
- title: Resources
3
- ---
@@ -1,3 +0,0 @@
1
- ---
2
- title: Streams
3
- ---
@@ -1,3 +0,0 @@
1
- ---
2
- title: Authentication and Security
3
- ---
@@ -1,3 +0,0 @@
1
- ---
2
- title: Configuration
3
- ---
@@ -1,3 +0,0 @@
1
- ---
2
- title: Server API
3
- ---
@@ -1,20 +0,0 @@
1
- ---
2
- title: Client API
3
- ---
4
-
5
- ## Clipboard
6
-
7
- ```ts
8
- import { readClipboardText, writeClipboardText } from "overmux/client";
9
-
10
- await writeClipboardText("Text to copy");
11
- const text = await readClipboardText();
12
- ```
13
-
14
- `readClipboardText(): Promise<string>` reads the system clipboard through `navigator.clipboard.readText()`. It never reads through the desktop bridge.
15
-
16
- `writeClipboardText(text: string): Promise<void>` uses Overmux's version-1 desktop write bridge when present, otherwise `navigator.clipboard.writeText()`. Desktop writes are fire-and-forget: resolution confirms dispatch, not completion or acceptance by the host. Existing host origin and active-frame checks still apply.
17
-
18
- Both reject on unavailable browser APIs, browser permission failures, or synchronous desktop dispatch failures. Browser secure-context, focus, permissions, and user-activation restrictions still apply. These APIs target the system clipboard, not the X11 primary selection. Only read clipboard data you need and trust the source of text you write.
19
-
20
- For terminal-program access via OSC 52, use the opt-in factories from `@overmux/xterm/client` rather than wiring platform bridges in application code.
@@ -1,20 +0,0 @@
1
- ---
2
- title: "overmux check"
3
- description: "Validate an Overmux configuration"
4
- ---
5
-
6
- # `overmux check`
7
-
8
- Validate an Overmux configuration.
9
-
10
- ## Usage
11
-
12
- ```text
13
- overmux check [--config path]
14
- ```
15
-
16
- ## Options
17
-
18
- | Flag | Description | Default |
19
- | --- | --- | --- |
20
- | `--config <path>, -c <path>` | Configuration file | `$XDG_CONFIG_HOME/overmux/overmux.config.ts` |