History

desktop app, setup page, keychain secrets, release pipeline

- Electron desktop app with sidecar CLI binary bundling - Setup page on marketing site with OS-detected download buttons - GitHub Actions workflow for building desktop distributables - Re-enable keychain secrets plugin - Fix React production build (resolve.dedupe) - Support EXECUTOR_SCOPE_DIR env var for scope selection

Rhys Sullivan committed 7 months ago

Commit e4bd2fa1 parent 723b8f313 files · +470 −138Browse files

Unified · Split

13 files
  1. .changeset/desktop-app-release.md +5 −0
  2. .github/workflows/publish-desktop.yml +146 −0
  3. .github/workflows/publish-executor-package.yml +1 −1
  4. .github/workflows/release.yml +3 −2
  5. .gitignore +4 −1
  6. apps/desktop/package.json +43 −6
  7. apps/desktop/scripts/bundle-cli.js +58 −0
  8. apps/desktop/src/main.ts +32 −13
  9. apps/marketing/src/pages/index.astro +13 −82
  10. apps/marketing/src/pages/setup.astro +159 −0
  11. apps/server/src/services/executor.ts +3 −3
  12. bun.lock +2 −29
  13. package.json +1 −1
.changeset/desktop-app-release.md+5−0
@@ -0,0 +1,5 @@
1---
2"executor": minor
3---
4
5Desktop app, setup page, and re-enable keychain secrets
.github/workflows/publish-desktop.yml+146−0
@@ -0,0 +1,146 @@
1name: Publish Desktop App
2run-name: "${{ format('publish desktop {0}', github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name) }}"
3
4on:
5 push:
6 tags:
7 - "v*"
8 workflow_dispatch:
9 inputs:
10 tag:
11 description: Git tag to publish
12 required: true
13 type: string
14
15permissions:
16 contents: write
17
18concurrency:
19 group: publish-desktop-${{ github.ref }}
20 cancel-in-progress: false
21
22jobs:
23 build:
24 strategy:
25 fail-fast: false
26 matrix:
27 include:
28 - os: macos-latest
29 arch: arm64
30 platform: mac
31 - os: macos-13
32 arch: x64
33 platform: mac
34 - os: ubuntu-latest
35 arch: x64
36 platform: linux
37 - os: windows-latest
38 arch: x64
39 platform: win
40
41 runs-on: ${{ matrix.os }}
42
43 steps:
44 - name: Checkout
45 uses: actions/checkout@v4
46 with:
47 ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', inputs.tag) || github.ref }}
48
49 - name: Setup Bun
50 uses: oven-sh/setup-bun@v2
51 with:
52 bun-version: 1.3.11
53
54 - name: Setup Node
55 uses: actions/setup-node@v4
56 with:
57 node-version: 24
58
59 - name: Install dependencies
60 run: bun install --frozen-lockfile
61
62 - name: Build web app
63 run: bun run build
64 working-directory: apps/web
65
66 - name: Build CLI sidecar binary
67 run: bun run src/build.ts binary --single
68 working-directory: apps/cli
69
70 - name: Copy sidecar to desktop resources
71 shell: bash
72 run: |
73 mkdir -p apps/desktop/resources
74 if [ "${{ matrix.platform }}" = "win" ]; then
75 BINARY_NAME="executor.exe"
76 else
77 BINARY_NAME="executor"
78 fi
79
80 PLATFORM="${{ matrix.platform == 'mac' && 'darwin' || matrix.platform == 'win' && 'windows' || 'linux' }}"
81 ARCH="${{ matrix.arch }}"
82 SRC="apps/cli/dist/executor-${PLATFORM}-${ARCH}/bin"
83
84 cp "${SRC}/${BINARY_NAME}" "apps/desktop/resources/${BINARY_NAME}"
85 chmod +x "apps/desktop/resources/${BINARY_NAME}" 2>/dev/null || true
86
87 if [ -f "${SRC}/emscripten-module.wasm" ]; then
88 cp "${SRC}/emscripten-module.wasm" "apps/desktop/resources/"
89 fi
90
91 - name: Build desktop app (TypeScript)
92 run: npx tsc -p tsconfig.json
93 working-directory: apps/desktop
94
95 - name: Build desktop distributables
96 env:
97 GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
98 run: npx electron-builder --${{ matrix.platform }} --${{ matrix.arch }} --publish never
99 working-directory: apps/desktop
100
101 - name: Upload artifacts
102 uses: actions/upload-artifact@v4
103 with:
104 name: desktop-${{ matrix.platform }}-${{ matrix.arch }}
105 path: |
106 apps/desktop/dist/*.dmg
107 apps/desktop/dist/*.zip
108 apps/desktop/dist/*.exe
109 apps/desktop/dist/*.AppImage
110 apps/desktop/dist/*.deb
111 if-no-files-found: warn
112
113 release:
114 needs: build
115 runs-on: ubuntu-latest
116
117 steps:
118 - name: Download all artifacts
119 uses: actions/download-artifact@v4
120 with:
121 path: artifacts
122 merge-multiple: true
123
124 - name: List artifacts
125 run: find artifacts -type f | head -20
126
127 - name: Upload to GitHub Release
128 env:
129 GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
130 TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
131 run: |
132 # Wait for the CLI release to create the GitHub release first
133 for i in $(seq 1 30); do
134 if gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
135 echo "Release $TAG found"
136 break
137 fi
138 echo "Waiting for release $TAG to be created... ($i/30)"
139 sleep 10
140 done
141
142 # Upload desktop artifacts
143 find artifacts -type f \( -name "*.dmg" -o -name "*.zip" -o -name "*.exe" -o -name "*.AppImage" -o -name "*.deb" \) | while read file; do
144 echo "Uploading: $file"
145 gh release upload "$TAG" "$file" --repo "$GITHUB_REPOSITORY" --clobber || true
146 done
.github/workflows/publish-executor-package.yml+1−1
@@ -34,7 +34,7 @@ jobs: · 33 unmodified lines
34 - name: Setup Bun34 - name: Setup Bun
35 uses: oven-sh/setup-bun@v235 uses: oven-sh/setup-bun@v2
36 with:36 with:
37 bun-version: 1.3.1037 bun-version: 1.3.11
38 38
39 - name: Setup Node39 - name: Setup Node
40 uses: actions/setup-node@v440 uses: actions/setup-node@v4
.github/workflows/release.yml+3−2
@@ -29,7 +29,7 @@ jobs: · 28 unmodified lines
29 - name: Setup Bun29 - name: Setup Bun
30 uses: oven-sh/setup-bun@v230 uses: oven-sh/setup-bun@v2
31 with:31 with:
32 bun-version: 1.3.1032 bun-version: 1.3.11
33 33
34 - name: Setup Node34 - name: Setup Node
35 uses: actions/setup-node@v435 uses: actions/setup-node@v4
@@ -88,10 +88,11 @@ jobs: · 52 unmodified lines
88 git tag "$tag"88 git tag "$tag"
89 git push origin "$tag"89 git push origin "$tag"
90 90
91 - name: Trigger publish workflow91 - name: Trigger publish workflows
92 if: steps.changesets.outputs.hasChangesets == 'false' && steps.detect_release.outputs.changed == 'true'92 if: steps.changesets.outputs.hasChangesets == 'false' && steps.detect_release.outputs.changed == 'true'
93 env:93 env:
94 GH_TOKEN: ${{ github.token }}94 GH_TOKEN: ${{ github.token }}
95 run: |95 run: |
96 tag="v${{ steps.detect_release.outputs.version }}"96 tag="v${{ steps.detect_release.outputs.version }}"
97 gh workflow run publish-executor-package.yml --ref "$tag" -f tag="$tag"97 gh workflow run publish-executor-package.yml --ref "$tag" -f tag="$tag"
98 gh workflow run publish-desktop.yml --ref "$tag" -f tag="$tag"
.gitignore+4−1
@@ -36,4 +36,7 @@ report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json · 35 unmodified lines
36personal-notes/36personal-notes/
37*.har.executor37*.har.executor
38executor.har38executor.har
39.executor/39.executor/
40
41# desktop app build artifacts
42apps/desktop/resources/
apps/desktop/package.json+43−6
@@ -2,18 +2,23 @@ · 1 unmodified line
2 "name": "@executor/desktop",2 "name": "@executor/desktop",
3 "version": "1.4.0",3 "version": "1.4.0",
4 "private": true,4 "private": true,
5 "description": "Executor desktop app",
6 "author": "Rhys Sullivan",
5 "main": "dist/main.js",7 "main": "dist/main.js",
6 "scripts": {8 "scripts": {
7 "dev": "node scripts/dev.js",9 "dev": "node scripts/dev.js",
8 "build": "tsc && electron-builder",10 "build": "tsc -p tsconfig.json",
11 "bundle-cli": "node scripts/bundle-cli.js",
12 "dist": "npm run build && npm run bundle-cli && electron-builder",
13 "dist:mac": "npm run build && npm run bundle-cli && electron-builder --mac",
14 "dist:win": "npm run build && npm run bundle-cli && electron-builder --win",
15 "dist:linux": "npm run build && npm run bundle-cli && electron-builder --linux",
9 "typecheck": "tsc --noEmit"16 "typecheck": "tsc --noEmit"
10 },17 },
11 "dependencies": {18 "dependencies": {},
12 "electron-store": "^10.0.0"
13 },
14 "devDependencies": {19 "devDependencies": {
15 "@types/node": "catalog:",20 "@types/node": "catalog:",
16 "electron": "^35.0.1",21 "electron": "35.7.5",
17 "electron-builder": "^26.0.12",22 "electron-builder": "^26.0.12",
18 "typescript": "^5.9.3"23 "typescript": "^5.9.3"
19 },24 },
@@ -23,8 +28,40 @@ · 3 unmodified lines
23 "files": [28 "files": [
24 "dist/**/*"29 "dist/**/*"
25 ],30 ],
31 "extraResources": [
32 {
33 "from": "resources/",
34 "to": "",
35 "filter": ["executor*", "emscripten-module.wasm"]
36 }
37 ],
26 "mac": {38 "mac": {
27 "category": "public.app-category.developer-tools"39 "category": "public.app-category.developer-tools",
40 "target": [
41 { "target": "dmg", "arch": ["arm64", "x64"] },
42 { "target": "zip", "arch": ["arm64", "x64"] }
43 ],
44 "icon": "build/icon.icns"
45 },
46 "win": {
47 "target": ["nsis"],
48 "icon": "build/icon.ico"
49 },
50 "linux": {
51 "target": ["AppImage", "deb"],
52 "category": "Development",
53 "icon": "build/icons"
54 },
55 "dmg": {
56 "title": "Executor",
57 "contents": [
58 { "x": 130, "y": 220 },
59 { "x": 410, "y": 220, "type": "link", "path": "/Applications" }
60 ]
61 },
62 "nsis": {
63 "oneClick": false,
64 "allowToChangeInstallationDirectory": true
28 }65 }
29 }66 }
30}67}
apps/desktop/scripts/bundle-cli.js+58−0
@@ -0,0 +1,58 @@
1/**
2 * Builds the executor CLI binary and copies it into the desktop app's
3 * resources/ folder so electron-builder can bundle it as a sidecar.
4 */
5const { execSync, spawnSync } = require("node:child_process");
6const { existsSync, mkdirSync, cpSync, chmodSync } = require("node:fs");
7const { resolve, join } = require("node:path");
8
9const root = resolve(__dirname, "..");
10const repoRoot = resolve(root, "../..");
11const cliRoot = resolve(repoRoot, "apps/cli");
12const resourcesDir = resolve(root, "resources");
13
14// Build CLI for current platform
15console.log("Building executor CLI binary...");
16
17// Resolve bun binary path explicitly
18const { homedir } = require("node:os");
19const bunBin = resolve(process.env.BUN_INSTALL || join(homedir(), ".bun"), "bin", "bun");
20
21const result = spawnSync(bunBin, ["run", "src/build.ts", "binary", "--single"], {
22 cwd: cliRoot,
23 stdio: "inherit",
24});
25
26if (result.error) {
27 console.error("CLI build spawn error:", result.error.message);
28 process.exit(1);
29}
30
31if (result.status !== 0) {
32 console.error(`CLI build failed with exit code ${result.status}`);
33 process.exit(1);
34}
35
36// Find the built binary
37const platform = process.platform === "win32" ? "windows" : process.platform;
38const arch = process.arch === "arm64" ? "arm64" : "x64";
39const binaryName = process.platform === "win32" ? "executor.exe" : "executor";
40const targetDir = join(cliRoot, "dist", `executor-${platform}-${arch}`, "bin");
41
42if (!existsSync(join(targetDir, binaryName))) {
43 console.error(`Binary not found at ${join(targetDir, binaryName)}`);
44 process.exit(1);
45}
46
47// Copy to resources/
48mkdirSync(resourcesDir, { recursive: true });
49cpSync(join(targetDir, binaryName), join(resourcesDir, binaryName));
50chmodSync(join(resourcesDir, binaryName), 0o755);
51
52// Copy QuickJS WASM if present
53const wasmPath = join(targetDir, "emscripten-module.wasm");
54if (existsSync(wasmPath)) {
55 cpSync(wasmPath, join(resourcesDir, "emscripten-module.wasm"));
56}
57
58console.log(`Sidecar binary copied to ${resourcesDir}`);
apps/desktop/src/main.ts+32−13
@@ -63,16 +63,31 @@ let serverProcess: ChildProcess | null = null; · 62 unmodified lines
63let currentScope: string | null = null;63let currentScope: string | null = null;
64let currentPort = DEFAULT_PORT;64let currentPort = DEFAULT_PORT;
65 65
66const findServerScript = (): string => {66const isDev = !app.isPackaged;
67 // In development, use the CLI source directly67
68 const cliMain = resolve(__dirname, "../../cli/src/main.ts");68const binaryName = process.platform === "win32" ? "executor.exe" : "executor";
69 if (existsSync(cliMain)) return cliMain;69
70/**
71 * Returns { command, args, cwd } for spawning the server.
72 * - In dev mode: uses `bun run` with the CLI source
73 * - In production: uses the bundled sidecar binary
74 */
75const resolveServerCommand = (): { command: string; args: string[] } => {
76 if (isDev) {
77 const cliMain = resolve(__dirname, "../../cli/src/main.ts");
78 if (existsSync(cliMain)) {
79 return { command: "bun", args: ["run", cliMain] };
80 }
81 throw new Error("Could not find executor CLI entry point for dev mode");
82 }
70 83
71 // Fallback: look for compiled CLI84 // Production: sidecar binary bundled via extraResources
72 const cliBin = resolve(__dirname, "../../cli/bin/executor.ts");85 const sidecar = join(process.resourcesPath, binaryName);
73 if (existsSync(cliBin)) return cliBin;86 if (existsSync(sidecar)) {
87 return { command: sidecar, args: [] };
88 }
74 89
75 throw new Error("Could not find executor CLI entry point");90 throw new Error(`Sidecar binary not found at ${sidecar}`);
76};91};
77 92
78const isServerReady = async (port: number): Promise<boolean> => {93const isServerReady = async (port: number): Promise<boolean> => {
@@ -117,13 +132,17 @@ const startServer = async ( · 38 unmodified lines
117 currentScope = scopePath;132 currentScope = scopePath;
118 currentPort = port;133 currentPort = port;
119 134
120 const script = findServerScript();135 const server = resolveServerCommand();
121 const args = ["run", script, "web", "--port", String(port)];136 const args = [...server.args, "web", "--port", String(port)];
137
138 // In dev mode, run from repo root so bun can resolve workspace deps.
139 // In production, the sidecar is self-contained.
140 const cwd = isDev ? resolve(__dirname, "../../..") : scopePath;
122 141
123 serverProcess = spawn("bun", args, {142 serverProcess = spawn(server.command, args, {
124 cwd: scopePath,143 cwd,
125 stdio: ["ignore", "pipe", "pipe"],144 stdio: ["ignore", "pipe", "pipe"],
126 env: { ...process.env },145 env: { ...process.env, EXECUTOR_SCOPE_DIR: scopePath },
127 });146 });
128 147
129 serverProcess.stdout?.on("data", (data: Buffer) => {148 serverProcess.stdout?.on("data", (data: Buffer) => {
apps/marketing/src/pages/index.astro+13−82
@@ -1,8 +1,5 @@
1---1---
2import Layout from '../layouts/Layout.astro'2import Layout from '../layouts/Layout.astro'
3
4const mcpCode = `<span class="text-ink-muted">$</span> executor mcp --stdio
5<span class="text-ink-faint"> 482 tools · policies active · auth shared</span>`
6---3---
7 4
8<Layout>5<Layout>
@@ -11,11 +8,11 @@ const mcpCode = `<span class="text-ink-muted">$</span> executor mcp --stdio · 2 unmodified lines
11 <div class="max-w-[1200px] mx-auto px-6 sm:px-10 h-14 flex items-center justify-between border-b border-rule">8 <div class="max-w-[1200px] mx-auto px-6 sm:px-10 h-14 flex items-center justify-between border-b border-rule">
12 <a href="/" class="font-display text-xl italic text-ink tracking-tight hover:text-teal transition-colors">executor</a>9 <a href="/" class="font-display text-xl italic text-ink tracking-tight hover:text-teal transition-colors">executor</a>
13 <div class="flex items-center gap-8">10 <div class="flex items-center gap-8">
14 <a href="#how-it-works" class="hidden sm:block text-[13px] text-ink-muted hover:text-ink transition-colors">How it works</a>
15 <a href="#roadmap" class="hidden sm:block text-[13px] text-ink-muted hover:text-ink transition-colors">Roadmap</a>11 <a href="#roadmap" class="hidden sm:block text-[13px] text-ink-muted hover:text-ink transition-colors">Roadmap</a>
12 <a href="/setup" class="hidden sm:block text-[13px] text-ink-muted hover:text-ink transition-colors">Setup</a>
16 <a href="https://github.com/RhysSullivan/executor" class="hidden sm:block text-[13px] text-ink-muted hover:text-ink transition-colors">GitHub</a>13 <a href="https://github.com/RhysSullivan/executor" class="hidden sm:block text-[13px] text-ink-muted hover:text-ink transition-colors">GitHub</a>
17 <a href="https://github.com/RhysSullivan/executor" class="text-[13px] font-medium text-surface bg-teal hover:bg-teal-dim px-4 py-1.5 rounded-md transition-colors">14 <a href="/setup" class="text-[13px] font-medium text-surface bg-teal hover:bg-teal-dim px-4 py-1.5 rounded-md transition-colors">
18 Get started15 Download
19 </a>16 </a>
20 </div>17 </div>
21 </div>18 </div>
@@ -38,13 +35,10 @@ const mcpCode = `<span class="text-ink-muted">$</span> executor mcp --stdio · 16 unmodified lines
38 </p>35 </p>
39 36
40 <div class="rise-d3 flex flex-wrap items-center justify-center gap-4">37 <div class="rise-d3 flex flex-wrap items-center justify-center gap-4">
41 <a href="https://github.com/RhysSullivan/executor" class="inline-flex items-center gap-2 text-[14px] font-medium text-surface bg-teal hover:bg-teal-dim px-5 py-2.5 rounded-md transition-colors">38 <a href="/setup" class="inline-flex items-center gap-2 text-[14px] font-medium text-surface bg-teal hover:bg-teal-dim px-5 py-2.5 rounded-md transition-colors">
42 Get started39 Get started
43 <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 7l5 5m0 0l-5 5m5-5H6" /></svg>40 <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 7l5 5m0 0l-5 5m5-5H6" /></svg>
44 </a>41 </a>
45 <a href="#how-it-works" class="inline-flex items-center gap-2 text-[14px] text-ink-muted hover:text-ink border border-rule hover:border-ink-faint px-5 py-2.5 rounded-md transition-colors">
46 How it works
47 </a>
48 </div>42 </div>
49 </div>43 </div>
50 44
@@ -686,75 +680,6 @@ const mcpCode = `<span class="text-ink-muted">$</span> executor mcp --stdio · 635 unmodified lines
686 </div>680 </div>
687 </section>681 </section>
688 682
689 <!-- ─── HOW IT WORKS: compact ─── -->
690 <section id="how-it-works" class="py-32 sm:py-40 relative">
691 <div class="max-w-[1200px] mx-auto px-6 sm:px-10">
692 <div class="reveal mb-20">
693 <span class="text-[11px] font-mono uppercase tracking-[0.2em] text-ink-faint mb-4 block">How it works</span>
694 <h2 class="font-display text-[clamp(2rem,4.5vw,3.5rem)] leading-[1.05] tracking-tight">
695 Four steps to<br /><span class="italic text-teal">every integration</span>
696 </h2>
697 </div>
698
699 <!-- Horizontal steps on desktop -->
700 <div class="reveal grid md:grid-cols-4 gap-px bg-rule rounded-xl overflow-hidden mb-16">
701 <div class="bg-surface p-6 sm:p-8">
702 <span class="font-display text-4xl text-teal/20 leading-none block mb-4">1</span>
703 <h3 class="text-[14px] font-medium mb-2">Add sources</h3>
704 <p class="text-[13px] text-ink-muted">Point at any API. If it has a schema, Executor indexes it.</p>
705 </div>
706 <div class="bg-surface p-6 sm:p-8">
707 <span class="font-display text-4xl text-teal/20 leading-none block mb-4">2</span>
708 <h3 class="text-[14px] font-medium mb-2">Tools are indexed</h3>
709 <p class="text-[13px] text-ink-muted">Every endpoint becomes a typed, discoverable tool in your catalog.</p>
710 </div>
711 <div class="bg-surface p-6 sm:p-8">
712 <span class="font-display text-4xl text-teal/20 leading-none block mb-4">3</span>
713 <h3 class="text-[14px] font-medium mb-2">Set policies</h3>
714 <p class="text-[13px] text-ink-muted">Define what's auto-approved and what needs human sign-off.</p>
715 </div>
716 <div class="bg-surface p-6 sm:p-8">
717 <span class="font-display text-4xl text-teal/20 leading-none block mb-4">4</span>
718 <h3 class="text-[14px] font-medium mb-2">Connect agents</h3>
719 <p class="text-[13px] text-ink-muted">Expose your catalog over MCP. Any agent gets your tools and auth.</p>
720 </div>
721 </div>
722
723 <!-- Single code block showing the MCP bridge -->
724 <div class="reveal max-w-lg mx-auto">
725 <div class="bg-surface-raised border border-rule rounded-lg overflow-hidden">
726 <div class="px-4 py-2.5 border-b border-rule">
727 <span class="text-[11px] font-mono text-ink-faint">terminal</span>
728 </div>
729 <div class="p-5 font-mono text-[13px] leading-[1.8]">
730 <pre set:html={mcpCode} />
731 </div>
732 </div>
733 </div>
734 </div>
735 </section>
736
737 <!-- ─── SOURCES: visual strip ─── -->
738 <section class="py-20 relative">
739 <div class="absolute inset-0 border-t border-b border-rule"></div>
740
741 <div class="relative max-w-[1200px] mx-auto px-6 sm:px-10">
742 <div class="flex flex-wrap items-center justify-between gap-6">
743 <span class="text-[13px] text-ink-muted">If you can represent it in JSON schema, it's an integration</span>
744 <div class="flex items-center gap-4 sm:gap-8">
745 <span class="font-mono text-[13px] text-teal/70">OpenAPI</span>
746 <span class="text-ink-faint">&middot;</span>
747 <span class="font-mono text-[13px] text-teal/70">GraphQL</span>
748 <span class="text-ink-faint">&middot;</span>
749 <span class="font-mono text-[13px] text-teal/70">MCP</span>
750 <span class="text-ink-faint">&middot;</span>
751 <span class="font-mono text-[13px] text-teal/70">Google Discovery</span>
752 <span class="text-ink-faint">&middot;</span>
753 <span class="font-mono text-[13px] text-ink-muted italic">yours</span>
754 </div>
755 </div>
756 </div>
757 </section>
758 683
759 <!-- ─── ROADMAP ─── -->684 <!-- ─── ROADMAP ─── -->
760 <section id="roadmap" class="py-32 sm:py-40 relative">685 <section id="roadmap" class="py-32 sm:py-40 relative">
@@ -792,6 +717,10 @@ const mcpCode = `<span class="text-ink-muted">$</span> executor mcp --stdio · 31 unmodified lines
792 <svg class="w-4 h-4 text-teal mt-0.5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5" /></svg>717 <svg class="w-4 h-4 text-teal mt-0.5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5" /></svg>
793 <span class="text-ink-muted">Local web UI</span>718 <span class="text-ink-muted">Local web UI</span>
794 </li>719 </li>
720 <li class="flex items-start gap-2.5">
721 <svg class="w-4 h-4 text-teal mt-0.5 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5" /></svg>
722 <span class="text-ink-muted">Desktop app</span>
723 </li>
795 </ul>724 </ul>
796 </div>725 </div>
797 </div>726 </div>
@@ -803,7 +732,6 @@ const mcpCode = `<span class="text-ink-muted">$</span> executor mcp --stdio · 5 unmodified lines
803 <span class="font-mono text-[11px] text-ink-muted uppercase tracking-[0.15em]">Soon</span>732 <span class="font-mono text-[11px] text-ink-muted uppercase tracking-[0.15em]">Soon</span>
804 </div>733 </div>
805 <ul class="space-y-3 text-[14px]">734 <ul class="space-y-3 text-[14px]">
806 <li class="text-ink-muted">Desktop app</li>
807 <li class="text-ink-muted">Team management &amp; SaaS</li>735 <li class="text-ink-muted">Team management &amp; SaaS</li>
808 <li class="text-ink-muted">Advanced approval workflows</li>736 <li class="text-ink-muted">Advanced approval workflows</li>
809 <li class="text-ink-muted">Org-wide source catalog</li>737 <li class="text-ink-muted">Org-wide source catalog</li>
@@ -838,9 +766,12 @@ const mcpCode = `<span class="text-ink-muted">$</span> executor mcp --stdio · 28 unmodified lines
838 </h2>766 </h2>
839 767
840 <div class="flex flex-col sm:flex-row items-center justify-center gap-4 mb-10">768 <div class="flex flex-col sm:flex-row items-center justify-center gap-4 mb-10">
841 <a href="https://github.com/RhysSullivan/executor" class="inline-flex items-center gap-2 text-[14px] font-medium text-surface bg-teal hover:bg-teal-dim px-6 py-3 rounded-md transition-colors">769 <a href="/setup" class="inline-flex items-center gap-2 text-[14px] font-medium text-surface bg-teal hover:bg-teal-dim px-6 py-3 rounded-md transition-colors">
842 Get started770 Get started
843 <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 7l5 5m0 0l-5 5m5-5H6" /></svg>771 <svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M19 14l-7 7m0 0l-7-7m7 7V3"/></svg>
772 </a>
773 <a href="https://github.com/RhysSullivan/executor" class="inline-flex items-center gap-2 text-[14px] text-ink-muted hover:text-ink border border-rule hover:border-ink-faint px-6 py-3 rounded-md transition-colors">
774 View on GitHub
844 </a>775 </a>
845 </div>776 </div>
846 777
apps/marketing/src/pages/setup.astro+159−0
@@ -0,0 +1,159 @@
1---
2import Layout from '../layouts/Layout.astro'
3---
4
5<Layout title="Setup Executor" description="Get started with Executor — download the desktop app or install via CLI.">
6 <!-- ─── NAV ─── -->
7 <nav class="fixed top-0 w-full z-50 bg-surface/80 backdrop-blur-lg">
8 <div class="max-w-[1200px] mx-auto px-6 sm:px-10 h-14 flex items-center justify-between border-b border-rule">
9 <a href="/" class="font-display text-xl italic text-ink tracking-tight hover:text-teal transition-colors">executor</a>
10 <div class="flex items-center gap-8">
11 <a href="/setup" class="hidden sm:block text-[13px] text-ink hover:text-ink transition-colors">Setup</a>
12 <a href="https://github.com/RhysSullivan/executor" class="hidden sm:block text-[13px] text-ink-muted hover:text-ink transition-colors">GitHub</a>
13 </div>
14 </div>
15 </nav>
16
17 <main class="pt-14">
18 <section class="py-24 sm:py-32 relative">
19 <div class="absolute top-[20%] left-[50%] -translate-x-1/2 w-[600px] h-[400px] bg-teal/[0.03] rounded-full blur-[150px] pointer-events-none"></div>
20
21 <div class="max-w-[1200px] mx-auto px-6 sm:px-10">
22 <div class="text-center max-w-2xl mx-auto mb-16">
23 <h1 class="font-display text-[clamp(2.5rem,5vw,4rem)] leading-[1.05] tracking-tight mb-6">
24 Get started with <span class="italic text-teal">Executor</span>
25 </h1>
26 <p class="text-[16px] leading-[1.7] text-ink-muted">
27 Manage sources, secrets, and tools from a native desktop app &mdash; or run straight from the command line.
28 </p>
29 </div>
30
31 <!-- ─── PRIMARY: auto-detected download ─── -->
32 <div class="max-w-md mx-auto text-center mb-6" id="primary-download">
33 <a id="primary-btn" href="#" class="inline-flex items-center gap-2.5 text-[15px] font-medium text-surface bg-teal hover:bg-teal-dim px-8 py-3.5 rounded-lg transition-colors">
34 <svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M19 14l-7 7m0 0l-7-7m7 7V3"/></svg>
35 <span id="primary-label">Download for macOS</span>
36 </a>
37 <p class="mt-3 text-[12px] text-ink-faint" id="primary-meta">Apple Silicon &amp; Intel &middot; .dmg</p>
38 </div>
39
40 <!-- Other platforms link -->
41 <div class="text-center mb-20">
42 <button onclick="document.getElementById('all-platforms').classList.toggle('hidden')" class="text-[13px] text-ink-faint hover:text-ink transition-colors underline underline-offset-2 decoration-rule hover:decoration-ink-faint">
43 Other platforms
44 </button>
45 </div>
46
47 <!-- ─── EXPANDED: all platforms (hidden by default) ─── -->
48 <div class="hidden max-w-2xl mx-auto mb-20" id="all-platforms">
49 <div class="grid sm:grid-cols-3 gap-4">
50 <a id="link-mac" href="#" class="group rounded-xl border border-rule hover:border-teal/30 p-5 text-center transition-all">
51 <div class="text-[14px] font-medium text-ink mb-1">macOS</div>
52 <p class="text-[11px] text-ink-faint">Apple Silicon &amp; Intel &middot; .dmg</p>
53 </a>
54 <a id="link-win" href="#" class="group rounded-xl border border-rule hover:border-teal/30 p-5 text-center transition-all">
55 <div class="text-[14px] font-medium text-ink mb-1">Windows</div>
56 <p class="text-[11px] text-ink-faint">Windows 10+ &middot; .exe</p>
57 </a>
58 <a id="link-linux" href="#" class="group rounded-xl border border-rule hover:border-teal/30 p-5 text-center transition-all">
59 <div class="text-[14px] font-medium text-ink mb-1">Linux</div>
60 <p class="text-[11px] text-ink-faint">AppImage &amp; .deb</p>
61 </a>
62 </div>
63 </div>
64
65 <!-- ─── CLI alternative ─── -->
66 <div class="max-w-md mx-auto">
67 <div class="flex items-center justify-center gap-3 mb-6">
68 <div class="h-px flex-1 bg-rule"></div>
69 <span class="font-mono text-[11px] text-ink-faint uppercase tracking-[0.15em]">Or via CLI</span>
70 <div class="h-px flex-1 bg-rule"></div>
71 </div>
72
73 <button onclick="copyCommand('npx executor web')" class="group w-full flex items-center justify-between gap-3 bg-surface-raised border border-rule rounded-lg px-4 py-3 font-mono text-[13px] hover:border-ink-faint transition-colors text-left">
74 <div>
75 <span class="text-ink-faint select-none">$ </span><span class="text-ink">npx executor web</span>
76 </div>
77 <svg class="w-4 h-4 text-ink-faint group-hover:text-ink transition-colors shrink-0 copy-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>
78 <svg class="w-4 h-4 text-teal shrink-0 check-icon hidden" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"/></svg>
79 </button>
80 </div>
81 </div>
82 </section>
83 </main>
84
85 <!-- ─── FOOTER ─── -->
86 <footer class="border-t border-rule py-10">
87 <div class="max-w-[1200px] mx-auto px-6 sm:px-10 flex items-center justify-between">
88 <span class="font-display italic text-ink-faint text-sm">executor</span>
89 <a href="https://github.com/RhysSullivan/executor" class="text-[13px] text-ink-faint hover:text-ink transition-colors">GitHub</a>
90 </div>
91 </footer>
92
93 <script is:inline>
94 const REPO = 'RhysSullivan/executor';
95 const RELEASE_API = `https://api.github.com/repos/${REPO}/releases/latest`;
96
97 const PLATFORMS = {
98 mac: { label: 'Download for macOS', meta: 'Apple Silicon & Intel \u00b7 .dmg', ext: '.dmg' },
99 win: { label: 'Download for Windows', meta: 'Windows 10+ \u00b7 .exe', ext: '.exe' },
100 linux: { label: 'Download for Linux', meta: 'AppImage', ext: '.AppImage' },
101 };
102
103 function detectOS() {
104 const ua = navigator.userAgent.toLowerCase();
105 if (ua.includes('mac')) return 'mac';
106 if (ua.includes('win')) return 'win';
107 return 'linux';
108 }
109
110 async function setup() {
111 const userOS = detectOS();
112 const platform = PLATFORMS[userOS];
113
114 // Set primary button text immediately
115 document.getElementById('primary-label').textContent = platform.label;
116 document.getElementById('primary-meta').textContent = platform.meta;
117
118 try {
119 const res = await fetch(RELEASE_API);
120 if (!res.ok) return;
121 const release = await res.json();
122 const assets = release.assets || [];
123
124 const findAsset = (ext) => assets.find(a => a.name.endsWith(ext));
125
126 const macUrl = findAsset('.dmg')?.browser_download_url;
127 const winUrl = findAsset('.exe')?.browser_download_url;
128 const linuxUrl = findAsset('.AppImage')?.browser_download_url;
129
130 const urls = { mac: macUrl, win: winUrl, linux: linuxUrl };
131
132 // Set primary button to user's OS
133 if (urls[userOS]) {
134 document.getElementById('primary-btn').href = urls[userOS];
135 }
136
137 // Set "other platforms" links
138 if (macUrl) document.getElementById('link-mac').href = macUrl;
139 if (winUrl) document.getElementById('link-win').href = winUrl;
140 if (linuxUrl) document.getElementById('link-linux').href = linuxUrl;
141 } catch {
142 // Silent fail — buttons just won't have hrefs
143 }
144 }
145
146 function copyCommand(cmd) {
147 const btn = event.currentTarget;
148 navigator.clipboard.writeText(cmd);
149 btn.querySelector('.copy-icon').classList.add('hidden');
150 btn.querySelector('.check-icon').classList.remove('hidden');
151 setTimeout(() => {
152 btn.querySelector('.copy-icon').classList.remove('hidden');
153 btn.querySelector('.check-icon').classList.add('hidden');
154 }, 1500);
155 }
156
157 setup();
158 </script>
159</Layout>
apps/server/src/services/executor.ts+3−3
@@ -93,12 +93,12 @@ const ExecutorLayer = Layer.effect( · 92 unmodified lines
93 93
94 yield* migrate.pipe(Effect.catchAll((e) => Effect.die(e)));94 yield* migrate.pipe(Effect.catchAll((e) => Effect.die(e)));
95 95
96 const cwd = process.cwd();96 const cwd = process.env.EXECUTOR_SCOPE_DIR || process.cwd();
97 const kv = makeSqliteKv(sql);97 const kv = makeSqliteKv(sql);
98 const config = makeKvConfig(kv, { cwd });98 const config = makeKvConfig(kv, { cwd });
99 const scopedKv = makeScopedKv(kv, cwd);99 const scopedKv = makeScopedKv(kv, cwd);
100 100
101 const configPath = join(process.cwd(), "executor.jsonc");101 const configPath = join(cwd, "executor.jsonc");
102 const fsLayer = NodeFileSystem.layer;102 const fsLayer = NodeFileSystem.layer;
103 103
104 return yield* createExecutor({104 return yield* createExecutor({
@@ -131,7 +131,7 @@ const ExecutorLayer = Layer.effect( · 26 unmodified lines
131 fsLayer,131 fsLayer,
132 ),132 ),
133 }),133 }),
134 // keychainPlugin(),134 keychainPlugin(),
135 fileSecretsPlugin(),135 fileSecretsPlugin(),
136 onepasswordPlugin({136 onepasswordPlugin({
137 kv: scopeKv(scopedKv, "onepassword"),137 kv: scopeKv(scopedKv, "onepassword"),
bun.lock+2−29
@@ -41,12 +41,9 @@ · 40 unmodified lines
41 "apps/desktop": {41 "apps/desktop": {
42 "name": "@executor/desktop",42 "name": "@executor/desktop",
43 "version": "1.4.0",43 "version": "1.4.0",
44 "dependencies": {
45 "electron-store": "^10.0.0",
46 },
47 "devDependencies": {44 "devDependencies": {
48 "@types/node": "catalog:",45 "@types/node": "catalog:",
49 "electron": "^35.0.1",46 "electron": "35.7.5",
50 "electron-builder": "^26.0.12",47 "electron-builder": "^26.0.12",
51 "typescript": "^5.9.3",48 "typescript": "^5.9.3",
52 },49 },
@@ -1537,8 +1534,6 @@ · 1484 unmodified lines
1537 1534
1538 "at-least-node": ["at-least-node@1.0.0", "", {}, "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="],1535 "at-least-node": ["at-least-node@1.0.0", "", {}, "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="],
1539 1536
1540 "atomically": ["atomically@2.1.1", "", { "dependencies": { "stubborn-fs": "^2.0.0", "when-exit": "^2.1.4" } }, "sha512-P4w9o2dqARji6P7MHprklbfiArZAWvo07yW7qs3pdljb3BWr12FIB7W+p0zJiuiVsUpRO0iZn1kFFcpPegg0tQ=="],
1541
1542 "autoprefixer": ["autoprefixer@10.4.27", "", { "dependencies": { "browserslist": "^4.28.1", "caniuse-lite": "^1.0.30001774", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA=="],1537 "autoprefixer": ["autoprefixer@10.4.27", "", { "dependencies": { "browserslist": "^4.28.1", "caniuse-lite": "^1.0.30001774", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA=="],
1543 1538
1544 "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],1539 "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
@@ -1665,8 +1660,6 @@ · 120 unmodified lines
1665 1660
1666 "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],1661 "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
1667 1662
1668 "conf": ["conf@14.0.0", "", { "dependencies": { "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "atomically": "^2.0.3", "debounce-fn": "^6.0.0", "dot-prop": "^9.0.0", "env-paths": "^3.0.0", "json-schema-typed": "^8.0.1", "semver": "^7.7.2", "uint8array-extras": "^1.4.0" } }, "sha512-L6BuueHTRuJHQvQVc6YXYZRtN5vJUtOdCTLn0tRYYV5azfbAFcPghB5zEE40mVrV6w7slMTqUfkDomutIK14fw=="],
1669
1670 "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],1663 "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
1671 1664
1672 "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="],1665 "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="],
@@ -1785,8 +1778,6 @@ · 112 unmodified lines
1785 1778
1786 "dayjs": ["dayjs@1.11.20", "", {}, "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ=="],1779 "dayjs": ["dayjs@1.11.20", "", {}, "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ=="],
1787 1780
1788 "debounce-fn": ["debounce-fn@6.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-rBMW+F2TXryBwB54Q0d8drNEI+TfoS9JpNTAoVpukbWEhjXQq4rySFYLaqXMFXwdv61Zb2OHtj5bviSoimqxRQ=="],
1789
1790 "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],1781 "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
1791 1782
1792 "decimal.js-light": ["decimal.js-light@2.5.1", "", {}, "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="],1783 "decimal.js-light": ["decimal.js-light@2.5.1", "", {}, "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="],
@@ -1853,8 +1844,6 @@ · 60 unmodified lines
1853 1844
1854 "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],1845 "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
1855 1846
1856 "dot-prop": ["dot-prop@9.0.0", "", { "dependencies": { "type-fest": "^4.18.2" } }, "sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ=="],
1857
1858 "dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],1847 "dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],
1859 1848
1860 "dotenv-expand": ["dotenv-expand@11.0.7", "", { "dependencies": { "dotenv": "^16.4.5" } }, "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA=="],1849 "dotenv-expand": ["dotenv-expand@11.0.7", "", { "dependencies": { "dotenv": "^16.4.5" } }, "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA=="],
@@ -1879,8 +1868,6 @@ · 18 unmodified lines
1879 1868
1880 "electron-publish": ["electron-publish@26.8.1", "", { "dependencies": { "@types/fs-extra": "^9.0.11", "builder-util": "26.8.1", "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "form-data": "^4.0.5", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "mime": "^2.5.2" } }, "sha512-q+jrSTIh/Cv4eGZa7oVR+grEJo/FoLMYBAnSL5GCtqwUpr1T+VgKB/dn1pnzxIxqD8S/jP1yilT9VrwCqINR4w=="],1869 "electron-publish": ["electron-publish@26.8.1", "", { "dependencies": { "@types/fs-extra": "^9.0.11", "builder-util": "26.8.1", "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "form-data": "^4.0.5", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "mime": "^2.5.2" } }, "sha512-q+jrSTIh/Cv4eGZa7oVR+grEJo/FoLMYBAnSL5GCtqwUpr1T+VgKB/dn1pnzxIxqD8S/jP1yilT9VrwCqINR4w=="],
1881 1870
1882 "electron-store": ["electron-store@10.1.0", "", { "dependencies": { "conf": "^14.0.0", "type-fest": "^4.41.0" } }, "sha512-oL8bRy7pVCLpwhmXy05Rh/L6O93+k9t6dqSw0+MckIc3OmCTZm6Mp04Q4f/J0rtu84Ky6ywkR8ivtGOmrq+16w=="],
1883
1884 "electron-to-chromium": ["electron-to-chromium@1.5.330", "", {}, "sha512-jFNydB5kFtYUobh4IkWUnXeyDbjf/r9gcUEXe1xcrcUxIGfTdzPXA+ld6zBRbwvgIGVzDll/LTIiDztEtckSnA=="],1871 "electron-to-chromium": ["electron-to-chromium@1.5.330", "", {}, "sha512-jFNydB5kFtYUobh4IkWUnXeyDbjf/r9gcUEXe1xcrcUxIGfTdzPXA+ld6zBRbwvgIGVzDll/LTIiDztEtckSnA=="],
1885 1872
1886 "electron-winstaller": ["electron-winstaller@5.4.0", "", { "dependencies": { "@electron/asar": "^3.2.1", "debug": "^4.1.1", "fs-extra": "^7.0.1", "lodash": "^4.17.21", "temp": "^0.9.0" }, "optionalDependencies": { "@electron/windows-sign": "^1.1.2" } }, "sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg=="],1873 "electron-winstaller": ["electron-winstaller@5.4.0", "", { "dependencies": { "@electron/asar": "^3.2.1", "debug": "^4.1.1", "fs-extra": "^7.0.1", "lodash": "^4.17.21", "temp": "^0.9.0" }, "optionalDependencies": { "@electron/windows-sign": "^1.1.2" } }, "sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg=="],
@@ -2401,8 +2388,6 @@ · 514 unmodified lines
2401 2388
2402 "mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],2389 "mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
2403 2390
2404 "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
2405
2406 "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],2391 "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],
2407 2392
2408 "minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],2393 "minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
@@ -2855,10 +2840,6 @@ · 446 unmodified lines
2855 2840
2856 "strip-literal": ["strip-literal@3.1.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg=="],2841 "strip-literal": ["strip-literal@3.1.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg=="],
2857 2842
2858 "stubborn-fs": ["stubborn-fs@2.0.0", "", { "dependencies": { "stubborn-utils": "^1.0.1" } }, "sha512-Y0AvSwDw8y+nlSNFXMm2g6L51rBGdAQT20J3YSOqxC53Lo3bjWRtr2BKcfYoAf352WYpsZSTURrA0tqhfgudPA=="],
2859
2860 "stubborn-utils": ["stubborn-utils@1.0.2", "", {}, "sha512-zOh9jPYI+xrNOyisSelgym4tolKTJCQd5GBhK0+0xJvcYDcwlOoxF/rnFKQ2KRZknXSG9jWAp66fwP6AxN9STg=="],
2861
2862 "style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="],2843 "style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="],
2863 2844
2864 "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="],2845 "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="],
@@ -2939,7 +2920,7 @@ · 74 unmodified lines
2939 2920
2940 "turbo": ["turbo@2.9.2", "", { "optionalDependencies": { "@turbo/darwin-64": "2.9.2", "@turbo/darwin-arm64": "2.9.2", "@turbo/linux-64": "2.9.2", "@turbo/linux-arm64": "2.9.2", "@turbo/windows-64": "2.9.2", "@turbo/windows-arm64": "2.9.2" }, "bin": { "turbo": "bin/turbo" } }, "sha512-DUUWysctg/vax8W05UJcyrHm4LvxtX0umAT4bZB5lab4inNXTbwoYSFpdgqzBxON23j8ls3xGxvx0kwQz6Q8wQ=="],2921 "turbo": ["turbo@2.9.2", "", { "optionalDependencies": { "@turbo/darwin-64": "2.9.2", "@turbo/darwin-arm64": "2.9.2", "@turbo/linux-64": "2.9.2", "@turbo/linux-arm64": "2.9.2", "@turbo/windows-64": "2.9.2", "@turbo/windows-arm64": "2.9.2" }, "bin": { "turbo": "bin/turbo" } }, "sha512-DUUWysctg/vax8W05UJcyrHm4LvxtX0umAT4bZB5lab4inNXTbwoYSFpdgqzBxON23j8ls3xGxvx0kwQz6Q8wQ=="],
2941 2922
2942 "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],2923 "type-fest": ["type-fest@0.13.1", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="],
2943 2924
2944 "type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],2925 "type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
2945 2926
@@ -2947,8 +2928,6 @@ · 1 unmodified line
2947 2928
2948 "ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="],2929 "ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="],
2949 2930
2950 "uint8array-extras": ["uint8array-extras@1.5.0", "", {}, "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A=="],
2951
2952 "ultrahtml": ["ultrahtml@1.6.0", "", {}, "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw=="],2931 "ultrahtml": ["ultrahtml@1.6.0", "", {}, "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw=="],
2953 2932
2954 "uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="],2933 "uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="],
@@ -3047,8 +3026,6 @@ · 92 unmodified lines
3047 3026
3048 "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],3027 "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
3049 3028
3050 "when-exit": ["when-exit@2.1.5", "", {}, "sha512-VGkKJ564kzt6Ms1dbgPP/yuIoQCrsFAnRbptpC5wOEsDaNsbCB2bnfnaA8i/vRs5tjUSEOtIuvl9/MyVsvQZCg=="],
3051
3052 "which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="],3029 "which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="],
3053 3030
3054 "which-pm-runs": ["which-pm-runs@1.1.0", "", {}, "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA=="],3031 "which-pm-runs": ["which-pm-runs@1.1.0", "", {}, "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA=="],
@@ -3207,8 +3184,6 @@ · 152 unmodified lines
3207 3184
3208 "clone-response/mimic-response": ["mimic-response@1.0.1", "", {}, "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="],3185 "clone-response/mimic-response": ["mimic-response@1.0.1", "", {}, "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="],
3209 3186
3210 "conf/env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="],
3211
3212 "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],3187 "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
3213 3188
3214 "csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="],3189 "csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="],
@@ -3291,8 +3266,6 @@ · 76 unmodified lines
3291 3266
3292 "router/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="],3267 "router/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="],
3293 3268
3294 "serialize-error/type-fest": ["type-fest@0.13.1", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="],
3295
3296 "tar-fs/chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],3269 "tar-fs/chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
3297 3270
3298 "temp-file/fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="],3271 "temp-file/fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="],
package.json+1−1
@@ -21,7 +21,7 @@ · 20 unmodified lines
21 "license": "MIT",21 "license": "MIT",
22 "private": true,22 "private": true,
23 "type": "module",23 "type": "module",
24 "packageManager": "bun@1.2.22",24 "packageManager": "bun@1.3.11",
25 "workspaces": [25 "workspaces": [
26 "packages/*/*",26 "packages/*/*",
27 "packages/ui",27 "packages/ui",