Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t.sh
223 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.

Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r91// The title bar's work: draw what the page under it reports, and send its
2// buttons to the app (src/bridge.rs: title_bar_current, title_bar_act,
3// window_control, window_menu). A click here hands the keyboard back to
4// the page, so typing goes on where it was.
5(function () {
6 var core = window.__TAURI__ && window.__TAURI__.core;
7 var events = window.__TAURI__ && window.__TAURI__.event;
8 function invoke(command, args) {
9 if (core && typeof core.invoke === "function") return core.invoke(command, args || {});
10 return Promise.reject(new Error("the title bar cannot reach the app"));
11 }
12 function quietly(promise) {
13 promise.catch(function () {});
14 }
15 function act(action) {
16 quietly(invoke("title_bar_act", { action: action }));
17 }
18 function control(action) {
19 return invoke("window_control", { action: action });
20 }
21
22 var ua = navigator.userAgent;
23 var MAC = /Macintosh|Mac OS X/.test(ua) && !/Windows/.test(ua);
24 if (MAC) document.documentElement.classList.add("mac");
25
26 function svg(body) {
27 return (
28 '<svg viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' +
29 body +
30 "</svg>"
31 );
32 }
33 // Drawn here, from lines and boxes, as each system draws its own.
34 var ICONS = {
35 menu: svg('<line x1="3" y1="4.5" x2="13" y2="4.5"/><line x1="3" y1="8" x2="13" y2="8"/><line x1="3" y1="11.5" x2="13" y2="11.5"/>'),
36 back: svg('<polyline points="9.5,3.5 5,8 9.5,12.5"/><line x1="5" y1="8" x2="13" y2="8"/>'),
37 forward: svg('<polyline points="6.5,3.5 11,8 6.5,12.5"/><line x1="3" y1="8" x2="11" y2="8"/>'),
38 search: svg('<circle cx="7" cy="7" r="4"/><line x1="10" y1="10" x2="13" y2="13"/>'),
The desktop app's settings are a button in its title bar. A Settings button sits at the right of the bar, before the window's own buttons (and at its end on macOS), so the runner and the rest are a click away instead of only in the File menu, the tray or the account menu.39 settings: svg('<line x1="2.5" y1="4.5" x2="13.5" y2="4.5"/><line x1="2.5" y1="11.5" x2="13.5" y2="11.5"/><circle cx="10" cy="4.5" r="1.75" fill="var(--bg)"/><circle cx="6" cy="11.5" r="1.75" fill="var(--bg)"/>'),
Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r940 minimize: svg('<line x1="3.5" y1="8" x2="12.5" y2="8"/>'),
41 maximize: svg('<rect x="3.5" y="3.5" width="9" height="9" rx="1"/>'),
42 restore: svg('<rect x="3.5" y="5.5" width="7" height="7" rx="1"/><path d="M5.5 5.5V4.5a1 1 0 0 1 1-1h5a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-1"/>'),
43 close: svg('<line x1="4" y1="4" x2="12" y2="12"/><line x1="12" y1="4" x2="4" y2="12"/>'),
44 };
45
46 function button(kind, label, icon, onClick) {
47 var b = document.createElement("button");
48 b.type = "button";
49 b.tabIndex = -1;
50 b.className = kind;
51 b.setAttribute("aria-label", label);
52 b.title = label;
53 if (icon) b.innerHTML = ICONS[icon];
54 b.addEventListener("click", function (event) {
55 event.stopPropagation();
56 onClick(b);
57 });
58 return b;
59 }
60
61 var bar = document.getElementById("bar");
62 var left = document.getElementById("left");
63 var middle = document.getElementById("middle");
64 var right = document.getElementById("right");
65
66 if (!MAC) {
67 left.append(
68 button("icon", "Menu", "menu", function (b) {
69 var box = b.getBoundingClientRect();
70 quietly(invoke("window_menu", { x: box.left, y: box.bottom }));
71 }),
72 );
73 }
74 var back = button("icon", "Back", "back", function () {
75 act("back");
76 });
77 var forward = button("icon", "Forward", "forward", function () {
78 act("forward");
79 });
80 left.append(back, forward);
81
Merge branch 'main' into rm-agents82 // The runner, as a dot right beside the settings: its colour says what
83 // it is doing, live, and a wide window says it in words too. A click
84 // opens its menu, which the site draws under the dot (or, with no page
85 // of the site's to draw it, the Runner window). The words are the app's
86 // (diagnosis.rs chip).
87 var chip = button("chip", "Runner", null, function (b) {
88 var box = b.getBoundingClientRect();
89 var width = document.documentElement.clientWidth || window.innerWidth || 1;
90 // Where the dot's right edge is, as a share of the bar, so the menu
91 // lines up under it whatever the site's zoom.
92 quietly(invoke("title_bar_act", { action: "runner", at: box.right / width }));
The desktop app is 0.3.4, and the runner has a window of its own. Beside the title bar's Settings button a chip says what the runner is doing, live, with a dot in its colour (Runner running, Running a job, Running 2 jobs, Runner starting, Runner updating, Runner stopped, Runner offline, Runner needs you), as Docker Desktop shows its engine; in a narrow window only the dot shows. It opens the Runner window, as the tray's runner row now does: at its top what the whole runner is doing, with what it is running, its version and workspace, and its own Stop or Start; then each kind of job's card as before; then its setup (running jobs here at all, how jobs run, the workspace, the computer with Check for runner updates and View on g1t); and its log, open and following along as it is written. Settings keeps the runner as one line, what it is doing with Open runner, and each window saves only its own settings over what the app has now, so neither undoes the other's. The chip's words are diagnosis.rs's, the Runner window is made off the main thread as Settings now is, and it has a capability of its own with only the commands it uses; the title bar may now ask the runner's status. Two things fixed on the way: a settings row hidden until it applies, Restart to change the title bar, showed all the time, since its row's display beat the hidden attribute; and in a narrow window the title bar's buttons ran over the search, which now shrinks instead. The desktop guide describes the chip, the Runner window and where each runner setting now is.93 });
94 chip.hidden = true;
Merge branch 'main' into rm-agents95 chip.setAttribute("aria-haspopup", "dialog");
96 chip.setAttribute("aria-expanded", "false");
The desktop app is 0.3.4, and the runner has a window of its own. Beside the title bar's Settings button a chip says what the runner is doing, live, with a dot in its colour (Runner running, Running a job, Running 2 jobs, Runner starting, Runner updating, Runner stopped, Runner offline, Runner needs you), as Docker Desktop shows its engine; in a narrow window only the dot shows. It opens the Runner window, as the tray's runner row now does: at its top what the whole runner is doing, with what it is running, its version and workspace, and its own Stop or Start; then each kind of job's card as before; then its setup (running jobs here at all, how jobs run, the workspace, the computer with Check for runner updates and View on g1t); and its log, open and following along as it is written. Settings keeps the runner as one line, what it is doing with Open runner, and each window saves only its own settings over what the app has now, so neither undoes the other's. The chip's words are diagnosis.rs's, the Runner window is made off the main thread as Settings now is, and it has a capability of its own with only the commands it uses; the title bar may now ask the runner's status. Two things fixed on the way: a settings row hidden until it applies, Restart to change the title bar, showed all the time, since its row's display beat the hidden attribute; and in a narrow window the title bar's buttons ran over the search, which now shrinks instead. The desktop guide describes the chip, the Runner window and where each runner setting now is.97 var chipDot = document.createElement("span");
98 chipDot.className = "chip-dot";
99 var chipText = document.createElement("span");
100 chipText.className = "chip-text";
101 chip.append(chipDot, chipText);
102 function drawChip(said) {
103 if (!said || !said.label) return;
104 chip.hidden = false;
105 chip.dataset.tone = said.tone;
106 chipText.textContent = said.label;
Merge branch 'main' into rm-agents107 chip.setAttribute("aria-label", /runner/i.test(said.label) ? said.label : "Runner: " + said.label);
108 chip.title = said.label;
The desktop app is 0.3.4, and the runner has a window of its own. Beside the title bar's Settings button a chip says what the runner is doing, live, with a dot in its colour (Runner running, Running a job, Running 2 jobs, Runner starting, Runner updating, Runner stopped, Runner offline, Runner needs you), as Docker Desktop shows its engine; in a narrow window only the dot shows. It opens the Runner window, as the tray's runner row now does: at its top what the whole runner is doing, with what it is running, its version and workspace, and its own Stop or Start; then each kind of job's card as before; then its setup (running jobs here at all, how jobs run, the workspace, the computer with Check for runner updates and View on g1t); and its log, open and following along as it is written. Settings keeps the runner as one line, what it is doing with Open runner, and each window saves only its own settings over what the app has now, so neither undoes the other's. The chip's words are diagnosis.rs's, the Runner window is made off the main thread as Settings now is, and it has a capability of its own with only the commands it uses; the title bar may now ask the runner's status. Two things fixed on the way: a settings row hidden until it applies, Restart to change the title bar, showed all the time, since its row's display beat the hidden attribute; and in a narrow window the title bar's buttons ran over the search, which now shrinks instead. The desktop guide describes the chip, the Runner window and where each runner setting now is.109 }
110 // The app's settings, at the right of the bar, before the window's
111 // buttons: where they are found without the menu.
The desktop app's settings are a button in its title bar. A Settings button sits at the right of the bar, before the window's own buttons (and at its end on macOS), so the runner and the rest are a click away instead of only in the File menu, the tray or the account menu.112 right.append(
The desktop app is 0.3.4, and the runner has a window of its own. Beside the title bar's Settings button a chip says what the runner is doing, live, with a dot in its colour (Runner running, Running a job, Running 2 jobs, Runner starting, Runner updating, Runner stopped, Runner offline, Runner needs you), as Docker Desktop shows its engine; in a narrow window only the dot shows. It opens the Runner window, as the tray's runner row now does: at its top what the whole runner is doing, with what it is running, its version and workspace, and its own Stop or Start; then each kind of job's card as before; then its setup (running jobs here at all, how jobs run, the workspace, the computer with Check for runner updates and View on g1t); and its log, open and following along as it is written. Settings keeps the runner as one line, what it is doing with Open runner, and each window saves only its own settings over what the app has now, so neither undoes the other's. The chip's words are diagnosis.rs's, the Runner window is made off the main thread as Settings now is, and it has a capability of its own with only the commands it uses; the title bar may now ask the runner's status. Two things fixed on the way: a settings row hidden until it applies, Restart to change the title bar, showed all the time, since its row's display beat the hidden attribute; and in a narrow window the title bar's buttons ran over the search, which now shrinks instead. The desktop guide describes the chip, the Runner window and where each runner setting now is.113 chip,
The desktop app's settings are a button in its title bar. A Settings button sits at the right of the bar, before the window's own buttons (and at its end on macOS), so the runner and the rest are a click away instead of only in the File menu, the tray or the account menu.114 button("icon", "Settings", "settings", function () {
115 act("settings");
116 }),
117 );
118
Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9119 var maximize = null;
120 function drawMaximized(maximized) {
121 if (!maximize) return;
122 maximize.innerHTML = maximized ? ICONS.restore : ICONS.maximize;
123 maximize.setAttribute("aria-label", maximized ? "Restore" : "Maximize");
124 maximize.title = maximized ? "Restore" : "Maximize";
125 }
126 // The window's buttons, at the right as Windows and Linux put them; macOS has its own.
127 if (!MAC) {
128 maximize = button("caption", "Maximize", "maximize", function () {
129 control("maximize").then(drawMaximized, function () {});
130 });
131 right.append(
132 button("caption", "Minimize", "minimize", function () {
133 quietly(control("minimize"));
134 }),
135 maximize,
136 button("caption close", "Close", "close", function () {
137 quietly(control("close"));
138 }),
139 );
140 var resizing = 0;
141 window.addEventListener("resize", function () {
142 clearTimeout(resizing);
143 resizing = setTimeout(function () {
144 control("maximized").then(drawMaximized, function () {});
145 }, 120);
146 });
147 control("maximized").then(drawMaximized, function () {});
148 }
149
150 // Dragging the bar moves the window; a double click maximizes it, as a system's title bar does.
151 bar.addEventListener("mousedown", function (event) {
152 if (event.button !== 0 || event.target.closest("button")) return;
153 if (event.detail === 2) {
154 control("maximize").then(drawMaximized, function () {});
155 return;
156 }
157 quietly(control("drag"));
158 });
159 // The keyboard belongs to the page: a click here gives it back.
160 window.addEventListener("mouseup", function () {
161 act("focus");
162 });
163
164 var title = document.createElement("span");
165 title.className = "title";
166 var pill = button("search", "Search", "search", function () {
167 act("search");
168 });
169 var pillText = document.createElement("span");
170 pill.append(pillText);
171
172 function setColors(colors) {
173 var root = document.documentElement.style;
174 if (!colors) return;
175 var shade = colors.dark ? "237, 237, 239" : "15, 15, 17";
176 root.setProperty("--bg", colors.background);
177 root.setProperty("--fg", colors.foreground);
178 root.setProperty("--muted", colors.muted);
179 root.setProperty("--accent", colors.accent);
180 root.setProperty("--hover", "rgba(" + shade + ", " + (colors.dark ? 0.1 : 0.07) + ")");
181 root.setProperty("--pill", "rgba(" + shade + ", " + (colors.dark ? 0.09 : 0.05) + ")");
182 root.setProperty("--pill-hover", "rgba(" + shade + ", " + (colors.dark ? 0.14 : 0.09) + ")");
183 root.setProperty("--pill-edge", "rgba(" + shade + ", " + (colors.dark ? 0.08 : 0.1) + ")");
184 document.documentElement.style.colorScheme = colors.dark ? "dark" : "light";
185 }
186
187 function draw(page) {
188 if (!page) return;
189 middle.textContent = "";
190 if (page.search) {
191 pillText.textContent = page.search;
192 pill.setAttribute("aria-label", page.search);
193 pill.removeAttribute("title");
194 middle.append(pill);
195 } else {
196 title.textContent = page.title || "g1t";
197 middle.append(title);
198 }
Merge branch 'main' into rm-agents199 chip.setAttribute("aria-expanded", page.runnerMenu ? "true" : "false");
Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9200 back.disabled = page.canGoBack === false;
201 forward.disabled = page.canGoForward === false;
202 setColors(page.colors);
203 }
204
205 if (events && typeof events.listen === "function") {
206 events
207 .listen("g1t-title-bar", function (event) {
208 draw(event.payload);
209 })
210 .catch(function () {});
211 }
212 invoke("title_bar_current").then(draw, function () {});
The desktop app is 0.3.4, and the runner has a window of its own. Beside the title bar's Settings button a chip says what the runner is doing, live, with a dot in its colour (Runner running, Running a job, Running 2 jobs, Runner starting, Runner updating, Runner stopped, Runner offline, Runner needs you), as Docker Desktop shows its engine; in a narrow window only the dot shows. It opens the Runner window, as the tray's runner row now does: at its top what the whole runner is doing, with what it is running, its version and workspace, and its own Stop or Start; then each kind of job's card as before; then its setup (running jobs here at all, how jobs run, the workspace, the computer with Check for runner updates and View on g1t); and its log, open and following along as it is written. Settings keeps the runner as one line, what it is doing with Open runner, and each window saves only its own settings over what the app has now, so neither undoes the other's. The chip's words are diagnosis.rs's, the Runner window is made off the main thread as Settings now is, and it has a capability of its own with only the commands it uses; the title bar may now ask the runner's status. Two things fixed on the way: a settings row hidden until it applies, Restart to change the title bar, showed all the time, since its row's display beat the hidden attribute; and in a narrow window the title bar's buttons ran over the search, which now shrinks instead. The desktop guide describes the chip, the Runner window and where each runner setting now is.213 if (events && typeof events.listen === "function") {
214 events
215 .listen("g1t-runner-status", function (event) {
216 drawChip(event.payload);
217 })
218 .catch(function () {});
219 }
220 invoke("runner_status").then(function (view) {
221 drawChip(view && view.chip);
222 }, function () {});
Merge remote-tracking branch 'origin/claude/cool-newton-7nm8r9' into claude/cool-newton-7nm8r9223})();

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