Skip to content
817 linesCodeBlameRaw

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.

Agents → Skills is the workspace's skill library in the open SKILL.md format: write a skill in g1t, import a SKILL.md or zip, link a repository whose .g1t/skills folders publish on every push, or save a finished session as a skill once a person reviews it; attach a skill to an agent, a team or the whole workspace, each attachment pinned to a version. Agents see each skill's name and when to use it, and read the rest with use_skill when a request needs it; a skill never adds a permission, and scripts wait for an agent's own computer. The agent skills guide says how.1import { Activity, BookMarked, Brain, ChevronRight, Dices, LayoutTemplate, Network, Plus, Route as RouteIcon, Sparkles } from "lucide-react";
Chat and workspace agents: channels, DMs and named agents you talk to2import { type ReactNode, useState } from "react";
3import { Form, NavLink, useLocation, useNavigation, useRouteLoaderData } from "react-router";
4
Agents have faces, and are never mistaken for people. Every agent wears a little bot face drawn from a look it owns, shape, colour, eyes, mouth, antenna, accessory and pattern, chosen in its builder and on its Profile tab with a live preview, Shuffle and a way back to the face its seed gives it; the face blinks on its own time, breathes, narrows its eyes while the agent works, shuts them asleep and bounces when it finishes, all of it still for anyone who asked for less motion. Wherever an agent shows, in chat, in a list, on a mention, on a review or a commit, its avatar carries an agent marker, and the people reading it are told so. In Chat, direct messages are two lists: People, and Agents, which also holds the agents you haven't talked to yet; a conversation with both a person and an agent in it is marked in the list, named in the conversation's header, spelled out by the composer and explained once the first time it opens. Agents keep their look in the agents service, which every service passes along. The chat and agents guides say so, and CONTRIBUTING makes the shared avatar the only way to draw an agent.5import type { AgentEffortCosts, AgentLook, AgentTemplate, ModelTier, WorkspaceAgent } from "@g1t/contracts";
Chat and workspace agents: channels, DMs and named agents you talk to6
Agents have faces, and are never mistaken for people. Every agent wears a little bot face drawn from a look it owns, shape, colour, eyes, mouth, antenna, accessory and pattern, chosen in its builder and on its Profile tab with a live preview, Shuffle and a way back to the face its seed gives it; the face blinks on its own time, breathes, narrows its eyes while the agent works, shuts them asleep and bounces when it finishes, all of it still for anyone who asked for less motion. Wherever an agent shows, in chat, in a list, on a mention, on a review or a commit, its avatar carries an agent marker, and the people reading it are told so. In Chat, direct messages are two lists: People, and Agents, which also holds the agents you haven't talked to yet; a conversation with both a person and an agent in it is marked in the list, named in the conversation's header, spelled out by the composer and explained once the first time it opens. Agents keep their look in the agents service, which every service passes along. The chat and agents guides say so, and CONTRIBUTING makes the shared avatar the only way to draw an agent.7import { type AgentLike, AgentAvatar } from "./agent-avatar";
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)8import { StatusDot, statusLabel } from "./chat/marks";
9import { isOrchestrator } from "./orchestrator";
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.10import { Button } from "./ui/button";
11import { Card } from "./ui/card";
Chat and workspace agents: channels, DMs and named agents you talk to12import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select";
13import { Skeleton } from "./ui/skeleton";
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)14import { AUTONOMY, type AgentDraft, PRESETS, TIER_LABELS, cleanHandle, dollarsField } from "../lib/agent-form";
The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work.15import { Checkbox } from "./ui/checkbox";
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)16import { Hint } from "./ui/hint";
The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work.17import { Input } from "./ui/input";
Pricing says it plainly: models at the provider's price, the agent rate for what g1t runs around every model call (the gateway, secrets, routing, context and pass-through to your own provider, so your own keys too), everything else at cost plus 20%, your own runners free, no seats; Security and quality comes with the plan with no separate fee, and live activations end. Each agent has an effort setting, Auto to Max, with what a typical task has cost at each level, and Spend's Spend less, keep quality suggests a lower level only when the agent's own past work shows quality held, to apply or dismiss. The pricing, spend and agents guides say how.18import { EffortPicker } from "./effort";
19import { effortSetting } from "../lib/effort";
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.20import { RoleFields, SubagentsField } from "./agent-role";
Agents have faces, and are never mistaken for people. Every agent wears a little bot face drawn from a look it owns, shape, colour, eyes, mouth, antenna, accessory and pattern, chosen in its builder and on its Profile tab with a live preview, Shuffle and a way back to the face its seed gives it; the face blinks on its own time, breathes, narrows its eyes while the agent works, shuts them asleep and bounces when it finishes, all of it still for anyone who asked for less motion. Wherever an agent shows, in chat, in a list, on a mention, on a review or a commit, its avatar carries an agent marker, and the people reading it are told so. In Chat, direct messages are two lists: People, and Agents, which also holds the agents you haven't talked to yet; a conversation with both a person and an agent in it is marked in the list, named in the conversation's header, spelled out by the composer and explained once the first time it opens. Agents keep their look in the agents service, which every service passes along. The chat and agents guides say so, and CONTRIBUTING makes the shared avatar the only way to draw an agent.21import { FaceEditor } from "./agents/face-editor";
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.22import { type AgentTeamRef, groupByTeam } from "../lib/people";
Chat and workspace agents: channels, DMs and named agents you talk to23import type { AgentsLayoutData } from "../routes/workspace/agents/layout";
24
25/** The workspace's agents while an Agents page is open; undefined elsewhere. */
26export function useAgentsData(): AgentsLayoutData | undefined {
27 return useRouteLoaderData("routes/workspace/agents/layout") as AgentsLayoutData | undefined;
28}
29
Agents have faces, and are never mistaken for people. Every agent wears a little bot face drawn from a look it owns, shape, colour, eyes, mouth, antenna, accessory and pattern, chosen in its builder and on its Profile tab with a live preview, Shuffle and a way back to the face its seed gives it; the face blinks on its own time, breathes, narrows its eyes while the agent works, shuts them asleep and bounces when it finishes, all of it still for anyone who asked for less motion. Wherever an agent shows, in chat, in a list, on a mention, on a review or a commit, its avatar carries an agent marker, and the people reading it are told so. In Chat, direct messages are two lists: People, and Agents, which also holds the agents you haven't talked to yet; a conversation with both a person and an agent in it is marked in the list, named in the conversation's header, spelled out by the composer and explained once the first time it opens. Agents keep their look in the agents service, which every service passes along. The chat and agents guides say so, and CONTRIBUTING makes the shared avatar the only way to draw an agent.30/** An agent's face: its picture, g1t's mark, or its bot face, with the agent marker (components/agent-avatar.tsx). */
31export function AgentFace({ agent, size = 20, ring }: { agent: AgentLike; size?: number; ring?: string }) {
32 return <AgentAvatar agent={agent} size={size} ring={ring} />;
Chat and workspace agents: channels, DMs and named agents you talk to33}
34
35function SideLink({ to, end, icon, children, trailing }: { to: string; end?: boolean; icon: ReactNode; children: ReactNode; trailing?: ReactNode }) {
36 return (
37 <NavLink
38 to={to}
39 end={end}
40 prefetch="intent"
41 className={({ isActive }) =>
42 `group flex h-9 items-center gap-2.5 rounded-md px-2 text-[0.8125rem] transition-colors ${
The left-hand navigation takes less room and reads at a glance. The dock becomes a rail: a 56-pixel column of icons with the g1t mark on top, the current app marked by a filled square, hover hints naming each with its shortcut, the apps you pinned in a scrolling band, and Apps, People, Workspace and your account at the foot. Each mode's sidebar sits flush against it, 240 pixels wide, opening on Search or jump to and listing its groups under small labels in 36-pixel rows; Ctrl B hides it and the page grows into the room. Every mode's list is built on the shadcn Sidebar now in the kit, so Workspace, Code, People, Notifications, account settings, Chat, Artifacts and Agents all share one frame; the phone keeps its bottom bar and drawer. The workspaces guide describes the rail, the sidebar and the page.43 isActive ? "bg-sidebar-accent font-medium text-fg" : "text-muted hover:bg-sidebar-accent/60 hover:text-fg"
Chat and workspace agents: channels, DMs and named agents you talk to44 }`
45 }
46 >
47 <span className="flex w-5 shrink-0 justify-center">{icon}</span>
48 <span className="min-w-0 grow truncate">{children}</span>
49 {trailing}
50 </NavLink>
51 );
52}
53
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)54/** An agent as the sidebar lists it: from the Agents pages' own data, or the shell's on any other page. */
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.55type Listed = Pick<WorkspaceAgent, "id" | "handle" | "display_name" | "avatar" | "role" | "status" | "title"> & {
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)56 builtin?: boolean;
57 avatar_seed?: string | null;
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.58 scope?: WorkspaceAgent["scope"];
59 personal_owner_id?: string | null;
60 personal_owner?: string | null;
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.61 /** The shell's list carries each agent's teams; the Agents pages' data has them apart. */
62 teams?: AgentTeamRef[];
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)63};
64
65/** "Margo · QA Engineer": how an agent reads wherever it shows. */
66export function nameAndTitle(agent: Pick<WorkspaceAgent, "display_name" | "title">): string {
67 return agent.title ? `${agent.display_name} · ${agent.title}` : agent.display_name;
68}
69
Chat and workspace agents: channels, DMs and named agents you talk to70/**
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)71 * Agents mode's sidebar: the fleet's runs, context and memory; g1t, the
72 * orchestrator, pinned at the top; then the specialists, each with its
73 * role and status; and the way to make a new one.
Chat and workspace agents: channels, DMs and named agents you talk to74 */
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)75export function AgentsSidebar({
76 slug,
77 shellAgents,
78 code,
79 owner,
80 phone = false,
81}: {
82 slug: string;
83 /** A phone's Agents tab: the list as the page, with no heading of its own and no fleet row (the fleet is under it). */
84 phone?: boolean;
85 /** The shell's list, for pages outside `-/agents` (context, memory). */
86 shellAgents: Listed[] | null;
87 /** Context and memory are about the code: only with Code access. */
88 code: boolean;
89 owner: boolean;
90}) {
Chat and workspace agents: channels, DMs and named agents you talk to91 const data = useAgentsData();
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)92 const agents: Listed[] | null = data?.agents ?? shellAgents;
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.93 // The teams each agent is on, from team memberships; null when they couldn't be read.
94 const teamsOf: Record<string, AgentTeamRef[]> | null = data
95 ? data.teams
96 : shellAgents?.every((agent) => agent.teams)
97 ? Object.fromEntries(shellAgents.map((agent) => [agent.id, agent.teams ?? []]))
98 : null;
Agents mode: an overview of every agent's work and spend, and each agent's sessions, memory, routines, spend, activity and versions99 const live = data?.live ?? {};
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)100 const orchestrator = agents?.find((agent) => isOrchestrator(agent)) ?? null;
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.101 const specialists = (agents ?? []).filter((agent) => !isOrchestrator(agent) && agent.scope !== "personal");
102 // Personal agents: the viewer's own under Yours; members' (an owner sees them) apart.
103 // The shell's list holds only the viewer's own.
104 const personal = (agents ?? []).filter((agent) => agent.scope === "personal").sort((a, b) => a.display_name.localeCompare(b.display_name));
105 const yours = personal.filter((agent) => !data || agent.personal_owner_id === data.viewer_id);
106 const members = personal.filter((agent) => !yours.includes(agent));
107 // Owners always create agents; members personal ones, unless owners turned that off.
108 const canCreate = data?.may_create ?? owner;
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)109 const row = (agent: Listed) => (
Chat and workspace agents: channels, DMs and named agents you talk to110 <li key={agent.id}>
111 <NavLink
112 to={`/${slug}/-/agents/${agent.handle}`}
113 prefetch="intent"
114 className={({ isActive }) =>
The left-hand navigation takes less room and reads at a glance. The dock becomes a rail: a 56-pixel column of icons with the g1t mark on top, the current app marked by a filled square, hover hints naming each with its shortcut, the apps you pinned in a scrolling band, and Apps, People, Workspace and your account at the foot. Each mode's sidebar sits flush against it, 240 pixels wide, opening on Search or jump to and listing its groups under small labels in 36-pixel rows; Ctrl B hides it and the page grows into the room. Every mode's list is built on the shadcn Sidebar now in the kit, so Workspace, Code, People, Notifications, account settings, Chat, Artifacts and Agents all share one frame; the phone keeps its bottom bar and drawer. The workspaces guide describes the rail, the sidebar and the page.115 `group flex h-11 items-center gap-2.5 rounded-md px-2 transition-colors ${isActive ? "bg-sidebar-accent" : "hover:bg-sidebar-accent/60"}`
Chat and workspace agents: channels, DMs and named agents you talk to116 }
117 >
118 <span className="relative shrink-0">
Agents have faces, and are never mistaken for people. Every agent wears a little bot face drawn from a look it owns, shape, colour, eyes, mouth, antenna, accessory and pattern, chosen in its builder and on its Profile tab with a live preview, Shuffle and a way back to the face its seed gives it; the face blinks on its own time, breathes, narrows its eyes while the agent works, shuts them asleep and bounces when it finishes, all of it still for anyone who asked for less motion. Wherever an agent shows, in chat, in a list, on a mention, on a review or a commit, its avatar carries an agent marker, and the people reading it are told so. In Chat, direct messages are two lists: People, and Agents, which also holds the agents you haven't talked to yet; a conversation with both a person and an agent in it is marked in the list, named in the conversation's header, spelled out by the composer and explained once the first time it opens. Agents keep their look in the agents service, which every service passes along. The chat and agents guides say so, and CONTRIBUTING makes the shared avatar the only way to draw an agent.119 <AgentFace agent={{ ...agent, builtin: isOrchestrator(agent) }} size={26} ring="var(--color-sidebar)" />
120 {!isOrchestrator(agent) && agent.status !== "idle" && (
121 <StatusDot status={agent.status} className="absolute -top-0.5 -right-0.5 ring-2 ring-sidebar" />
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)122 )}
Chat and workspace agents: channels, DMs and named agents you talk to123 </span>
124 <span className="min-w-0 grow leading-tight">
125 <span className="block truncate text-[0.8125rem] font-medium text-fg">{agent.display_name}</span>
126 <span className="block truncate text-[0.6875rem] text-faint">
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.127 {isOrchestrator(agent)
128 ? "Orchestrator"
129 : agent.scope === "personal" && agent.personal_owner && agent.personal_owner_id !== data?.viewer_id
130 ? `@${agent.personal_owner}'s · ${agent.title || agent.role}`
131 : agent.status === "idle"
132 ? agent.title || agent.role
133 : `${statusLabel(agent.status)} · ${agent.title || agent.role}`}
Chat and workspace agents: channels, DMs and named agents you talk to134 </span>
135 </span>
Agents mode: an overview of every agent's work and spend, and each agent's sessions, memory, routines, spend, activity and versions136 {(live[agent.id] ?? 0) > 0 && (
137 <Hint label={`${live[agent.id]} live ${live[agent.id] === 1 ? "session" : "sessions"}`}>
138 <span className="flex h-5 min-w-5 shrink-0 items-center justify-center gap-1 rounded-full bg-accent/15 px-1.5 text-[0.6875rem] font-medium text-accent tabular-nums">
139 <span className="size-1.5 animate-pulse rounded-full bg-accent motion-reduce:animate-none" aria-hidden="true" />
140 {live[agent.id]}
141 <span className="sr-only"> live sessions</span>
142 </span>
143 </Hint>
144 )}
Chat and workspace agents: channels, DMs and named agents you talk to145 </NavLink>
146 </li>
147 );
148 return (
149 <div className="flex h-full flex-col">
g1t is described as the product it is in alpha, and its shell takes the new shape: the README, the docs home and docs/PLAN.md label every feature Live, Preview or Coming; a floating dock with the g1t mark, Today, Chat, Notifications, Agents, Code, Artifacts, your pinned apps and the Apps launcher, with People, Workspace and the account menu (now holding help) at its foot; the workspace's logo and switcher heading a flat sidebar that folds away with Ctrl B, or leading the header's breadcrumbs where there is none; the page in a rounded panel with a full-width header; Today as the front page, with first-time acceptance of agents' pull requests, what needs you and what's at stake, spend today and one item to start with, every number from a service; Notifications in place of the Inbox at /notifications; a bottom bar and More sheet on phones; and sign-in, sign-up, two-factor, reset, invites and choosing a workspace on standalone pages with no app around them.150 <div className={`flex h-9 shrink-0 items-center justify-between pr-1 pl-3 ${phone ? "hidden" : ""}`}>
The left-hand navigation takes less room and reads at a glance. The dock becomes a rail: a 56-pixel column of icons with the g1t mark on top, the current app marked by a filled square, hover hints naming each with its shortcut, the apps you pinned in a scrolling band, and Apps, People, Workspace and your account at the foot. Each mode's sidebar sits flush against it, 240 pixels wide, opening on Search or jump to and listing its groups under small labels in 36-pixel rows; Ctrl B hides it and the page grows into the room. Every mode's list is built on the shadcn Sidebar now in the kit, so Workspace, Code, People, Notifications, account settings, Chat, Artifacts and Agents all share one frame; the phone keeps its bottom bar and drawer. The workspaces guide describes the rail, the sidebar and the page.151 <h2 className="text-[0.6875rem] font-medium tracking-wide text-faint uppercase">Agents</h2>
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.152 {canCreate && (
153 <NavLink
154 to={`/${slug}/-/agents/new`}
155 aria-label="New agent"
156 className="flex size-8 items-center justify-center rounded-md text-faint transition-colors hover:bg-raised hover:text-fg"
157 >
158 <Plus size={16} />
159 </NavLink>
160 )}
Chat and workspace agents: channels, DMs and named agents you talk to161 </div>
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)162 <nav aria-label="Agents" className={`min-h-0 grow overflow-y-auto px-2.5 pt-3 pb-4 [scrollbar-width:thin] ${phone ? "[&_a]:min-h-11" : ""}`}>
Chat and workspace agents: channels, DMs and named agents you talk to163 <div className="space-y-px">
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)164 {!phone && (
165 <SideLink to={`/${slug}/-/agents`} end icon={<Activity size={15} className="text-faint" />}>
Agents mode: an overview of every agent's work and spend, and each agent's sessions, memory, routines, spend, activity and versions166 Overview
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)167 </SideLink>
168 )}
The Marketplace adds what g1t doesn't do and connects what you already use: extensions (Mail, Support, CRM, Recruiting, On-call, and bridges to a helpdesk, CRM or ERP you run, all Soon), starter kits, and integrations connected by the workspace or by each person; agents aren't installed there. Agent templates live in Agents, as starting points you configure, at Agents → Templates, and the Marketplace's old agent addresses lead there. The marketplace and agents guides say how.169 <SideLink to={`/${slug}/-/agents/templates`} icon={<LayoutTemplate size={15} className="text-faint" />}>
170 Templates
171 </SideLink>
Agents → Skills is the workspace's skill library in the open SKILL.md format: write a skill in g1t, import a SKILL.md or zip, link a repository whose .g1t/skills folders publish on every push, or save a finished session as a skill once a person reviews it; attach a skill to an agent, a team or the whole workspace, each attachment pinned to a version. Agents see each skill's name and when to use it, and read the rest with use_skill when a request needs it; a skill never adds a permission, and scripts wait for an agent's own computer. The agent skills guide says how.172 <SideLink to={`/${slug}/-/agents/skills`} icon={<BookMarked size={15} className="text-faint" />}>
173 Skills
174 </SideLink>
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)175 {code && (
176 <>
177 <SideLink to={`/${slug}/-/context`} icon={<Network size={15} className="text-faint" />}>
178 Context
179 </SideLink>
180 <SideLink to={`/${slug}/-/memory`} icon={<Brain size={15} className="text-faint" />}>
181 Memory
182 </SideLink>
183 </>
184 )}
Chat and workspace agents: channels, DMs and named agents you talk to185 </div>
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)186 {agents == null ? (
187 data === undefined && shellAgents === null ? (
188 <p className="mt-4 px-2 text-xs leading-relaxed text-faint">The agents service didn&apos;t answer. Your agents will show here once it does.</p>
189 ) : (
190 <div className="mt-5 space-y-3 px-2" aria-busy="true">
191 {[0, 1, 2].map((i) => (
192 <div key={i} className="flex items-center gap-2.5">
193 <Skeleton className="size-6 rounded-md" />
194 <Skeleton className="h-3 w-28" />
195 </div>
196 ))}
197 </div>
198 )
Chat and workspace agents: channels, DMs and named agents you talk to199 ) : (
200 <>
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)201 {orchestrator && <Group title="Orchestrator">{row(orchestrator)}</Group>}
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.202 {yours.length > 0 && <Group title="Yours">{yours.map(row)}</Group>}
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.203 <p className="mt-4 px-2 text-[0.6875rem] leading-snug text-faint">Specialists are colleagues hired into a role, on teams like anyone. g1t hands them work.</p>
204 {teamsOf ? (
205 groupByTeam(specialists, teamsOf).map((group) => (
206 <Group key={group.key || "none"} title={`${group.label} · ${group.agents.length}`} collapsible>
207 {group.agents.map(row)}
208 </Group>
209 ))
210 ) : specialists.length > 0 ? (
211 <Group title={`Specialists · ${specialists.length}`}>{[...specialists].sort((a, b) => a.display_name.localeCompare(b.display_name)).map(row)}</Group>
212 ) : null}
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)213 {specialists.length === 0 && <p className="px-2 py-1 text-xs text-faint">No specialists yet. Hire one into a role.</p>}
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.214 {members.length > 0 && (
215 <Group title={`Members' personal · ${members.length}`} collapsible initiallyOpen={false}>
216 {members.map(row)}
217 </Group>
218 )}
Chat and workspace agents: channels, DMs and named agents you talk to219 </>
220 )}
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.221 {canCreate && (
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)222 <NavLink
223 to={`/${slug}/-/agents/new`}
224 className={({ isActive }) =>
225 `mt-2 flex h-9 items-center gap-2.5 rounded-md border border-dashed px-2 text-[0.8125rem] transition-colors ${
226 isActive ? "border-accent/50 bg-accent/10 text-fg" : "border-line text-muted hover:border-line-strong hover:text-fg"
227 }`
228 }
229 >
230 <span className="flex w-5 justify-center">
231 <Plus size={15} />
232 </span>
233 New agent
234 </NavLink>
235 )}
Chat and workspace agents: channels, DMs and named agents you talk to236 </nav>
237 </div>
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)238 );
239}
240
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.241function Group({ title, children, collapsible, initiallyOpen = true }: { title: string; children: ReactNode; collapsible?: boolean; initiallyOpen?: boolean }) {
242 const [open, setOpen] = useState(initiallyOpen);
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)243 if (collapsible) {
244 return (
245 <section className="mt-3">
246 <button
247 type="button"
248 onClick={() => setOpen(!open)}
249 aria-expanded={open}
The left-hand navigation takes less room and reads at a glance. The dock becomes a rail: a 56-pixel column of icons with the g1t mark on top, the current app marked by a filled square, hover hints naming each with its shortcut, the apps you pinned in a scrolling band, and Apps, People, Workspace and your account at the foot. Each mode's sidebar sits flush against it, 240 pixels wide, opening on Search or jump to and listing its groups under small labels in 36-pixel rows; Ctrl B hides it and the page grows into the room. Every mode's list is built on the shadcn Sidebar now in the kit, so Workspace, Code, People, Notifications, account settings, Chat, Artifacts and Agents all share one frame; the phone keeps its bottom bar and drawer. The workspaces guide describes the rail, the sidebar and the page.250 className="mb-1 flex w-full items-center gap-1 rounded px-1 text-[0.6875rem] font-medium tracking-wide text-faint uppercase transition-colors hover:text-muted"
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)251 >
252 <ChevronRight size={12} className={`transition-transform ${open ? "rotate-90" : ""}`} />
253 {title}
254 </button>
255 {open && <ul className="space-y-px border-l border-line pl-1.5 ml-2.5">{children}</ul>}
256 </section>
257 );
258 }
Chat and workspace agents: channels, DMs and named agents you talk to259 return (
260 <section className="mt-4">
The left-hand navigation takes less room and reads at a glance. The dock becomes a rail: a 56-pixel column of icons with the g1t mark on top, the current app marked by a filled square, hover hints naming each with its shortcut, the apps you pinned in a scrolling band, and Apps, People, Workspace and your account at the foot. Each mode's sidebar sits flush against it, 240 pixels wide, opening on Search or jump to and listing its groups under small labels in 36-pixel rows; Ctrl B hides it and the page grows into the room. Every mode's list is built on the shadcn Sidebar now in the kit, so Workspace, Code, People, Notifications, account settings, Chat, Artifacts and Agents all share one frame; the phone keeps its bottom bar and drawer. The workspaces guide describes the rail, the sidebar and the page.261 <h3 className="mb-1 px-2 text-[0.6875rem] font-medium tracking-wide text-faint uppercase">{title}</h3>
Chat and workspace agents: channels, DMs and named agents you talk to262 <ul className="space-y-px">{children}</ul>
263 </section>
264 );
265}
266
267/** The templates g1t ships, and a blank one, to start a new agent from. */
268export function TemplateGallery({ templates, chosen, onChoose }: { templates: AgentTemplate[]; chosen: string | null; onChoose: (id: string | null) => void }) {
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.269 // One grid in the order g1t lists them: a template is a role, never a team.
Chat and workspace agents: channels, DMs and named agents you talk to270 return (
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)271 <div className="space-y-8">
272 <section>
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.273 <h2 className="mb-3 text-xs font-semibold tracking-wide text-faint uppercase">Roles</h2>
274 <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
275 {templates.map((template) => (
276 <TemplateCard
277 key={template.id}
278 selected={chosen === template.id}
279 onClick={() => onChoose(template.id)}
280 name={template.display_name}
281 title={template.title}
282 seed={template.handle}
283 duties={template.responsibilities.slice(0, 3)}
284 />
285 ))}
286 </div>
287 </section>
288 <section>
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)289 <h2 className="mb-3 text-xs font-semibold tracking-wide text-faint uppercase">Your own</h2>
290 <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
291 <TemplateCard
292 selected={chosen === "blank"}
293 onClick={() => onChoose("blank")}
294 name="A new role"
295 title="Start from nothing"
296 blank
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.297 duties={["Give it a name and a title", "Say what it is responsible for"]}
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)298 />
299 </div>
300 </section>
Chat and workspace agents: channels, DMs and named agents you talk to301 </div>
302 );
303}
304
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)305/** A role to hire into: its face, a name it suggests, its title and what it does. */
Chat and workspace agents: channels, DMs and named agents you talk to306function TemplateCard({
307 selected,
308 onClick,
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)309 name,
Chat and workspace agents: channels, DMs and named agents you talk to310 title,
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)311 seed,
312 duties,
Chat and workspace agents: channels, DMs and named agents you talk to313 blank,
314}: {
315 selected: boolean;
316 onClick: () => void;
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)317 name: string;
Chat and workspace agents: channels, DMs and named agents you talk to318 title: string;
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)319 seed?: string;
320 duties: string[];
Chat and workspace agents: channels, DMs and named agents you talk to321 blank?: boolean;
322}) {
323 return (
324 <button
325 type="button"
326 onClick={onClick}
327 aria-pressed={selected}
328 className={`group flex flex-col items-start rounded-xl border p-4 text-left transition-all ${
329 selected
330 ? "border-accent/60 bg-accent/[0.07] ring-1 ring-accent/40"
331 : "border-line bg-surface hover:-translate-y-px hover:border-line-strong hover:bg-raised/40"
332 }`}
333 >
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)334 <span className="flex w-full items-center gap-3">
Chat and workspace agents: channels, DMs and named agents you talk to335 {blank ? (
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)336 <span className="flex size-10 items-center justify-center rounded-[11px] border border-dashed border-line-strong text-muted">
Chat and workspace agents: channels, DMs and named agents you talk to337 <Plus size={16} />
338 </span>
339 ) : (
Agents have faces, and are never mistaken for people. Every agent wears a little bot face drawn from a look it owns, shape, colour, eyes, mouth, antenna, accessory and pattern, chosen in its builder and on its Profile tab with a live preview, Shuffle and a way back to the face its seed gives it; the face blinks on its own time, breathes, narrows its eyes while the agent works, shuts them asleep and bounces when it finishes, all of it still for anyone who asked for less motion. Wherever an agent shows, in chat, in a list, on a mention, on a review or a commit, its avatar carries an agent marker, and the people reading it are told so. In Chat, direct messages are two lists: People, and Agents, which also holds the agents you haven't talked to yet; a conversation with both a person and an agent in it is marked in the list, named in the conversation's header, spelled out by the composer and explained once the first time it opens. Agents keep their look in the agents service, which every service passes along. The chat and agents guides say so, and CONTRIBUTING makes the shared avatar the only way to draw an agent.340 <AgentAvatar agent={{ handle: seed ?? name }} size={40} />
Chat and workspace agents: channels, DMs and named agents you talk to341 )}
342 <span className="min-w-0 grow">
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)343 <span className="block truncate text-sm font-semibold">{name}</span>
344 <span className="block truncate text-xs text-muted">{title}</span>
Chat and workspace agents: channels, DMs and named agents you talk to345 </span>
346 <ChevronRight size={15} className={`shrink-0 transition-colors ${selected ? "text-accent" : "text-faint group-hover:text-muted"}`} />
347 </span>
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)348 <ul className="mt-3 space-y-1">
349 {duties.map((duty) => (
350 <li key={duty} className="flex gap-2 text-[0.8125rem] leading-snug text-muted">
351 <span className="mt-[0.45rem] size-1 shrink-0 rounded-full bg-line-strong" aria-hidden="true" />
352 <span className="line-clamp-1">{duty}</span>
353 </li>
354 ))}
355 </ul>
Chat and workspace agents: channels, DMs and named agents you talk to356 </button>
357 );
358}
359
360const FIELD = "w-full rounded-md border border-line bg-bg px-3 py-2 text-sm outline-none transition-colors placeholder:text-faint hover:border-line-strong focus:border-accent-dim";
361
362function Label({ children, hint, error, htmlFor }: { children: ReactNode; hint?: ReactNode; error?: string; htmlFor?: string }) {
363 return (
364 <div className="mb-1.5 flex items-baseline justify-between gap-3">
365 <label htmlFor={htmlFor} className="text-sm font-medium text-fg-soft">
366 {children}
367 </label>
368 {error ? <span className="text-xs text-danger">{error}</span> : hint ? <span className="text-xs text-faint">{hint}</span> : null}
369 </div>
370 );
371}
372
373/** A section of the form: what it is on the left, its fields on the right, on a wide screen. */
374function FormSection({ title, about, children }: { title: string; about: ReactNode; children: ReactNode }) {
375 return (
376 <section className="grid gap-x-10 gap-y-4 border-t border-line py-8 first-of-type:border-t-0 first-of-type:pt-0 md:grid-cols-[13rem_1fr]">
377 <div>
378 <h2 className="text-sm font-semibold">{title}</h2>
379 <p className="mt-1 text-[0.8125rem] leading-relaxed text-muted">{about}</p>
380 </div>
381 <div className="min-w-0 space-y-5">{children}</div>
382 </section>
383 );
384}
385
386function TierSelect({ name, value, none }: { name: string; value: ModelTier | null; none: string }) {
387 return (
388 <Select name={name} defaultValue={value ?? "none"}>
389 <SelectTrigger id={name}>
390 <SelectValue />
391 </SelectTrigger>
392 <SelectContent>
393 <SelectItem value="none">{none}</SelectItem>
394 {(["small", "large", "frontier"] as const).map((tier) => (
395 <SelectItem key={tier} value={tier} description={TIER_LABELS[tier].split(": ")[1]}>
396 {TIER_LABELS[tier].split(":")[0]}
397 </SelectItem>
398 ))}
399 </SelectContent>
400 </Select>
401 );
402}
403
404function Money({ name, value, label, hint, error }: { name: string; value: number | null; label: string; hint: string; error?: string }) {
405 return (
406 <div>
407 <Label htmlFor={name} hint={hint} error={error}>
408 {label}
409 </Label>
410 <div className="flex items-center rounded-md border border-line bg-bg transition-colors focus-within:border-accent-dim hover:border-line-strong">
411 <span className="pl-3 text-sm text-faint">$</span>
412 <input
413 id={name}
414 name={name}
415 inputMode="decimal"
416 defaultValue={dollarsField(value)}
417 placeholder="No cap"
418 autoComplete="off"
419 data-1p-ignore
420 className="min-w-0 grow bg-transparent px-2 py-2 text-sm tabular-nums outline-none placeholder:text-faint"
421 />
422 </div>
423 </div>
424 );
425}
426
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)427/** Names to shuffle through when a template has none of its own. */
428const FALLBACK_NAMES = ["Margo", "Juniper", "Otto", "Wren", "Basil", "Nova", "Clementine", "Fig", "Rook", "Pip"];
429
Chat and workspace agents: channels, DMs and named agents you talk to430/**
431 * Everything that defines an agent, for making one and for its Profile:
432 * who it is, its job, its voice, the limits on routing, its budget, what it
433 * may do alone, and how much it takes on at once.
434 */
435export function AgentForm({
436 draft,
437 errors,
438 submit,
439 intent,
440 formKey,
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)441 nameIdeas = [],
442 locked = false,
443 seed,
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.444 joinable = null,
Agents recall what Docs say before they answer or work, and each has required reading445 spaces = [],
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.446 hidden = {},
447 personal = false,
Pricing says it plainly: models at the provider's price, the agent rate for what g1t runs around every model call (the gateway, secrets, routing, context and pass-through to your own provider, so your own keys too), everything else at cost plus 20%, your own runners free, no seats; Security and quality comes with the plan with no separate fee, and live activations end. Each agent has an effort setting, Auto to Max, with what a typical task has cost at each level, and Spend's Spend less, keep quality suggests a lower level only when the agent's own past work shows quality held, to apply or dismiss. The pricing, spend and agents guides say how.448 effortCosts,
Chat and workspace agents: channels, DMs and named agents you talk to449}: {
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.450 /** A personal agent: on no team. */
451 personal?: boolean;
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.452 /** Making an agent: the teams the person may add it to ("Add to teams"). Left out on a profile. */
453 joinable?: { slug: string; name: string }[] | null;
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.454 /** Fields the form carries without showing: a drafted agent's scope, skills and face. */
455 hidden?: Record<string, string>;
Pricing says it plainly: models at the provider's price, the agent rate for what g1t runs around every model call (the gateway, secrets, routing, context and pass-through to your own provider, so your own keys too), everything else at cost plus 20%, your own runners free, no seats; Security and quality comes with the plan with no separate fee, and live activations end. Each agent has an effort setting, Auto to Max, with what a typical task has cost at each level, and Spend's Spend less, keep quality suggests a lower level only when the agent's own past work shows quality held, to apply or dismiss. The pricing, spend and agents guides say how.456 /** What each effort level has cost this agent, when it has a history; a new agent has none. */
457 effortCosts?: AgentEffortCosts | null;
Agents recall what Docs say before they answer or work, and each has required reading458 /** The Docs spaces the person editing can read, for its required reading. */
459 spaces?: { id: string; name: string; kind: string }[];
Chat and workspace agents: channels, DMs and named agents you talk to460 draft: AgentDraft;
461 errors?: Record<string, string>;
462 submit: string;
463 intent: string;
464 formKey?: string;
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)465 /** Names to shuffle through (a template's `name_ideas`); the dice offers them. */
466 nameIdeas?: string[];
467 /** g1t, the orchestrator: its identity and job are fixed; the rest is editable. */
468 locked?: boolean;
469 /** The agent's own `avatar_seed`, once it has one; a new agent's face follows its handle. */
470 seed?: string | null;
Chat and workspace agents: channels, DMs and named agents you talk to471}) {
472 const navigation = useNavigation();
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)473 // The handle follows the name until someone edits it.
474 const [name, setName] = useState(draft.display_name);
475 const [handle, setHandle] = useState(draft.handle);
476 const [handleEdited, setHandleEdited] = useState(Boolean(draft.handle) && cleanHandle(draft.display_name) !== draft.handle);
477 const ideas = nameIdeas.length > 0 ? nameIdeas : FALLBACK_NAMES;
478 const [idea, setIdea] = useState(() => Math.max(0, ideas.indexOf(draft.display_name)));
479 const rename = (next: string) => {
480 setName(next);
481 if (!handleEdited) setHandle(cleanHandle(next));
482 };
483 const shuffle = () => {
484 const at = (idea + 1) % ideas.length;
485 setIdea(at);
486 rename(ideas[at]!);
487 };
Chat and workspace agents: channels, DMs and named agents you talk to488 const { pathname } = useLocation();
489 const busy = navigation.state === "submitting" && navigation.formAction === pathname;
490 const [preset, setPreset] = useState(draft.personality_preset);
Agents have faces, and are never mistaken for people. Every agent wears a little bot face drawn from a look it owns, shape, colour, eyes, mouth, antenna, accessory and pattern, chosen in its builder and on its Profile tab with a live preview, Shuffle and a way back to the face its seed gives it; the face blinks on its own time, breathes, narrows its eyes while the agent works, shuts them asleep and bounces when it finishes, all of it still for anyone who asked for less motion. Wherever an agent shows, in chat, in a list, on a mention, on a review or a commit, its avatar carries an agent marker, and the people reading it are told so. In Chat, direct messages are two lists: People, and Agents, which also holds the agents you haven't talked to yet; a conversation with both a person and an agent in it is marked in the list, named in the conversation's header, spelled out by the composer and explained once the first time it opens. Agents keep their look in the agents service, which every service passes along. The chat and agents guides say so, and CONTRIBUTING makes the shared avatar the only way to draw an agent.491 // Its face: the look chosen here, or null for the one its seed draws (components/agents/face-editor.tsx).
492 const [look, setLook] = useState<AgentLook | null>(draft.look ?? null);
493 const faceSeed = seed ?? handle ?? "agent";
Chat and workspace agents: channels, DMs and named agents you talk to494 const [advanced, setAdvanced] = useState(Boolean(draft.routing.pinned));
495 const e = errors ?? {};
496 const presetAbout = PRESETS.find((p) => p.value === preset)?.about;
497 return (
498 <Form method="post" key={formKey} className="pb-24">
499 <input type="hidden" name="intent" value={intent} />
500 <input type="hidden" name="template" value={draft.template ?? ""} />
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.501 {Object.entries(hidden).map(([name, value]) => (
502 <input key={name} type="hidden" name={name} value={value} />
503 ))}
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)504 <FormSection
505 title="Identity"
506 about={
507 locked
508 ? "g1t is the workspace's orchestrator: its name, handle and role are the same everywhere, and it can't be archived."
509 : "How it shows in chat, mentions, assignees and the audit log. Give it a name people will enjoy saying."
510 }
511 >
512 <div className="flex items-center gap-3">
Agents have faces, and are never mistaken for people. Every agent wears a little bot face drawn from a look it owns, shape, colour, eyes, mouth, antenna, accessory and pattern, chosen in its builder and on its Profile tab with a live preview, Shuffle and a way back to the face its seed gives it; the face blinks on its own time, breathes, narrows its eyes while the agent works, shuts them asleep and bounces when it finishes, all of it still for anyone who asked for less motion. Wherever an agent shows, in chat, in a list, on a mention, on a review or a commit, its avatar carries an agent marker, and the people reading it are told so. In Chat, direct messages are two lists: People, and Agents, which also holds the agents you haven't talked to yet; a conversation with both a person and an agent in it is marked in the list, named in the conversation's header, spelled out by the composer and explained once the first time it opens. Agents keep their look in the agents service, which every service passes along. The chat and agents guides say so, and CONTRIBUTING makes the shared avatar the only way to draw an agent.513 <AgentAvatar agent={{ handle: handle || "agent", avatar_seed: faceSeed, look, builtin: locked }} size={44} />
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)514 <div className="min-w-0 text-sm">
515 <p className="truncate font-semibold">{name || "Your new agent"}</p>
516 <p className="truncate text-xs text-muted">{handle ? `@${handle}` : "@handle"}</p>
517 </div>
518 </div>
Chat and workspace agents: channels, DMs and named agents you talk to519 <div className="grid gap-5 sm:grid-cols-2">
520 <div>
521 <Label htmlFor="display_name" error={e.display_name}>
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)522 Name
Chat and workspace agents: channels, DMs and named agents you talk to523 </Label>
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)524 <div className="flex gap-2">
525 <input
526 id="display_name"
527 name="display_name"
528 value={name}
529 onChange={(event) => rename(event.target.value)}
530 readOnly={locked}
531 placeholder="Margo"
532 className={`${FIELD} ${locked ? "cursor-not-allowed text-muted" : ""}`}
533 autoComplete="off"
534 data-1p-ignore
535 />
536 {!locked && (
537 <Hint label="Another name">
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.538 <Button
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)539 type="button"
540 aria-label="Another name"
541 onClick={shuffle}
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.542 variant="outline" size="icon"
543 className="size-[38px] text-muted hover:bg-raised active:rotate-12"
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)544 >
545 <Dices size={17} />
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.546 </Button>
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)547 </Hint>
548 )}
549 </div>
Chat and workspace agents: channels, DMs and named agents you talk to550 </div>
551 <div>
552 <Label htmlFor="handle" error={e.handle} hint="Mentioned as @handle">
553 Handle
554 </Label>
555 <div className="flex items-center rounded-md border border-line bg-bg transition-colors focus-within:border-accent-dim hover:border-line-strong">
556 <span className="pl-3 font-mono text-sm text-faint">@</span>
557 <input
558 id="handle"
559 name="handle"
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)560 value={handle}
561 onChange={(event) => {
562 setHandle(event.target.value);
563 setHandleEdited(true);
564 }}
565 readOnly={locked}
566 placeholder="margo"
Chat and workspace agents: channels, DMs and named agents you talk to567 autoComplete="off"
568 data-1p-ignore
569 className="min-w-0 grow bg-transparent py-2 pr-3 pl-0.5 font-mono text-sm outline-none placeholder:text-faint"
570 />
571 </div>
572 </div>
573 </div>
574 </FormSection>
575
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)576 {!locked && (
Agents have faces, and are never mistaken for people. Every agent wears a little bot face drawn from a look it owns, shape, colour, eyes, mouth, antenna, accessory and pattern, chosen in its builder and on its Profile tab with a live preview, Shuffle and a way back to the face its seed gives it; the face blinks on its own time, breathes, narrows its eyes while the agent works, shuts them asleep and bounces when it finishes, all of it still for anyone who asked for less motion. Wherever an agent shows, in chat, in a list, on a mention, on a review or a commit, its avatar carries an agent marker, and the people reading it are told so. In Chat, direct messages are two lists: People, and Agents, which also holds the agents you haven't talked to yet; a conversation with both a person and an agent in it is marked in the list, named in the conversation's header, spelled out by the composer and explained once the first time it opens. Agents keep their look in the agents service, which every service passes along. The chat and agents guides say so, and CONTRIBUTING makes the shared avatar the only way to draw an agent.577 <FormSection title="Face" about="Its bot face, wherever it appears: shape, colour, eyes, mouth and a few extras. It blinks on its own, narrows its eyes while it works and sleeps when it's paused. Every agent has a face of its own from the start; change any part of it here.">
578 <input type="hidden" name="look" value={look ? JSON.stringify(look) : "null"} />
579 <FaceEditor value={look} seed={faceSeed} name={name || "Your new agent"} preset={preset} onChange={setLook} />
580 </FormSection>
581 )}
582
583 {!locked && (
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)584 <FormSection
585 title="Role"
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.586 about={
587 joinable
588 ? "Hired into a role, not a task: a title and what it is responsible for, and the teams it joins, like anyone. Shown as its name and title everywhere."
589 : "Hired into a role, not a task: a title and what it is responsible for. Shown as its name and title everywhere."
590 }
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)591 >
592 <RoleFields
593 title={draft.title}
594 responsibilities={draft.responsibilities}
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.595 joinable={joinable}
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)596 errors={e}
597 locked={locked}
Anyone makes an agent by describing it: one box drafts the whole agent (name, job, responsibilities, voice, skills to keep, integrations it needs, model limits and budget) as a card to change and try in a chat beside it before creating it, and an agent changes later by saying what to change, shown as a diff before it's saved. Members can make personal agents, which only they talk to and which spend from their own budget, unless owners turn that off; owners promote one to a workspace agent. The agents guide says how.598 personal={personal}
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)599 />
600 </FormSection>
601 )}
602
603 <FormSection
604 title="Job"
605 about={
606 locked
607 ? "Its job is fixed: know the team, hand work to the right specialist, do it itself when nobody fits, and report. Add your own instructions on top."
608 : "What it is responsible for, how it works, and what good looks like. It reads this before every reply and task."
609 }
610 >
Chat and workspace agents: channels, DMs and named agents you talk to611 <div>
612 <Label htmlFor="instructions" error={e.instructions}>
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)613 {locked ? "Extra instructions" : "Instructions"}
Chat and workspace agents: channels, DMs and named agents you talk to614 </Label>
615 <textarea
616 id="instructions"
617 name="instructions"
618 defaultValue={draft.instructions}
619 rows={9}
620 placeholder={"Cut a release of g1t every Tuesday.\n- Read the merged pull requests since the last tag.\n- Write the release notes.\n- Ask in #releases before tagging."}
621 className={`${FIELD} resize-y font-mono text-[0.8125rem] leading-relaxed`}
622 />
623 </div>
624 </FormSection>
625
Agents recall what Docs say before they answer or work, and each has required reading626 <FormSection
627 title="Required reading"
628 about="Docs it checks first, every time it answers or works. It also recalls whatever else in Docs fits the question, but only from spaces everyone in the conversation can read."
629 >
630 {spaces.length ? (
631 <div className="grid gap-1.5 sm:grid-cols-2">
632 {spaces.map((space) => (
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.633 <Card asChild key={space.id} radius="lg" className="flex min-h-10 cursor-pointer items-center gap-2.5 px-3 py-2 text-sm has-[[data-state=checked]]:border-accent/50 has-[[data-state=checked]]:bg-accent/5">
634 <label>
635 <Checkbox name="reading" value={space.id} defaultChecked={(draft.reading ?? []).includes(space.id)} />
636 <span className="min-w-0 grow truncate">{space.name}</span>
637 <span className="shrink-0 text-xs text-faint capitalize">{space.kind}</span>
638 </label>
639 </Card>
Agents recall what Docs say before they answer or work, and each has required reading640 ))}
641 </div>
642 ) : (
643 <p className="text-sm text-muted">No Docs spaces yet. Once your workspace has some, choose what it should know by heart.</p>
644 )}
645 {(draft.reading ?? []).filter((id) => !spaces.some((space) => space.id === id)).map((id) => (
646 // Spaces it reads that you can't see stay as they are.
647 <input key={id} type="hidden" name="reading" value={id} />
648 ))}
649 </FormSection>
650
Merge the workspace shell: navigation and phone shell, g1t as orchestrator, agents in roles with audience-checked reads, reactions and custom emoji, live notifications and browser push, the homepage tour (agents 0002, chat 0002)651 {!locked && (
652 <FormSection title="Subagents" about="Help it calls on for one kind of work inside its own tasks. Never members of the workspace, and never wider than the agent itself.">
653 <SubagentsField initial={draft.subagents} routing={draft.routing} />
654 {e.subagents && <p className="text-sm text-danger">{e.subagents}</p>}
655 </FormSection>
656 )}
657
Chat and workspace agents: channels, DMs and named agents you talk to658 <FormSection title="Personality" about="Its voice only: tone, length, how it asks. A personality never changes what it may do.">
659 <div>
660 <input type="hidden" name="personality_preset" value={preset} />
661 <div role="radiogroup" aria-label="Voice" className="grid grid-cols-2 gap-1 rounded-lg bg-surface p-1 ring-1 ring-line sm:grid-cols-4">
662 {PRESETS.map((option) => (
663 <button
664 key={option.value}
665 type="button"
666 role="radio"
667 aria-checked={preset === option.value}
668 onClick={() => setPreset(option.value)}
669 className={`h-8 rounded-md text-[0.8125rem] font-medium transition-colors ${
670 preset === option.value ? "bg-raised text-fg shadow-sm ring-1 ring-line-strong" : "text-muted hover:text-fg"
671 }`}
672 >
673 {option.label}
674 </button>
675 ))}
676 </div>
677 <p className="mt-2 text-xs text-muted">{presetAbout}</p>
678 </div>
679 <div>
680 <Label htmlFor="personality" hint="Optional">
681 In its own words
682 </Label>
683 <textarea
684 id="personality"
685 name="personality"
686 defaultValue={draft.personality}
687 rows={3}
688 placeholder="Dry humor is fine. No emoji. Asks one question at a time."
689 className={`${FIELD} resize-y`}
690 />
691 </div>
692 </FormSection>
693
694 <FormSection
695 title="Models"
696 about="Nobody picks a model to get work done. g1t routes each step to the tier it needs and records which ran. These only limit the routing."
697 >
698 <div className="flex items-start gap-3 rounded-xl border border-accent/25 bg-accent/[0.06] p-4">
699 <span className="mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-lg bg-accent/15 text-accent">
700 <RouteIcon size={16} />
701 </span>
702 <div>
703 <p className="text-sm font-semibold">Auto: routed per step by need</p>
704 <p className="mt-0.5 text-[0.8125rem] leading-relaxed text-muted">
705 Replies and triage run on Fast; making changes on Standard; planning, hard reviews and retries after a failure on Most capable. It steps up after a failure and back down when the cheaper tier works.
706 </p>
707 </div>
708 </div>
Pricing says it plainly: models at the provider's price, the agent rate for what g1t runs around every model call (the gateway, secrets, routing, context and pass-through to your own provider, so your own keys too), everything else at cost plus 20%, your own runners free, no seats; Security and quality comes with the plan with no separate fee, and live activations end. Each agent has an effort setting, Auto to Max, with what a typical task has cost at each level, and Spend's Spend less, keep quality suggests a lower level only when the agent's own past work shows quality held, to apply or dismiss. The pricing, spend and agents guides say how.709 <div>
710 <Label hint="Tier, reasoning and steps together">Effort</Label>
711 <EffortPicker value={effortSetting(draft.routing)} costs={effortCosts} />
712 </div>
Chat and workspace agents: channels, DMs and named agents you talk to713 <div className="grid gap-5 sm:grid-cols-3">
714 <div>
715 <Label htmlFor="floor">Floor</Label>
716 <TierSelect name="floor" value={draft.routing.floor} none="No floor" />
717 </div>
718 <div>
719 <Label htmlFor="ceiling" error={e.ceiling}>
720 Ceiling
721 </Label>
722 <TierSelect name="ceiling" value={draft.routing.ceiling} none="No ceiling" />
723 </div>
724 <div>
725 <Label htmlFor="providers">Providers</Label>
726 <Select name="providers" defaultValue={draft.routing.providers[0] ?? "any"}>
727 <SelectTrigger id="providers">
728 <SelectValue />
729 </SelectTrigger>
730 <SelectContent>
731 <SelectItem value="any" description="g1t's hosted models and the workspace's own">
732 Any the workspace allows
733 </SelectItem>
734 <SelectItem value="g1t" description="Never the workspace's own keys">
735 g1t's hosted models
736 </SelectItem>
737 <SelectItem value="workspace" description="Set up under Integrations; billed by the provider">
738 The workspace's own providers
739 </SelectItem>
740 </SelectContent>
741 </Select>
742 </div>
743 </div>
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.744 <Card tone="plain" radius="lg">
Chat and workspace agents: channels, DMs and named agents you talk to745 <button
746 type="button"
747 onClick={() => setAdvanced(!advanced)}
748 aria-expanded={advanced}
749 className="flex w-full items-center gap-2 px-3.5 py-2.5 text-left text-[0.8125rem] font-medium text-muted hover:text-fg"
750 >
751 <ChevronRight size={14} className={`transition-transform ${advanced ? "rotate-90" : ""}`} />
752 Advanced
753 <span className="font-normal text-faint">Pin one model</span>
754 </button>
755 <div hidden={!advanced} className="border-t border-line px-3.5 py-3.5">
756 <Label htmlFor="pinned" error={e.pinned} hint="For your own endpoints. Turns routing off.">
757 Pinned model
758 </Label>
759 <input id="pinned" name="pinned" defaultValue={draft.routing.pinned ?? ""} placeholder="provider/model" className={`${FIELD} font-mono`} autoComplete="off" data-1p-ignore />
760 </div>
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.761 </Card>
Chat and workspace agents: channels, DMs and named agents you talk to762 </FormSection>
763
764 <FormSection title="Budget" about="Checked before work starts and enforced while it runs. At 80% of the month it tells you; at 100% it takes no new tasks.">
765 <div className="grid gap-5 sm:grid-cols-3">
766 <Money name="monthly" label="Monthly" hint="Per calendar month" value={draft.budget.monthly_micros} error={e.monthly} />
767 <Money name="daily" label="Daily" hint="Optional" value={draft.budget.daily_micros} error={e.daily} />
Agents mode: an overview of every agent's work and spend, and each agent's sessions, memory, routines, spend, activity and versions768 <Money name="task" label="Per session" hint="Going over asks an owner" value={draft.budget.task_micros} error={e.task} />
Chat and workspace agents: channels, DMs and named agents you talk to769 </div>
770 </FormSection>
771
772 <FormSection title="Autonomy" about="What it may do alone and what needs a person. Rulesets and branch protection still apply on top.">
773 <div className="grid gap-5 sm:grid-cols-2">
774 {(Object.keys(AUTONOMY) as (keyof typeof AUTONOMY)[]).map((key) => (
775 <div key={key}>
776 <Label htmlFor={key}>{AUTONOMY[key].label}</Label>
777 <Select name={key} defaultValue={draft.autonomy[key]}>
778 <SelectTrigger id={key}>
779 <SelectValue />
780 </SelectTrigger>
781 <SelectContent>
782 {AUTONOMY[key].options.map(([value, label]) => (
783 <SelectItem key={value} value={value}>
784 {label}
785 </SelectItem>
786 ))}
787 </SelectContent>
788 </Select>
789 </div>
790 ))}
791 </div>
792 </FormSection>
793
Agents mode: an overview of every agent's work and spend, and each agent's sessions, memory, routines, spend, activity and versions794 <FormSection title="Capacity" about="How many sessions it works on at once. More wait in line, queued.">
Chat and workspace agents: channels, DMs and named agents you talk to795 <div className="max-w-40">
796 <Label htmlFor="capacity" error={e.capacity}>
Agents mode: an overview of every agent's work and spend, and each agent's sessions, memory, routines, spend, activity and versions797 Sessions at once
Chat and workspace agents: channels, DMs and named agents you talk to798 </Label>
The top of every page is one surface: the breadcrumb, search, spend, Ask g1t, bell and + share one height, corners and spacing, Ask g1t is a plain tinted button with the g1t mark drawn on whole pixels, a page's own header sits directly under the bar at the same left edge, and every section, conversations and open artifacts included, draws the same rounded panel. Tables written in chat render as tables, and the site's file, checkbox, radio, number and date controls are the design system's. Button, Separator, Breadcrumb, Table and FileDrop join the shared components; the chat guide says how tables work.799 <Input id="capacity" name="capacity" type="number" min={1} max={20} defaultValue={draft.capacity} />
Chat and workspace agents: channels, DMs and named agents you talk to800 </div>
801 </FormSection>
802
Phones reach every page: each mode's menu from the top bar or by tapping the tab you're on, Docs first in the avatar sheet, a project's pages as a swipeable strip; dialogs as bottom sheets above the keyboard, safe areas, menus kept on screen, 40px targets, touch-visible controls, save bars above the tab bar803 <div className="sticky bottom-(--tabbar-h) in-data-[keyboard=open]:bottom-0 z-10 -mx-4 flex items-center justify-end gap-3 border-t border-line bg-bg/90 px-4 py-3 backdrop-blur sm:-mx-8 sm:px-8">
Chat and workspace agents: channels, DMs and named agents you talk to804 {Object.keys(e).length > 0 && <p className="mr-auto text-sm text-danger">Check the fields marked above.</p>}
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.805 <Button
Chat and workspace agents: channels, DMs and named agents you talk to806 type="submit"
807 disabled={busy}
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.808 variant="accent"
809 className="px-4 disabled:opacity-60"
Chat and workspace agents: channels, DMs and named agents you talk to810 >
811 <Sparkles size={15} />
812 {busy ? "Saving…" : submit}
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.813 </Button>
Chat and workspace agents: channels, DMs and named agents you talk to814 </div>
815 </Form>
816 );
817}

This file's history is long; its oldest lines are credited to the oldest commit read.