crewcode-plugin-cli 0.1.0

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 (75) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +39 -0
  3. package/bin/crewcode.mjs +388 -0
  4. package/package.json +40 -0
  5. package/templates/plugins/README.md +25 -0
  6. package/templates/plugins/browser-docs-grabber/crewcode-plugin-api.js +80 -0
  7. package/templates/plugins/browser-docs-grabber/crewcode.plugin.json +13 -0
  8. package/templates/plugins/browser-docs-grabber/panel.html +1 -0
  9. package/templates/plugins/browser-docs-grabber/plugin.js +1 -0
  10. package/templates/plugins/codebase-graph-lite/crewcode-plugin-api.js +80 -0
  11. package/templates/plugins/codebase-graph-lite/crewcode.plugin.json +57 -0
  12. package/templates/plugins/codebase-graph-lite/panel.html +53 -0
  13. package/templates/plugins/codebase-graph-lite/plugin.js +49 -0
  14. package/templates/plugins/company-agent-http-adapter/crewcode-plugin-api.js +80 -0
  15. package/templates/plugins/company-agent-http-adapter/crewcode.plugin.json +24 -0
  16. package/templates/plugins/company-agent-http-adapter/panel.html +1 -0
  17. package/templates/plugins/company-agent-http-adapter/plugin.js +1 -0
  18. package/templates/plugins/company-agent-http-adapter/server.mjs +27 -0
  19. package/templates/plugins/git-risk-lens/crewcode-plugin-api.js +80 -0
  20. package/templates/plugins/git-risk-lens/crewcode.plugin.json +13 -0
  21. package/templates/plugins/git-risk-lens/panel.html +1 -0
  22. package/templates/plugins/git-risk-lens/plugin.js +2 -0
  23. package/templates/plugins/github-copilot-cli-provider/crewcode-plugin-api.js +80 -0
  24. package/templates/plugins/github-copilot-cli-provider/crewcode.plugin.json +42 -0
  25. package/templates/plugins/github-copilot-cli-provider/panel.html +1 -0
  26. package/templates/plugins/github-copilot-cli-provider/plugin.js +1 -0
  27. package/templates/plugins/handoff-pack/crewcode-plugin-api.js +80 -0
  28. package/templates/plugins/handoff-pack/crewcode.plugin.json +72 -0
  29. package/templates/plugins/handoff-pack/panel.html +63 -0
  30. package/templates/plugins/handoff-pack/plugin.js +156 -0
  31. package/templates/plugins/mcp-server-template/README.md +22 -0
  32. package/templates/plugins/mcp-server-template/crewcode-plugin-api.js +80 -0
  33. package/templates/plugins/mcp-server-template/crewcode.plugin.json +30 -0
  34. package/templates/plugins/mcp-server-template/panel.html +25 -0
  35. package/templates/plugins/mcp-server-template/plugin.js +9 -0
  36. package/templates/plugins/mcp-server-template/server.mjs +30 -0
  37. package/templates/plugins/mission-ci-widget/crewcode-plugin-api.js +80 -0
  38. package/templates/plugins/mission-ci-widget/crewcode.plugin.json +13 -0
  39. package/templates/plugins/mission-ci-widget/panel.html +1 -0
  40. package/templates/plugins/mission-ci-widget/plugin.js +1 -0
  41. package/templates/plugins/mock-agent-provider/crewcode-plugin-api.js +80 -0
  42. package/templates/plugins/mock-agent-provider/crewcode.plugin.json +38 -0
  43. package/templates/plugins/mock-agent-provider/panel.html +45 -0
  44. package/templates/plugins/mock-agent-provider/plugin.js +3 -0
  45. package/templates/plugins/openai-compatible-provider/README.md +17 -0
  46. package/templates/plugins/openai-compatible-provider/crewcode-plugin-api.js +80 -0
  47. package/templates/plugins/openai-compatible-provider/crewcode.plugin.json +28 -0
  48. package/templates/plugins/openai-compatible-provider/panel.html +1 -0
  49. package/templates/plugins/openai-compatible-provider/plugin.js +4 -0
  50. package/templates/plugins/openai-compatible-provider/server.mjs +21 -0
  51. package/templates/plugins/repo-radar/crewcode-plugin-api.js +80 -0
  52. package/templates/plugins/repo-radar/crewcode.plugin.json +55 -0
  53. package/templates/plugins/repo-radar/panel.html +56 -0
  54. package/templates/plugins/repo-radar/plugin.js +103 -0
  55. package/templates/plugins/static-panel-template/README.md +19 -0
  56. package/templates/plugins/static-panel-template/crewcode-plugin-api.js +80 -0
  57. package/templates/plugins/static-panel-template/crewcode.plugin.json +44 -0
  58. package/templates/plugins/static-panel-template/panel.html +36 -0
  59. package/templates/plugins/static-panel-template/plugin.js +30 -0
  60. package/templates/plugins/terminal-watchdog-lite/crewcode-plugin-api.js +80 -0
  61. package/templates/plugins/terminal-watchdog-lite/crewcode.plugin.json +13 -0
  62. package/templates/plugins/terminal-watchdog-lite/panel.html +1 -0
  63. package/templates/plugins/terminal-watchdog-lite/plugin.js +1 -0
  64. package/templates/plugins/typescript-panel-template/README.md +40 -0
  65. package/templates/plugins/typescript-panel-template/compiled/assets/panel-ECHDDxZz.js +8 -0
  66. package/templates/plugins/typescript-panel-template/compiled/assets/panel-u6HzQzUF.css +1 -0
  67. package/templates/plugins/typescript-panel-template/compiled/src/panel.html +13 -0
  68. package/templates/plugins/typescript-panel-template/crewcode.plugin.json +23 -0
  69. package/templates/plugins/typescript-panel-template/package.json +19 -0
  70. package/templates/plugins/typescript-panel-template/src/crewcode-api.ts +146 -0
  71. package/templates/plugins/typescript-panel-template/src/main.tsx +38 -0
  72. package/templates/plugins/typescript-panel-template/src/panel.html +12 -0
  73. package/templates/plugins/typescript-panel-template/src/style.css +17 -0
  74. package/templates/plugins/typescript-panel-template/tsconfig.json +20 -0
  75. package/templates/plugins/typescript-panel-template/vite.config.ts +14 -0
@@ -0,0 +1,25 @@
1
+ # CrewCode plugin templates and dogfood examples
2
+
3
+ Use these folders as local plugin starting points. Copy one into `~/.crewcode/plugins/<plugin-id>`, refresh the Plugins page, approve it, then edit from there.
4
+
5
+ ## Starter templates
6
+
7
+ | Template | Use when | Key files |
8
+ | --- | --- | --- |
9
+ | `static-panel-template` | You want a no-build HTML/CSS/JS panel. | `crewcode.plugin.json`, `panel.html`, `plugin.js`, `crewcode-plugin-api.js` |
10
+ | `typescript-panel-template` | You want a bundled TypeScript/React panel compiled to static assets. | `src/`, `vite.config.ts`, manifest entry `compiled/src/panel.html` |
11
+ | `mock-agent-provider` | You want to add a new agent provider shape before shell/network integration. | `contributes.agentProviders`, `runtime: mock` |
12
+ | `company-agent-http-adapter` | You want an HTTP-backed company/local agent provider. | `runtime: http`, `server.mjs` |
13
+ | `openai-compatible-provider` | You want an OpenAI-compatible model gateway. | `runtime: openai-compatible`, `apiKeyEnv` |
14
+ | `github-copilot-cli-provider` | You want an exec-backed CLI agent provider. | `runtime: exec`, `terminal:spawn` |
15
+ | `mcp-server-template` | You want to declare a local MCP server. | `contributes.mcpServers`, `server.mjs` |
16
+ | `browser-docs-grabber` | You want a browser toolbar action. | `contributes.browserActions` |
17
+ | `git-risk-lens` | You want a git/sidebar review lens. | `contributes.gitLenses` |
18
+
19
+ ## Template rules
20
+
21
+ - Use `crewcode-plugin-api` as the only plugin UI API. No-build plugins vendor `crewcode-plugin-api.js`; bundled plugins import or vendor the typed source.
22
+ - Keep plugin UI sandboxed. Do not import plugin React components into CrewCode's trusted renderer.
23
+ - Keep `crewcode.apiVersion` pinned to a supported version, currently `"0.1"`.
24
+ - Add only the permissions your template needs; approval and changed-permission warnings are based on the manifest permission set.
25
+ - Treat `openContext` fields as optional. Actions opened from editor, browser, terminal, chat, git, or restored tabs provide different subsets.
@@ -0,0 +1,80 @@
1
+ // Official CrewCode plugin browser helper. GENERATED from src/ — do not edit by hand.
2
+ // Runs inside sandboxed plugin iframes. It never exposes Electron APIs.
3
+ "use strict";
4
+ (() => {
5
+ // src/create-api.ts
6
+ var CREWCODE_PLUGIN_API_VERSION = "0.1";
7
+ var RESERVED_NETWORK_MESSAGE = "crewcode.network.fetch is reserved in plugin API v0. Use an agentProvider runtime (http/sse-http/openai-compatible/websocket) for network access.";
8
+ var RESERVED_SECRETS_MESSAGE = "crewcode.secrets.get is reserved in plugin API v0. Use a provider apiKeyEnv or local CLI auth instead.";
9
+ function createCrewCodeApi(options = {}) {
10
+ var _a, _b;
11
+ const timeoutMs = (_a = options.timeoutMs) != null ? _a : 1e4;
12
+ const targetOrigin = (_b = options.targetOrigin) != null ? _b : "*";
13
+ const pending = /* @__PURE__ */ new Map();
14
+ const contextListeners = /* @__PURE__ */ new Set();
15
+ let seq = 0;
16
+ let latestContext = null;
17
+ const reportError = (err) => {
18
+ const error = err instanceof Error ? err : new Error(String(err));
19
+ window.parent.postMessage({ type: "crewcode:runtimeError", message: error.message, stack: error.stack }, targetOrigin);
20
+ };
21
+ window.addEventListener("error", (event) => {
22
+ var _a2;
23
+ return reportError((_a2 = event.error) != null ? _a2 : event.message);
24
+ });
25
+ window.addEventListener("unhandledrejection", (event) => reportError(event.reason));
26
+ const request = (method, params) => {
27
+ const id = `req-${++seq}`;
28
+ window.parent.postMessage({ type: "crewcode:request", id, method, params }, targetOrigin);
29
+ return new Promise((resolve, reject) => {
30
+ pending.set(id, { resolve, reject });
31
+ window.setTimeout(() => {
32
+ if (!pending.has(id)) return;
33
+ pending.delete(id);
34
+ reject(new Error("CrewCode plugin request timed out"));
35
+ }, timeoutMs);
36
+ });
37
+ };
38
+ window.addEventListener("message", (event) => {
39
+ if (event.source !== window.parent) return;
40
+ const msg = event.data;
41
+ if (!msg || typeof msg !== "object") return;
42
+ if (msg.type === "crewcode:context") {
43
+ latestContext = msg;
44
+ for (const listener of contextListeners) listener(latestContext);
45
+ return;
46
+ }
47
+ if (msg.type === "crewcode:response" && typeof msg.id === "string" && pending.has(msg.id)) {
48
+ const callbacks = pending.get(msg.id);
49
+ pending.delete(msg.id);
50
+ if (msg.ok) callbacks.resolve(msg.result);
51
+ else callbacks.reject(new Error(typeof msg.error === "string" ? msg.error : "plugin request failed"));
52
+ }
53
+ });
54
+ return {
55
+ apiVersion: CREWCODE_PLUGIN_API_VERSION,
56
+ request,
57
+ onContext(listener) {
58
+ contextListeners.add(listener);
59
+ if (latestContext) listener(latestContext);
60
+ return () => contextListeners.delete(listener);
61
+ },
62
+ getContext: () => latestContext,
63
+ workspace: {
64
+ listFiles: () => request("workspace:listFiles"),
65
+ readFile: (sub) => request("workspace:readFile", { sub }),
66
+ writeFile: (sub, text) => request("workspace:writeFile", { sub, text })
67
+ },
68
+ network: {
69
+ fetch: () => Promise.reject(new Error(RESERVED_NETWORK_MESSAGE))
70
+ },
71
+ secrets: {
72
+ get: () => Promise.reject(new Error(RESERVED_SECRETS_MESSAGE))
73
+ }
74
+ };
75
+ }
76
+
77
+ // src/browser-global.ts
78
+ window.createCrewCodeApi = createCrewCodeApi;
79
+ window.crewcode = createCrewCodeApi();
80
+ })();
@@ -0,0 +1,13 @@
1
+ {
2
+ "$schema": "../../../schemas/crewcode.plugin.schema.json",
3
+ "id": "browser-docs-grabber",
4
+ "name": "Browser Docs Grabber",
5
+ "version": "0.1.0",
6
+ "description": "Dogfoods explicit browser action contributions for docs context workflows.",
7
+ "crewcode": { "apiVersion": "0.1" },
8
+ "permissions": ["browser:read"],
9
+ "contributes": {
10
+ "sidebarPanels": [{ "id": "docs", "title": "Docs Grabber", "icon": "target", "entry": "panel.html" }],
11
+ "browserActions": [{ "id": "open-docs-grabber", "title": "Docs Grabber", "icon": "target", "sidebarPanel": "docs", "browserContext": "selection" }]
12
+ }
13
+ }
@@ -0,0 +1 @@
1
+ <!doctype html><html><head><meta charset="utf-8"><title>Browser Docs Grabber</title><style>body{margin:0;background:#0f120f;color:#e5e7eb;font:13px Inter,system-ui;padding:16px}.mono,code{font-family:'JetBrains Mono',monospace;color:#8b9a91}.card{border:1px solid #1c2f2f;background:#121712;padding:12px;margin-top:12px}</style></head><body><div class="mono">dogfood plugin</div><h1>browser docs grabber</h1><p id="ctx">waiting for context…</p><div class="card">Opened from the browser toolbar. This tests explicit browser action placement without exposing cookies, storage, or page text automatically.</div><div class="card">Future safe path: user-selected text only via <code>browser:read</code>.</div><script src="crewcode-plugin-api.js"></script><script src="plugin.js"></script></body></html>
@@ -0,0 +1 @@
1
+ window.crewcode.onContext(ctx=>{document.getElementById('ctx').textContent=ctx.workspace?`${ctx.workspace.name} · ${ctx.workspace.kind}`:'no workspace'})
@@ -0,0 +1,80 @@
1
+ // Official CrewCode plugin browser helper. GENERATED from src/ — do not edit by hand.
2
+ // Runs inside sandboxed plugin iframes. It never exposes Electron APIs.
3
+ "use strict";
4
+ (() => {
5
+ // src/create-api.ts
6
+ var CREWCODE_PLUGIN_API_VERSION = "0.1";
7
+ var RESERVED_NETWORK_MESSAGE = "crewcode.network.fetch is reserved in plugin API v0. Use an agentProvider runtime (http/sse-http/openai-compatible/websocket) for network access.";
8
+ var RESERVED_SECRETS_MESSAGE = "crewcode.secrets.get is reserved in plugin API v0. Use a provider apiKeyEnv or local CLI auth instead.";
9
+ function createCrewCodeApi(options = {}) {
10
+ var _a, _b;
11
+ const timeoutMs = (_a = options.timeoutMs) != null ? _a : 1e4;
12
+ const targetOrigin = (_b = options.targetOrigin) != null ? _b : "*";
13
+ const pending = /* @__PURE__ */ new Map();
14
+ const contextListeners = /* @__PURE__ */ new Set();
15
+ let seq = 0;
16
+ let latestContext = null;
17
+ const reportError = (err) => {
18
+ const error = err instanceof Error ? err : new Error(String(err));
19
+ window.parent.postMessage({ type: "crewcode:runtimeError", message: error.message, stack: error.stack }, targetOrigin);
20
+ };
21
+ window.addEventListener("error", (event) => {
22
+ var _a2;
23
+ return reportError((_a2 = event.error) != null ? _a2 : event.message);
24
+ });
25
+ window.addEventListener("unhandledrejection", (event) => reportError(event.reason));
26
+ const request = (method, params) => {
27
+ const id = `req-${++seq}`;
28
+ window.parent.postMessage({ type: "crewcode:request", id, method, params }, targetOrigin);
29
+ return new Promise((resolve, reject) => {
30
+ pending.set(id, { resolve, reject });
31
+ window.setTimeout(() => {
32
+ if (!pending.has(id)) return;
33
+ pending.delete(id);
34
+ reject(new Error("CrewCode plugin request timed out"));
35
+ }, timeoutMs);
36
+ });
37
+ };
38
+ window.addEventListener("message", (event) => {
39
+ if (event.source !== window.parent) return;
40
+ const msg = event.data;
41
+ if (!msg || typeof msg !== "object") return;
42
+ if (msg.type === "crewcode:context") {
43
+ latestContext = msg;
44
+ for (const listener of contextListeners) listener(latestContext);
45
+ return;
46
+ }
47
+ if (msg.type === "crewcode:response" && typeof msg.id === "string" && pending.has(msg.id)) {
48
+ const callbacks = pending.get(msg.id);
49
+ pending.delete(msg.id);
50
+ if (msg.ok) callbacks.resolve(msg.result);
51
+ else callbacks.reject(new Error(typeof msg.error === "string" ? msg.error : "plugin request failed"));
52
+ }
53
+ });
54
+ return {
55
+ apiVersion: CREWCODE_PLUGIN_API_VERSION,
56
+ request,
57
+ onContext(listener) {
58
+ contextListeners.add(listener);
59
+ if (latestContext) listener(latestContext);
60
+ return () => contextListeners.delete(listener);
61
+ },
62
+ getContext: () => latestContext,
63
+ workspace: {
64
+ listFiles: () => request("workspace:listFiles"),
65
+ readFile: (sub) => request("workspace:readFile", { sub }),
66
+ writeFile: (sub, text) => request("workspace:writeFile", { sub, text })
67
+ },
68
+ network: {
69
+ fetch: () => Promise.reject(new Error(RESERVED_NETWORK_MESSAGE))
70
+ },
71
+ secrets: {
72
+ get: () => Promise.reject(new Error(RESERVED_SECRETS_MESSAGE))
73
+ }
74
+ };
75
+ }
76
+
77
+ // src/browser-global.ts
78
+ window.createCrewCodeApi = createCrewCodeApi;
79
+ window.crewcode = createCrewCodeApi();
80
+ })();
@@ -0,0 +1,57 @@
1
+ {
2
+ "$schema": "../../../schemas/crewcode.plugin.schema.json",
3
+ "id": "codebase-graph-lite",
4
+ "name": "Codebase Graph Lite",
5
+ "version": "0.1.0",
6
+ "description": "Dogfood plugin: isolated panel that reads the workspace file list through the v0 permission gate.",
7
+ "author": "CrewCode",
8
+ "crewcode": {
9
+ "apiVersion": "0.1"
10
+ },
11
+ "permissions": ["workspace:read"],
12
+ "contributes": {
13
+ "tabs": [
14
+ {
15
+ "id": "main",
16
+ "title": "Codebase Graph Lite",
17
+ "icon": "grid",
18
+ "entry": "panel.html",
19
+ "singleton": true
20
+ }
21
+ ],
22
+ "sidebarPanels": [
23
+ {
24
+ "id": "sidebar",
25
+ "title": "Graph Lite",
26
+ "icon": "sidebar",
27
+ "entry": "panel.html"
28
+ }
29
+ ],
30
+ "statusItems": [
31
+ {
32
+ "id": "graph-ready",
33
+ "title": "Codebase Graph Lite",
34
+ "text": "graph lite",
35
+ "icon": "grid",
36
+ "sidebarPanel": "sidebar"
37
+ }
38
+ ],
39
+ "editorActions": [
40
+ {
41
+ "id": "show-in-graph",
42
+ "title": "Show in Graph Lite",
43
+ "icon": "grid",
44
+ "sidebarPanel": "sidebar"
45
+ }
46
+ ],
47
+ "chatActions": [
48
+ {
49
+ "id": "inspect-chat",
50
+ "title": "Inspect chat with Graph Lite",
51
+ "icon": "grid",
52
+ "sidebarPanel": "sidebar",
53
+ "messageRole": "any"
54
+ }
55
+ ]
56
+ }
57
+ }
@@ -0,0 +1,53 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Codebase Graph Lite</title>
7
+ <style>
8
+ :root { color-scheme: dark; font-family: Inter, system-ui, sans-serif; background: #0f120f; color: #fafafa; }
9
+ body { margin: 0; background: #0f120f; }
10
+ main { padding: 22px; display: grid; gap: 16px; }
11
+ header { display: flex; align-items: baseline; justify-content: space-between; border-bottom: 1px solid #1c2f2f; padding-bottom: 12px; }
12
+ h1 { margin: 0; font-size: 18px; letter-spacing: -0.01em; }
13
+ .mono, button, code { font-family: 'JetBrains Mono', ui-monospace, monospace; }
14
+ .muted { color: #8a948a; font-size: 12px; }
15
+ button { background: #142018; border: 1px solid #1c2f2f; color: #fafafa; border-radius: 8px; padding: 7px 10px; cursor: pointer; }
16
+ button:hover { background: #1e3a30; }
17
+ .grid { display: grid; grid-template-columns: 280px 1fr; gap: 16px; min-height: 0; }
18
+ .panel { border: 1px solid #1c2f2f; background: #111611; border-radius: 10px; min-height: 360px; overflow: hidden; }
19
+ .panel h2 { margin: 0; padding: 10px 12px; font-size: 12px; border-bottom: 1px solid #1c2f2f; color: #8a948a; text-transform: uppercase; letter-spacing: .12em; }
20
+ ul { list-style: none; padding: 6px; margin: 0; max-height: 520px; overflow: auto; }
21
+ li { padding: 6px 8px; border-radius: 6px; font-size: 12px; color: #d7ddd7; cursor: pointer; }
22
+ li:hover, li.on { background: #1e3a30; }
23
+ pre { margin: 0; padding: 14px; white-space: pre-wrap; color: #d7ddd7; font-size: 12px; max-height: 520px; overflow: auto; }
24
+ .pill { border: 1px solid #1c2f2f; border-radius: 999px; padding: 3px 8px; color: #8a948a; font-size: 11px; }
25
+ </style>
26
+ </head>
27
+ <body>
28
+ <main>
29
+ <header>
30
+ <div>
31
+ <h1>Codebase Graph Lite</h1>
32
+ <div id="workspace" class="muted mono">waiting for CrewCode context…</div>
33
+ </div>
34
+ <div style="display:flex; gap:8px; align-items:center">
35
+ <span id="count" class="pill mono">0 files</span>
36
+ <button id="refresh">refresh graph</button>
37
+ </div>
38
+ </header>
39
+ <div class="grid">
40
+ <section class="panel">
41
+ <h2>files</h2>
42
+ <ul id="files"></ul>
43
+ </section>
44
+ <section class="panel">
45
+ <h2>preview</h2>
46
+ <pre id="preview">Select a file to read it through the plugin permission gate.</pre>
47
+ </section>
48
+ </div>
49
+ </main>
50
+ <script src="crewcode-plugin-api.js"></script>
51
+ <script src="plugin.js"></script>
52
+ </body>
53
+ </html>
@@ -0,0 +1,49 @@
1
+ let context = null
2
+ let files = []
3
+
4
+ function showError(err) {
5
+ document.getElementById('preview').textContent = `Error: ${err.message}`
6
+ }
7
+
8
+ function renderFiles() {
9
+ const list = document.getElementById('files')
10
+ list.innerHTML = ''
11
+ document.getElementById('count').textContent = `${files.length} files`
12
+ for (const rel of files.slice(0, 400)) {
13
+ const li = document.createElement('li')
14
+ li.textContent = rel
15
+ li.className = 'mono'
16
+ li.onclick = async () => {
17
+ for (const item of list.querySelectorAll('li')) item.classList.remove('on')
18
+ li.classList.add('on')
19
+ try {
20
+ const result = await window.crewcode.workspace.readFile(rel)
21
+ document.getElementById('preview').textContent = result.text.slice(0, 12000)
22
+ } catch (err) {
23
+ showError(err)
24
+ }
25
+ }
26
+ list.appendChild(li)
27
+ }
28
+ }
29
+
30
+ async function loadFiles() {
31
+ if (!context?.workspace) return
32
+ document.getElementById('preview').textContent = 'Reading workspace file list through CrewCode…'
33
+ const result = await window.crewcode.workspace.listFiles()
34
+ files = result.files || []
35
+ renderFiles()
36
+ document.getElementById('preview').textContent = files.length
37
+ ? 'Select a file to preview it. This panel is isolated; file reads go through CrewCode permissions.'
38
+ : 'No files returned.'
39
+ }
40
+
41
+ window.crewcode.onContext(next => {
42
+ context = next
43
+ document.getElementById('workspace').textContent = next.workspace
44
+ ? `${next.workspace.name} · ${next.workspace.kind} · permissions: ${next.permissions.join(', ') || 'none'}`
45
+ : `no workspace · permissions: ${next.permissions.join(', ') || 'none'}`
46
+ loadFiles().catch(showError)
47
+ })
48
+
49
+ document.getElementById('refresh').onclick = () => loadFiles().catch(showError)
@@ -0,0 +1,80 @@
1
+ // Official CrewCode plugin browser helper. GENERATED from src/ — do not edit by hand.
2
+ // Runs inside sandboxed plugin iframes. It never exposes Electron APIs.
3
+ "use strict";
4
+ (() => {
5
+ // src/create-api.ts
6
+ var CREWCODE_PLUGIN_API_VERSION = "0.1";
7
+ var RESERVED_NETWORK_MESSAGE = "crewcode.network.fetch is reserved in plugin API v0. Use an agentProvider runtime (http/sse-http/openai-compatible/websocket) for network access.";
8
+ var RESERVED_SECRETS_MESSAGE = "crewcode.secrets.get is reserved in plugin API v0. Use a provider apiKeyEnv or local CLI auth instead.";
9
+ function createCrewCodeApi(options = {}) {
10
+ var _a, _b;
11
+ const timeoutMs = (_a = options.timeoutMs) != null ? _a : 1e4;
12
+ const targetOrigin = (_b = options.targetOrigin) != null ? _b : "*";
13
+ const pending = /* @__PURE__ */ new Map();
14
+ const contextListeners = /* @__PURE__ */ new Set();
15
+ let seq = 0;
16
+ let latestContext = null;
17
+ const reportError = (err) => {
18
+ const error = err instanceof Error ? err : new Error(String(err));
19
+ window.parent.postMessage({ type: "crewcode:runtimeError", message: error.message, stack: error.stack }, targetOrigin);
20
+ };
21
+ window.addEventListener("error", (event) => {
22
+ var _a2;
23
+ return reportError((_a2 = event.error) != null ? _a2 : event.message);
24
+ });
25
+ window.addEventListener("unhandledrejection", (event) => reportError(event.reason));
26
+ const request = (method, params) => {
27
+ const id = `req-${++seq}`;
28
+ window.parent.postMessage({ type: "crewcode:request", id, method, params }, targetOrigin);
29
+ return new Promise((resolve, reject) => {
30
+ pending.set(id, { resolve, reject });
31
+ window.setTimeout(() => {
32
+ if (!pending.has(id)) return;
33
+ pending.delete(id);
34
+ reject(new Error("CrewCode plugin request timed out"));
35
+ }, timeoutMs);
36
+ });
37
+ };
38
+ window.addEventListener("message", (event) => {
39
+ if (event.source !== window.parent) return;
40
+ const msg = event.data;
41
+ if (!msg || typeof msg !== "object") return;
42
+ if (msg.type === "crewcode:context") {
43
+ latestContext = msg;
44
+ for (const listener of contextListeners) listener(latestContext);
45
+ return;
46
+ }
47
+ if (msg.type === "crewcode:response" && typeof msg.id === "string" && pending.has(msg.id)) {
48
+ const callbacks = pending.get(msg.id);
49
+ pending.delete(msg.id);
50
+ if (msg.ok) callbacks.resolve(msg.result);
51
+ else callbacks.reject(new Error(typeof msg.error === "string" ? msg.error : "plugin request failed"));
52
+ }
53
+ });
54
+ return {
55
+ apiVersion: CREWCODE_PLUGIN_API_VERSION,
56
+ request,
57
+ onContext(listener) {
58
+ contextListeners.add(listener);
59
+ if (latestContext) listener(latestContext);
60
+ return () => contextListeners.delete(listener);
61
+ },
62
+ getContext: () => latestContext,
63
+ workspace: {
64
+ listFiles: () => request("workspace:listFiles"),
65
+ readFile: (sub) => request("workspace:readFile", { sub }),
66
+ writeFile: (sub, text) => request("workspace:writeFile", { sub, text })
67
+ },
68
+ network: {
69
+ fetch: () => Promise.reject(new Error(RESERVED_NETWORK_MESSAGE))
70
+ },
71
+ secrets: {
72
+ get: () => Promise.reject(new Error(RESERVED_SECRETS_MESSAGE))
73
+ }
74
+ };
75
+ }
76
+
77
+ // src/browser-global.ts
78
+ window.createCrewCodeApi = createCrewCodeApi;
79
+ window.crewcode = createCrewCodeApi();
80
+ })();
@@ -0,0 +1,24 @@
1
+ {
2
+ "$schema": "../../../schemas/crewcode.plugin.schema.json",
3
+ "id": "company-agent-http-adapter",
4
+ "name": "Company Agent HTTP Adapter",
5
+ "version": "0.1.0",
6
+ "description": "Template for companies to expose an internal coding agent over a CrewCode-brokered HTTP provider runtime.",
7
+ "crewcode": { "apiVersion": "0.1" },
8
+ "permissions": ["agent:provider", "network:fetch"],
9
+ "contributes": {
10
+ "tabs": [
11
+ { "id": "main", "title": "Company Agent HTTP", "icon": "bot", "entry": "panel.html", "singleton": true }
12
+ ],
13
+ "agentProviders": [
14
+ {
15
+ "id": "company-http",
16
+ "title": "Company HTTP Agent",
17
+ "runtime": "http",
18
+ "description": "POSTs prompts to a local/company-owned HTTP endpoint. Response may be plain text or JSON { text }.",
19
+ "endpoint": "http://localhost:8787/agent",
20
+ "models": ["company-default"]
21
+ }
22
+ ]
23
+ }
24
+ }
@@ -0,0 +1 @@
1
+ <!doctype html><html><head><meta charset="utf-8"><title>Company Agent HTTP</title><style>body{margin:0;background:#0f120f;color:#e5e7eb;font:13px Inter,system-ui;padding:16px}.mono,code{font-family:'JetBrains Mono',monospace;color:#8b9a91}.card{border:1px solid #1c2f2f;background:#121712;padding:12px;margin-top:12px}pre{white-space:pre-wrap}</style></head><body><div class="mono">dogfood template</div><h1>company agent http adapter</h1><p id="ctx">waiting for context…</p><div class="card">CrewCode POSTs to <code>http://localhost:8787/agent</code> with JSON:</div><pre class="card">{ "prompt": "...", "cwd": "...", "model": "company-default", "provider": "company-agent-http-adapter:company-http" }</pre><div class="card">Return plain text or JSON like <code>{ "text": "answer" }</code>.</div><script src="crewcode-plugin-api.js"></script><script src="plugin.js"></script></body></html>
@@ -0,0 +1 @@
1
+ window.crewcode.onContext(ctx=>{document.getElementById('ctx').textContent=ctx.workspace?`${ctx.workspace.name} · ${ctx.workspace.kind}`:'no workspace'})
@@ -0,0 +1,27 @@
1
+ import http from 'node:http'
2
+
3
+ const server = http.createServer(async (req, res) => {
4
+ if (req.method !== 'POST' || req.url !== '/agent') {
5
+ res.writeHead(404, { 'Content-Type': 'text/plain' })
6
+ res.end('not found')
7
+ return
8
+ }
9
+ let body = ''
10
+ for await (const chunk of req) body += chunk
11
+ const input = JSON.parse(body || '{}')
12
+ res.writeHead(200, { 'Content-Type': 'application/json' })
13
+ res.end(JSON.stringify({
14
+ text: [
15
+ 'Company HTTP Agent template response.',
16
+ '',
17
+ `cwd: ${input.cwd ?? 'unknown'}`,
18
+ `model: ${input.model ?? 'default'}`,
19
+ '',
20
+ `prompt length: ${String(input.prompt ?? '').length}`,
21
+ ].join('\n')
22
+ }))
23
+ })
24
+
25
+ server.listen(8787, () => {
26
+ console.log('company agent template listening on http://localhost:8787/agent')
27
+ })
@@ -0,0 +1,80 @@
1
+ // Official CrewCode plugin browser helper. GENERATED from src/ — do not edit by hand.
2
+ // Runs inside sandboxed plugin iframes. It never exposes Electron APIs.
3
+ "use strict";
4
+ (() => {
5
+ // src/create-api.ts
6
+ var CREWCODE_PLUGIN_API_VERSION = "0.1";
7
+ var RESERVED_NETWORK_MESSAGE = "crewcode.network.fetch is reserved in plugin API v0. Use an agentProvider runtime (http/sse-http/openai-compatible/websocket) for network access.";
8
+ var RESERVED_SECRETS_MESSAGE = "crewcode.secrets.get is reserved in plugin API v0. Use a provider apiKeyEnv or local CLI auth instead.";
9
+ function createCrewCodeApi(options = {}) {
10
+ var _a, _b;
11
+ const timeoutMs = (_a = options.timeoutMs) != null ? _a : 1e4;
12
+ const targetOrigin = (_b = options.targetOrigin) != null ? _b : "*";
13
+ const pending = /* @__PURE__ */ new Map();
14
+ const contextListeners = /* @__PURE__ */ new Set();
15
+ let seq = 0;
16
+ let latestContext = null;
17
+ const reportError = (err) => {
18
+ const error = err instanceof Error ? err : new Error(String(err));
19
+ window.parent.postMessage({ type: "crewcode:runtimeError", message: error.message, stack: error.stack }, targetOrigin);
20
+ };
21
+ window.addEventListener("error", (event) => {
22
+ var _a2;
23
+ return reportError((_a2 = event.error) != null ? _a2 : event.message);
24
+ });
25
+ window.addEventListener("unhandledrejection", (event) => reportError(event.reason));
26
+ const request = (method, params) => {
27
+ const id = `req-${++seq}`;
28
+ window.parent.postMessage({ type: "crewcode:request", id, method, params }, targetOrigin);
29
+ return new Promise((resolve, reject) => {
30
+ pending.set(id, { resolve, reject });
31
+ window.setTimeout(() => {
32
+ if (!pending.has(id)) return;
33
+ pending.delete(id);
34
+ reject(new Error("CrewCode plugin request timed out"));
35
+ }, timeoutMs);
36
+ });
37
+ };
38
+ window.addEventListener("message", (event) => {
39
+ if (event.source !== window.parent) return;
40
+ const msg = event.data;
41
+ if (!msg || typeof msg !== "object") return;
42
+ if (msg.type === "crewcode:context") {
43
+ latestContext = msg;
44
+ for (const listener of contextListeners) listener(latestContext);
45
+ return;
46
+ }
47
+ if (msg.type === "crewcode:response" && typeof msg.id === "string" && pending.has(msg.id)) {
48
+ const callbacks = pending.get(msg.id);
49
+ pending.delete(msg.id);
50
+ if (msg.ok) callbacks.resolve(msg.result);
51
+ else callbacks.reject(new Error(typeof msg.error === "string" ? msg.error : "plugin request failed"));
52
+ }
53
+ });
54
+ return {
55
+ apiVersion: CREWCODE_PLUGIN_API_VERSION,
56
+ request,
57
+ onContext(listener) {
58
+ contextListeners.add(listener);
59
+ if (latestContext) listener(latestContext);
60
+ return () => contextListeners.delete(listener);
61
+ },
62
+ getContext: () => latestContext,
63
+ workspace: {
64
+ listFiles: () => request("workspace:listFiles"),
65
+ readFile: (sub) => request("workspace:readFile", { sub }),
66
+ writeFile: (sub, text) => request("workspace:writeFile", { sub, text })
67
+ },
68
+ network: {
69
+ fetch: () => Promise.reject(new Error(RESERVED_NETWORK_MESSAGE))
70
+ },
71
+ secrets: {
72
+ get: () => Promise.reject(new Error(RESERVED_SECRETS_MESSAGE))
73
+ }
74
+ };
75
+ }
76
+
77
+ // src/browser-global.ts
78
+ window.createCrewCodeApi = createCrewCodeApi;
79
+ window.crewcode = createCrewCodeApi();
80
+ })();
@@ -0,0 +1,13 @@
1
+ {
2
+ "$schema": "../../../schemas/crewcode.plugin.schema.json",
3
+ "id": "git-risk-lens",
4
+ "name": "Git Risk Lens",
5
+ "version": "0.1.0",
6
+ "description": "Dogfoods a read-only git lens contribution that opens a risk review panel.",
7
+ "crewcode": { "apiVersion": "0.1" },
8
+ "permissions": ["workspace:read", "git:read"],
9
+ "contributes": {
10
+ "sidebarPanels": [{ "id": "risk", "title": "Risk Lens", "icon": "alert", "entry": "panel.html" }],
11
+ "gitLenses": [{ "id": "open-risk", "title": "Open Risk Lens", "icon": "alert", "sidebarPanel": "risk", "placement": "sidebar" }]
12
+ }
13
+ }
@@ -0,0 +1 @@
1
+ <!doctype html><html><head><meta charset="utf-8"><title>Git Risk Lens</title><style>body{margin:0;background:#0f120f;color:#e5e7eb;font:13px Inter,system-ui;padding:16px}code,.mono{font-family:'JetBrains Mono',monospace;color:#9fbfaf}.card{border:1px solid #1c2f2f;background:#121712;padding:12px;margin-top:12px}button{background:#285a48;color:#e6f0eb;border:1px solid #356b57;padding:7px 10px;font:11px 'JetBrains Mono',monospace}</style></head><body><div class="mono">dogfood plugin</div><h1>git risk lens</h1><p id="ctx">waiting for context…</p><div class="card">Read-only lens opened from the Git sidebar. Future versions can consume structured git status/diff summaries through <code>git:read</code>.</div><button id="scan">scan workspace files</button><pre id="out"></pre><script src="crewcode-plugin-api.js"></script><script src="plugin.js"></script></body></html>
@@ -0,0 +1,2 @@
1
+ window.crewcode.onContext(ctx=>{document.getElementById('ctx').textContent=ctx.workspace?`${ctx.workspace.name} · ${ctx.workspace.kind}`:'no workspace'})
2
+ document.getElementById('scan').onclick=async()=>{const {files}=await window.crewcode.workspace.listFiles();const risky=files.filter(f=>/(auth|secret|migration|schema|\.env|lock)/i.test(f)).slice(0,40);document.getElementById('out').textContent=risky.length?risky.join('\n'):'no obvious risk filenames found'}