@getjack/jack 0.1.2 → 0.1.4

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 (91) hide show
  1. package/README.md +77 -29
  2. package/package.json +54 -47
  3. package/src/commands/agents.ts +145 -10
  4. package/src/commands/down.ts +110 -102
  5. package/src/commands/feedback.ts +189 -0
  6. package/src/commands/init.ts +8 -12
  7. package/src/commands/login.ts +88 -0
  8. package/src/commands/logout.ts +14 -0
  9. package/src/commands/logs.ts +21 -0
  10. package/src/commands/mcp.ts +134 -7
  11. package/src/commands/new.ts +43 -17
  12. package/src/commands/open.ts +13 -6
  13. package/src/commands/projects.ts +269 -143
  14. package/src/commands/secrets.ts +413 -0
  15. package/src/commands/services.ts +96 -123
  16. package/src/commands/ship.ts +5 -1
  17. package/src/commands/whoami.ts +31 -0
  18. package/src/index.ts +218 -144
  19. package/src/lib/agent-files.ts +34 -0
  20. package/src/lib/agents.ts +390 -22
  21. package/src/lib/asset-hash.ts +50 -0
  22. package/src/lib/auth/client.ts +115 -0
  23. package/src/lib/auth/constants.ts +5 -0
  24. package/src/lib/auth/guard.ts +57 -0
  25. package/src/lib/auth/index.ts +18 -0
  26. package/src/lib/auth/store.ts +54 -0
  27. package/src/lib/binding-validator.ts +136 -0
  28. package/src/lib/build-helper.ts +211 -0
  29. package/src/lib/cloudflare-api.ts +24 -0
  30. package/src/lib/config.ts +5 -6
  31. package/src/lib/control-plane.ts +295 -0
  32. package/src/lib/debug.ts +3 -1
  33. package/src/lib/deploy-mode.ts +93 -0
  34. package/src/lib/deploy-upload.ts +92 -0
  35. package/src/lib/errors.ts +2 -0
  36. package/src/lib/github.ts +31 -1
  37. package/src/lib/hooks.ts +4 -12
  38. package/src/lib/intent.ts +88 -0
  39. package/src/lib/jsonc.ts +125 -0
  40. package/src/lib/local-paths.test.ts +902 -0
  41. package/src/lib/local-paths.ts +258 -0
  42. package/src/lib/managed-deploy.ts +175 -0
  43. package/src/lib/managed-down.ts +159 -0
  44. package/src/lib/mcp-config.ts +55 -34
  45. package/src/lib/names.ts +9 -29
  46. package/src/lib/project-operations.ts +676 -249
  47. package/src/lib/project-resolver.ts +476 -0
  48. package/src/lib/registry.ts +76 -37
  49. package/src/lib/resources.ts +196 -0
  50. package/src/lib/schema.ts +30 -1
  51. package/src/lib/storage/file-filter.ts +1 -0
  52. package/src/lib/storage/index.ts +5 -1
  53. package/src/lib/telemetry.ts +14 -0
  54. package/src/lib/tty.ts +15 -0
  55. package/src/lib/zip-packager.ts +255 -0
  56. package/src/mcp/resources/index.ts +8 -2
  57. package/src/mcp/server.ts +32 -4
  58. package/src/mcp/tools/index.ts +35 -13
  59. package/src/mcp/types.ts +6 -0
  60. package/src/mcp/utils.ts +1 -1
  61. package/src/templates/index.ts +42 -4
  62. package/src/templates/types.ts +13 -0
  63. package/templates/CLAUDE.md +166 -0
  64. package/templates/api/.jack.json +4 -0
  65. package/templates/api/bun.lock +1 -0
  66. package/templates/api/wrangler.jsonc +5 -0
  67. package/templates/hello/.jack.json +28 -0
  68. package/templates/hello/package.json +10 -0
  69. package/templates/hello/src/index.ts +11 -0
  70. package/templates/hello/tsconfig.json +11 -0
  71. package/templates/hello/wrangler.jsonc +5 -0
  72. package/templates/miniapp/.jack.json +15 -4
  73. package/templates/miniapp/bun.lock +135 -40
  74. package/templates/miniapp/index.html +1 -0
  75. package/templates/miniapp/package.json +3 -1
  76. package/templates/miniapp/public/.well-known/farcaster.json +7 -5
  77. package/templates/miniapp/public/icon.png +0 -0
  78. package/templates/miniapp/public/og.png +0 -0
  79. package/templates/miniapp/schema.sql +8 -0
  80. package/templates/miniapp/src/App.tsx +254 -3
  81. package/templates/miniapp/src/components/ShareSheet.tsx +147 -0
  82. package/templates/miniapp/src/hooks/useAI.ts +35 -0
  83. package/templates/miniapp/src/hooks/useGuestbook.ts +11 -1
  84. package/templates/miniapp/src/hooks/useShare.ts +76 -0
  85. package/templates/miniapp/src/index.css +15 -0
  86. package/templates/miniapp/src/lib/api.ts +2 -1
  87. package/templates/miniapp/src/worker.ts +515 -1
  88. package/templates/miniapp/wrangler.jsonc +15 -3
  89. package/LICENSE +0 -190
  90. package/src/commands/cloud.ts +0 -230
  91. package/templates/api/wrangler.toml +0 -3
@@ -14,18 +14,18 @@ export interface McpServerConfig {
14
14
  }
15
15
 
16
16
  /**
17
- * IDE-specific MCP configuration paths and settings
17
+ * App-specific MCP configuration paths and settings
18
18
  */
19
- interface IdeMcpConfig {
19
+ interface AppMcpConfig {
20
20
  path: string;
21
21
  key: string;
22
22
  }
23
23
 
24
24
  /**
25
- * IDE MCP configuration paths
26
- * Maps IDE ID to its config file path and MCP servers key
25
+ * App MCP configuration paths
26
+ * Maps app ID to its config file path and MCP servers key
27
27
  */
28
- export const IDE_MCP_CONFIGS: Record<string, IdeMcpConfig> = {
28
+ export const APP_MCP_CONFIGS: Record<string, AppMcpConfig> = {
29
29
  "claude-code": {
30
30
  path: join(homedir(), ".claude.json"),
31
31
  key: "mcpServers",
@@ -49,64 +49,85 @@ const JACK_MCP_CONFIG_PATH = join(JACK_MCP_CONFIG_DIR, "config.json");
49
49
 
50
50
  /**
51
51
  * Returns the jack MCP server configuration
52
+ * Includes PATH with common install locations so Claude Desktop can find jack
52
53
  */
53
54
  export function getJackMcpConfig(): McpServerConfig {
55
+ // Build PATH with common locations where jack might be installed
56
+ // ~/.bun/bin is where `bun link` installs global commands
57
+ const bunBin = join(homedir(), ".bun", "bin");
58
+ const npmBin = join(homedir(), ".npm-global", "bin");
59
+ const defaultPaths = [bunBin, npmBin, "/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"];
60
+
54
61
  return {
55
62
  command: "jack",
56
63
  args: ["mcp", "serve"],
64
+ env: {
65
+ PATH: defaultPaths.join(":"),
66
+ },
57
67
  };
58
68
  }
59
69
 
60
70
  /**
61
- * Get display name for IDE
71
+ * Get display name for app
62
72
  */
63
- export function getIdeDisplayName(ideId: string): string {
73
+ export function getAppDisplayName(appId: string): string {
64
74
  const displayNames: Record<string, string> = {
65
75
  "claude-code": "Claude Code",
66
76
  "claude-desktop": "Claude Desktop",
67
77
  };
68
- return displayNames[ideId] || ideId;
78
+ return displayNames[appId] || appId;
69
79
  }
70
80
 
71
81
  /**
72
- * Check if an IDE's config directory exists (indicating it's installed)
82
+ * Check if an app is installed
83
+ *
84
+ * Detection strategies per app:
85
+ * - claude-code: Check for ~/.claude/ directory (created when Claude Code is installed/run)
86
+ * - claude-desktop: Check if config directory exists (created when app is first run)
73
87
  */
74
- export function isIdeInstalled(ideId: string): boolean {
75
- const ideConfig = IDE_MCP_CONFIGS[ideId];
76
- if (!ideConfig) return false;
88
+ export function isAppInstalled(appId: string): boolean {
89
+ const appConfig = APP_MCP_CONFIGS[appId];
90
+ if (!appConfig) return false;
91
+
92
+ if (appId === "claude-code") {
93
+ // Claude Code creates ~/.claude/ directory when installed
94
+ // Don't use parent of ~/.claude.json (that's ~, which always exists)
95
+ const claudeCodeDataDir = join(homedir(), ".claude");
96
+ return existsSync(claudeCodeDataDir);
97
+ }
77
98
 
78
- // Check if the parent directory exists (config file itself may not exist yet)
79
- const configDir = dirname(ideConfig.path);
99
+ // For other apps (claude-desktop), check if config directory exists
100
+ const configDir = dirname(appConfig.path);
80
101
  return existsSync(configDir);
81
102
  }
82
103
 
83
104
  /**
84
- * Install MCP config to a single IDE
105
+ * Install MCP config to a single app
85
106
  * Reads existing config, merges jack server, writes back
86
107
  * Returns true on success
87
108
  */
88
- export async function installMcpConfigToIde(ideId: string): Promise<boolean> {
89
- const ideConfig = IDE_MCP_CONFIGS[ideId];
90
- if (!ideConfig) {
91
- throw new Error(`Unknown IDE: ${ideId}`);
109
+ export async function installMcpConfigToApp(appId: string): Promise<boolean> {
110
+ const appConfig = APP_MCP_CONFIGS[appId];
111
+ if (!appConfig) {
112
+ throw new Error(`Unknown app: ${appId}`);
92
113
  }
93
114
 
94
115
  // Ensure parent directory exists
95
- const configDir = dirname(ideConfig.path);
116
+ const configDir = dirname(appConfig.path);
96
117
  if (!existsSync(configDir)) {
97
118
  try {
98
119
  await mkdir(configDir, { recursive: true });
99
120
  } catch (error) {
100
- // Directory doesn't exist and can't be created - IDE not installed
121
+ // Directory doesn't exist and can't be created - app not installed
101
122
  return false;
102
123
  }
103
124
  }
104
125
 
105
126
  // Read existing config or start with empty object
106
127
  let existingConfig: Record<string, unknown> = {};
107
- if (existsSync(ideConfig.path)) {
128
+ if (existsSync(appConfig.path)) {
108
129
  try {
109
- existingConfig = await Bun.file(ideConfig.path).json();
130
+ existingConfig = await Bun.file(appConfig.path).json();
110
131
  } catch {
111
132
  // Invalid JSON - treat as empty config
112
133
  existingConfig = {};
@@ -114,17 +135,17 @@ export async function installMcpConfigToIde(ideId: string): Promise<boolean> {
114
135
  }
115
136
 
116
137
  // Get or create mcpServers object
117
- const mcpServers = (existingConfig[ideConfig.key] as Record<string, unknown>) || {};
138
+ const mcpServers = (existingConfig[appConfig.key] as Record<string, unknown>) || {};
118
139
 
119
140
  // Add/update jack MCP server
120
141
  mcpServers.jack = getJackMcpConfig();
121
142
 
122
143
  // Merge back into config
123
- existingConfig[ideConfig.key] = mcpServers;
144
+ existingConfig[appConfig.key] = mcpServers;
124
145
 
125
146
  // Write updated config
126
147
  try {
127
- await Bun.write(ideConfig.path, JSON.stringify(existingConfig, null, 2));
148
+ await Bun.write(appConfig.path, JSON.stringify(existingConfig, null, 2));
128
149
  return true;
129
150
  } catch {
130
151
  // Write failed (permissions, etc.)
@@ -133,22 +154,22 @@ export async function installMcpConfigToIde(ideId: string): Promise<boolean> {
133
154
  }
134
155
 
135
156
  /**
136
- * Install to ALL detected/installed IDEs
137
- * Returns array of IDE IDs that were configured
157
+ * Install to ALL detected/installed apps
158
+ * Returns array of app IDs that were configured
138
159
  */
139
- export async function installMcpConfigsToAllIdes(): Promise<string[]> {
160
+ export async function installMcpConfigsToAllApps(): Promise<string[]> {
140
161
  const configured: string[] = [];
141
162
 
142
- for (const ideId of Object.keys(IDE_MCP_CONFIGS)) {
143
- // Check if IDE is installed
144
- if (!isIdeInstalled(ideId)) {
163
+ for (const appId of Object.keys(APP_MCP_CONFIGS)) {
164
+ // Check if app is installed
165
+ if (!isAppInstalled(appId)) {
145
166
  continue;
146
167
  }
147
168
 
148
169
  // Try to install config
149
- const success = await installMcpConfigToIde(ideId);
170
+ const success = await installMcpConfigToApp(appId);
150
171
  if (success) {
151
- configured.push(ideId);
172
+ configured.push(appId);
152
173
  }
153
174
  }
154
175
 
package/src/lib/names.ts CHANGED
@@ -1,32 +1,12 @@
1
- const adjectives = [
2
- "swift",
3
- "bright",
4
- "calm",
5
- "bold",
6
- "cool",
7
- "fast",
8
- "keen",
9
- "neat",
10
- "warm",
11
- "wise",
12
- ];
13
-
14
- const nouns = [
15
- "wave",
16
- "spark",
17
- "cloud",
18
- "star",
19
- "leaf",
20
- "stone",
21
- "wind",
22
- "flame",
23
- "brook",
24
- "ridge",
25
- ];
1
+ import { humanId } from "human-id";
26
2
 
3
+ /**
4
+ * Generate a Heroku-style project name
5
+ * Examples: "brave-moon-7xz", "calm-star-2ab"
6
+ */
27
7
  export function generateProjectName(): string {
28
- const adj = adjectives[Math.floor(Math.random() * adjectives.length)];
29
- const noun = nouns[Math.floor(Math.random() * nouns.length)];
30
- const suffix = Math.random().toString(16).slice(2, 6);
31
- return `${adj}-${noun}-${suffix}`;
8
+ return humanId({
9
+ separator: "-",
10
+ capitalize: false,
11
+ });
32
12
  }