Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.
| The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how. | 1 | /** |
| 2 | * What a workspace has connected, by connector id (@g1t/contracts/connectors): | |
| 3 | * its provider connections from the integrations service, the GitHub App's | |
| 4 | * installations and its own webhooks, each with how it is doing. The | |
| Customize replaces the Marketplace on the site and the phone: three tabs, Skills, Connectors and Plugins, each with Yours and Discover, a search and the owners' Add menu, all kept in the address. Skills' Yours is the library (drafts, each skill with an inline Available to control that attaches it to every agent, a team or one, g1t's foundational skills, and the repository it follows); its Discover lists every skill in every marketplace's plugins, grouped by marketplace, and Add installs the plugin that brings one. Connectors' Yours is the workspace's MCP servers with their state, tools, where they reach and what an owner does with them (sign in or out, a key, list tools again, remove), beside the integrations the workspace has connected; its Discover is the directory, MCP servers first and connected in a step (the browser signs in, a key is pasted, or neither), then g1t's integrations, each person's own, and what is coming; a connector has a page, a connect page by directory entry or address, and the sign-in's return lands on it. Plugins' Yours is what the workspace installed with what each brought, its switch, Update when the marketplace moved on, and Uninstall; its Discover is every plugin, narrowed by category and marketplace and sorted by marketplace or name, with g1t's announced ones muted as Soon; a plugin's page renders its README and lists its skills (given to agents from there), its subagents (Hire opens the new-agent form filled from one), its servers and what only Claude Code uses. Marketplaces have a page; requests moved under Customize and name plugins, skills and connectors. Apps lists installed plugins and connectors beside integrations, ⌘K, the Apps page, the phone's More and the breadcrumbs say Customize, and the Marketplace's and the skill library's old addresses redirect. An agent's Abilities tab shows the connectors that reach it as Connectors, with per-tool levels, and keeps Add an MCP server under Only this agent; Templates lists the agents installed plugins bring; an agent's Skills tab says which plugin a skill came from. The phone's deep links open Customize's tabs. | 5 | * Integrations directory and Customize both read it. |
| The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how. | 6 | */ |
| 7 | import type { User } from "@g1t/contracts"; | |
| 8 | import { PROVIDERS } from "@g1t/contracts"; | |
| 9 | import { CONNECTORS } from "@g1t/contracts/connectors"; | |
| 10 | ||
| 11 | import type { ConnectedState } from "./connectors"; | |
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 12 | import { githubConnected } from "./github"; |
| The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how. | 13 | import { githubApp } from "./github.server"; |
| 14 | import { integrationsSection } from "./integration-sections"; | |
| 15 | import { integrations, webhooks } from "./services.server"; | |
| 16 | ||
| 17 | /** What the workspace `slug` has connected, as `viewer` may see it. Each source that does not answer counts as nothing connected. */ | |
| 18 | export async function connectedStates(slug: string, viewer: User): Promise<Record<string, ConnectedState>> { | |
| Every Marketplace listing says who builds it and whether you can add it: a tier (Official, Verified, Community, Internal) with what it means, and an availability (Available, Connected, Soon, or Not available here with why) that never looks like a button that doesn't work; Extensions and Integrations are grouped and filtered by both, each integration has a page with what it lets agents do today and what's Soon, and the marketplace guide says how. | 19 | return (await workspaceConnections(slug, viewer)).connected; |
| 20 | } | |
| 21 | ||
| 22 | /** | |
| 23 | * What the workspace `slug` has connected, and the connectors this g1t | |
| 24 | * can't connect at all, by id, each with why: GitHub when no GitHub App is | |
| 25 | * set up (as on a self-hosted g1t that hasn't added one). | |
| 26 | */ | |
| 27 | export async function workspaceConnections(slug: string, viewer: User): Promise<{ connected: Record<string, ConnectedState>; unavailable: Record<string, string> }> { | |
| The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how. | 28 | const [connections, github, hooks] = await Promise.all([ |
| 29 | integrations.list(slug, viewer).catch(() => null), | |
| 30 | githubApp.status(viewer, slug).catch(() => null), | |
| 31 | webhooks.list(viewer, { workspace: slug }).catch(() => null), | |
| 32 | ]); | |
| 33 | ||
| 34 | const connected: Record<string, ConnectedState> = {}; | |
| 35 | if (connections?.ok) { | |
| 36 | for (const connector of CONNECTORS) { | |
| 37 | if (!connector.provider) continue; | |
| 38 | const mine = connections.value.filter((connection) => connection.provider === connector.provider); | |
| 39 | if (mine.length === 0) continue; | |
| 40 | const broken = mine.find((connection) => connection.lastError); | |
| 41 | connected[connector.id] = { | |
| 42 | detail: mine.length === 1 ? mine[0]!.name : `${mine.length} connections: ${mine.map((c) => c.name).join(", ")}`, | |
| 43 | problem: broken ? `${broken.name}: ${broken.lastError}` : null, | |
| 44 | manage: `/${slug}/-/integrations/${integrationsSection(PROVIDERS[connector.provider].kind)}`, | |
| 45 | }; | |
| 46 | } | |
| 47 | } | |
| A GitHub App installed straight on GitHub can be added to a workspace: Import from GitHub lists the installations your GitHub account can see that this workspace hasn't added, each with Add for owners, and coming back from GitHub without g1t's own start asks which of your workspaces to add it to instead of stopping; the GitHub guide says how. | 48 | const fromGithub = github?.ok ? githubConnected(github.value.installations) : null; |
| 49 | if (fromGithub) connected.github = fromGithub; | |
| The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how. | 50 | const ours = hooks?.ok ? hooks.value.filter((hook) => hook.scope === "workspace") : []; |
| 51 | if (ours.length > 0) { | |
| 52 | const failing = ours.filter((hook) => hook.lastStatus === "failed"); | |
| 53 | connected.webhooks = { | |
| 54 | detail: ours.length === 1 ? ours[0]!.url : `${ours.length} webhooks`, | |
| 55 | problem: failing.length > 0 ? `The last delivery to ${failing[0]!.url} failed.` : null, | |
| 56 | manage: null, | |
| 57 | }; | |
| 58 | } | |
| Every Marketplace listing says who builds it and whether you can add it: a tier (Official, Verified, Community, Internal) with what it means, and an availability (Available, Connected, Soon, or Not available here with why) that never looks like a button that doesn't work; Extensions and Integrations are grouped and filtered by both, each integration has a page with what it lets agents do today and what's Soon, and the marketplace guide says how. | 59 | const unavailable: Record<string, string> = {}; |
| 60 | if (github?.ok && !github.value.configured) unavailable.github = "This g1t has no GitHub App set up. Whoever runs it adds one first."; | |
| 61 | return { connected, unavailable }; | |
| The Marketplace is where a workspace finds what to add, reached from Apps: the agent catalog of roles with who already does each job and Add to workspace; every integration with whether it's connected; g1t's own extensions, listed as Soon; and requests, where members ask and owners add or turn down, each told by a notification. Underneath, an extension is a manifest (publisher and tier, source and version from a tag, scopes, the domains its data goes to, its page on g1tusercontent.com, no price) and an install pins its version with an off switch, a budget and the audit log. Apps lists only what was added from the Marketplace, with pins; g1t's own pages stay in their sidebars, and AI Gateway joins Workspace's. The marketplace guide says how. | 62 | } |