Skip to content

Commit 312a3a3

Browse files
author
Bruno Azoulay
authored
Merge pull request #3 from fusengine/refactor/installer-bun-portage
refactor(installer)!: port installer engine to TypeScript/bun
2 parents 308b1e7 + 2947e2a commit 312a3a3

211 files changed

Lines changed: 9954 additions & 1024 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.codex/apex/task.json‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"current_task": "task-1788259000",
2+
"current_task": "readme-remote-installation",
33
"created_at": "2026-08-29T15:41:42Z",
44
"tasks": {
55
"task-1788018121": {
@@ -33,6 +33,18 @@
3333
"cursor-loader": "docs/reference/project-loader.md",
3434
"cursor-compatibility": "docs/reference/migration-compatibility.md"
3535
}
36+
},
37+
"readme-remote-installation": {
38+
"subject": "Replace clone-local README installation with a verified remote Cursor installation flow",
39+
"status": "in_progress",
40+
"phase": "validation",
41+
"started_at": "2026-09-01T10:26:23Z",
42+
"doc_consulted": {
43+
"cursor-cli-changelog": "https://cursor.com/docs/cli/changelog",
44+
"cursor-cli-slash-commands": "https://cursor.com/docs/cli/reference/slash-commands",
45+
"cursor-plugins": "https://cursor.com/docs/plugins",
46+
"codex-reference-readme": "Adjacent Codex plugins repository: root README.md"
47+
}
3648
}
3749
}
3850
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name": "@fusengine/cursor-harness",
3+
"version": "1.0.0",
4+
"private": true,
5+
"description": "Fusengine Cursor global harness vendor manifest - single shared install of @fusengine/harness under ~/.cursor/.fusengine-global/node_modules, always tracking the latest published release.",
6+
"dependencies": {
7+
"@fusengine/harness": "latest"
8+
}
9+
}

‎.cursor-plugin/marketplace.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
},
77
"metadata": {
88
"description": "Professional Cursor plugins with APEX workflow, SOLID principles, and expert development agents for Next.js, Laravel, Swift, Tailwind CSS, and more",
9-
"version": "1.39.26"
9+
"version": "0.1.1"
1010
},
1111
"plugins": [
1212
{

‎.cursor-plugin/mcp/catalog.json‎

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
{
2+
"mcpServers": {
3+
"_comment": "MCP Servers catalog for Fusengine Plugins installer - Verified packages only",
4+
5+
"sequential-thinking": {
6+
"_description": "Dynamic problem-solving with step-by-step reasoning",
7+
"command": "npx",
8+
"args": ["-y", "@modelcontextprotocol/server-sequential-thinking"],
9+
"type": "stdio",
10+
"requiresApiKey": false
11+
},
12+
"memory": {
13+
"_description": "Knowledge graph-based persistent memory system",
14+
"command": "npx",
15+
"args": ["-y", "@modelcontextprotocol/server-memory"],
16+
"type": "stdio",
17+
"requiresApiKey": false
18+
},
19+
"filesystem": {
20+
"_description": "Secure local file operations with configurable access",
21+
"command": "npx",
22+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "${HOME}"],
23+
"type": "stdio",
24+
"requiresApiKey": false,
25+
"default": false
26+
},
27+
"fuse-browser": {
28+
"_description": "Stealth browser automation: snapshots, multi-step plans, themed (light/dark) screenshots",
29+
"command": "npx",
30+
"args": ["-y", "@fusengine/browser-mcp@latest"],
31+
"type": "stdio",
32+
"requiresApiKey": false
33+
},
34+
"postgres": {
35+
"_description": "PostgreSQL database queries via natural language",
36+
"command": "npx",
37+
"args": ["-y", "@modelcontextprotocol/server-postgres"],
38+
"type": "stdio",
39+
"requiresApiKey": false,
40+
"default": false,
41+
"env": {
42+
"DATABASE_URL": "${DATABASE_URL}"
43+
}
44+
},
45+
"shadcn": {
46+
"_description": "shadcn/ui component registry and installation",
47+
"command": "npx",
48+
"args": ["shadcn@latest", "mcp"],
49+
"type": "stdio",
50+
"requiresApiKey": false
51+
},
52+
"next-devtools": {
53+
"_description": "Next.js development tools and debugging",
54+
"command": "npx",
55+
"args": ["-y", "next-devtools-mcp@latest"],
56+
"type": "stdio",
57+
"requiresApiKey": false
58+
},
59+
"XcodeBuildMCP": {
60+
"_description": "Xcode build, test and simulator automation for iOS/macOS",
61+
"command": "npx",
62+
"args": ["-y", "xcodebuildmcp@latest", "mcp"],
63+
"type": "stdio",
64+
"requiresApiKey": false
65+
},
66+
"apple-docs": {
67+
"_description": "Apple developer documentation and WWDC content",
68+
"command": "npx",
69+
"args": ["-y", "@kimsungwhee/apple-docs-mcp"],
70+
"type": "stdio",
71+
"requiresApiKey": false
72+
},
73+
"astro-docs": {
74+
"_description": "Search official Astro framework documentation",
75+
"type": "http",
76+
"url": "https://mcp.docs.astro.build/mcp",
77+
"requiresApiKey": false
78+
},
79+
80+
"context7": {
81+
"_description": "Up-to-date documentation lookup to reduce AI hallucinations",
82+
"command": "npx",
83+
"args": [
84+
"-y",
85+
"@upstash/context7-mcp",
86+
"--api-key",
87+
"${CONTEXT7_API_KEY}"
88+
],
89+
"type": "stdio",
90+
"default": true,
91+
"requiresApiKey": true,
92+
"apiKeyEnv": "CONTEXT7_API_KEY",
93+
"apiKeyUrl": "https://context7.com"
94+
},
95+
"exa": {
96+
"_description": "AI-powered web search, code context and deep research",
97+
"default": true,
98+
"type": "http",
99+
"url": "https://mcp.exa.ai/mcp?tools=web_search_exa,get_code_context_exa,crawling_exa,company_research_exa,linkedin_search_exa,deep_researcher_start,deep_researcher_check&exaApiKey=${EXA_API_KEY}",
100+
"headers": {},
101+
"requiresApiKey": true,
102+
"apiKeyEnv": "EXA_API_KEY",
103+
"apiKeyUrl": "https://exa.ai"
104+
},
105+
"magic": {
106+
"_description": "AI-powered UI component generation from 21st.dev",
107+
"command": "npx",
108+
"args": ["-y", "@21st-dev/magic@latest"],
109+
"env": {
110+
"MAGIC_API_KEY": "${MAGIC_API_KEY}"
111+
},
112+
"type": "stdio",
113+
"default": true,
114+
"requiresApiKey": true,
115+
"apiKeyEnv": "MAGIC_API_KEY",
116+
"apiKeyUrl": "https://21st.dev"
117+
},
118+
"gemini-design": {
119+
"_description": "AI frontend generation with Tailwind CSS and shadcn/ui",
120+
"command": "npx",
121+
"args": ["-y", "gemini-design-mcp@latest"],
122+
"env": {
123+
"API_KEY": "${GEMINI_DESIGN_API_KEY}"
124+
},
125+
"type": "stdio",
126+
"default": true,
127+
"requiresApiKey": true,
128+
"apiKeyEnv": "GEMINI_DESIGN_API_KEY",
129+
"apiKeyUrl": "https://gemini-design-mcp.com"
130+
},
131+
"github": {
132+
"_description": "GitHub repos, PRs, issues, commits and code review",
133+
"command": "npx",
134+
"args": ["-y", "@modelcontextprotocol/server-github"],
135+
"env": {
136+
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
137+
},
138+
"type": "stdio",
139+
"requiresApiKey": true,
140+
"apiKeyEnv": "GITHUB_TOKEN",
141+
"apiKeyUrl": "https://github.com/settings/tokens"
142+
},
143+
"supabase": {
144+
"_description": "Supabase database, auth, storage and migrations",
145+
"command": "npx",
146+
"args": ["-y", "supabase", "mcp"],
147+
"env": {
148+
"SUPABASE_ACCESS_TOKEN": "${SUPABASE_ACCESS_TOKEN}"
149+
},
150+
"type": "stdio",
151+
"requiresApiKey": true,
152+
"apiKeyEnv": "SUPABASE_ACCESS_TOKEN",
153+
"apiKeyUrl": "https://supabase.com/dashboard/account/tokens"
154+
},
155+
"slack": {
156+
"_description": "Slack messages, channels and workspace management",
157+
"command": "npx",
158+
"args": ["-y", "@modelcontextprotocol/server-slack"],
159+
"env": {
160+
"SLACK_TOKEN": "${SLACK_TOKEN}"
161+
},
162+
"type": "stdio",
163+
"requiresApiKey": true,
164+
"apiKeyEnv": "SLACK_TOKEN",
165+
"apiKeyUrl": "https://api.slack.com/apps"
166+
},
167+
"sentry": {
168+
"_description": "Sentry error tracking, issues and debugging",
169+
"command": "npx",
170+
"args": ["-y", "@sentry/mcp-server"],
171+
"env": {
172+
"SENTRY_AUTH_TOKEN": "${SENTRY_AUTH_TOKEN}"
173+
},
174+
"type": "stdio",
175+
"requiresApiKey": true,
176+
"apiKeyEnv": "SENTRY_AUTH_TOKEN",
177+
"apiKeyUrl": "https://sentry.io/settings/auth-tokens"
178+
},
179+
"brave-search": {
180+
"_description": "Private web search via Brave Search API",
181+
"command": "npx",
182+
"args": ["-y", "@brave/brave-search-mcp-server"],
183+
"env": {
184+
"BRAVE_API_KEY": "${BRAVE_API_KEY}"
185+
},
186+
"type": "stdio",
187+
"requiresApiKey": true,
188+
"apiKeyEnv": "BRAVE_API_KEY",
189+
"apiKeyUrl": "https://brave.com/search/api"
190+
},
191+
"serper": {
192+
"_description": "Google search (SERP) and webpage scraping via Serper API",
193+
"command": "npx",
194+
"args": ["-y", "serper-search-scrape-mcp-server"],
195+
"env": {
196+
"SERPER_API_KEY": "${SERPER_API_KEY}"
197+
},
198+
"type": "stdio",
199+
"requiresApiKey": true,
200+
"apiKeyEnv": "SERPER_API_KEY",
201+
"apiKeyUrl": "https://serper.dev/api-key"
202+
},
203+
"stripe": {
204+
"_description": "Stripe payments, invoices, customers and subscriptions",
205+
"command": "npx",
206+
"args": ["-y", "@stripe/mcp"],
207+
"env": {
208+
"STRIPE_SECRET_KEY": "${STRIPE_SECRET_KEY}"
209+
},
210+
"type": "stdio",
211+
"requiresApiKey": true,
212+
"apiKeyEnv": "STRIPE_SECRET_KEY",
213+
"apiKeyUrl": "https://dashboard.stripe.com/apikeys"
214+
},
215+
"notion": {
216+
"_description": "Notion pages, databases and knowledge base access",
217+
"command": "npx",
218+
"args": ["-y", "@notionhq/notion-mcp-server"],
219+
"env": {
220+
"NOTION_TOKEN": "${NOTION_TOKEN}"
221+
},
222+
"type": "stdio",
223+
"requiresApiKey": true,
224+
"apiKeyEnv": "NOTION_TOKEN",
225+
"apiKeyUrl": "https://www.notion.so/my-integrations"
226+
},
227+
"replicate": {
228+
"_description": "Run 1000+ AI models (Stable Diffusion, Whisper, etc.)",
229+
"type": "http",
230+
"url": "https://replicate.com/mcp?token=${REPLICATE_API_TOKEN}",
231+
"headers": {},
232+
"requiresApiKey": true,
233+
"apiKeyEnv": "REPLICATE_API_TOKEN",
234+
"apiKeyUrl": "https://replicate.com/account/api-tokens"
235+
}
236+
}
237+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/bin/sh
2+
# Fusengine hook entrypoint — shipped inside every plugin as scripts/hook.sh.
3+
#
4+
# Resolves the shared harness itself so the plugin works from the Cursor
5+
# marketplace, where no installer ever runs. Order:
6+
# 1. the vendored install under $HOME/.cursor/.fusengine-global (fast path)
7+
# 2. a self-heal `bun install` of that same shared directory, once
8+
# 3. `npx` on latest (last resort, network)
9+
#
10+
# Always tracks the LATEST published harness: the vendored manifest uses the
11+
# `latest` dist-tag and the npx fallback resolves it too, so a new release is
12+
# picked up without editing 21 wrappers.
13+
#
14+
# Resolution is relative to THIS file, never to the caller's cwd. Always exits 0
15+
# on its own failures: Cursor fails hooks open, and a broken guard must never
16+
# block the user's action.
17+
#
18+
# Usage (from hooks/hooks.json): ./scripts/hook.sh [scope...]
19+
20+
HARNESS_SPEC="latest"
21+
CONTROL_ROOT="${HOME}/.cursor/.fusengine-global"
22+
BIN="${CONTROL_ROOT}/node_modules/@fusengine/harness/dist/cli/bin.mjs"
23+
STAMP="${CONTROL_ROOT}/.selfheal-attempted"
24+
25+
run_bin() {
26+
if command -v bun >/dev/null 2>&1; then exec bun "$BIN" hook cursor "$@"; fi
27+
exec node "$BIN" hook cursor "$@"
28+
}
29+
30+
# 1. Fast path: already vendored.
31+
[ -f "$BIN" ] && run_bin "$@"
32+
33+
# 2. Self-heal once. The stamp keeps 62 hooks from stampeding the registry when
34+
# the install is genuinely impossible (offline, no bun, no network).
35+
if [ ! -e "$STAMP" ] && command -v bun >/dev/null 2>&1; then
36+
mkdir -p "$CONTROL_ROOT" 2>/dev/null && : > "$STAMP" 2>/dev/null
37+
printf '{"name":"@fusengine/cursor-harness","private":true,"dependencies":{"@fusengine/harness":"%s"}}\n' \
38+
"$HARNESS_SPEC" > "${CONTROL_ROOT}/package.json" 2>/dev/null
39+
(cd "$CONTROL_ROOT" && bun install --silent) >/dev/null 2>&1
40+
[ -f "$BIN" ] && run_bin "$@"
41+
fi
42+
43+
# 3. Last resort: npx on the latest published release.
44+
command -v npx >/dev/null 2>&1 || exit 0
45+
exec npx -y "@fusengine/harness@${HARNESS_SPEC}" hook cursor "$@"
File renamed without changes.
File renamed without changes.

.cursor-plugin/scripts/project-plugin-inventory.mjs renamed to .cursor-plugin/plugin-runtime/project-plugin-inventory.mjs

File renamed without changes.

0 commit comments

Comments
 (0)