Official
git
Built-in git UI (JavaScript UI plugin).
The app opens the listing; nothing installs until an agent in your Plugins workspace has read the files and you enable the plugin. In a terminal: cvg install convergence/git@0.2.0
Permissions in 0.2.0
Files
views/controls.ts4.3 KB
// Primary action, branch picker and repository menu trees.
// HTM whitespace is significant; keep these templates out of Prettier's HTML formatter.
import { ui, html as htm } from "convergence";
import type { GitStatus } from "convergence";
import type { EffectViewContext } from "convergence/effect";
import type { Git } from "../controller.ts";
import { branchOptions, MENU, primaryAction } from "../status.ts";
import type { Groups } from "../status.ts";
import { column, panelRow, menuCard } from "./layout.ts";
export function controls(ctx: EffectViewContext<object>, actions: Git["Service"]) {
const { state } = actions;
function primaryButton(status: GitStatus, total: number) {
const disabled = !!state.busy;
if (primaryAction(status, total) === "commit") {
return htm`<button id="git-commit" icon="check" label="Commit" variant="accent" disabled=${disabled || !state.message.trim()} onClick=${() => ctx.run(actions.commit())} />`;
}
if (primaryAction(status, total) === "publish") {
return htm`<button id="git-publish" icon="cloud-upload" label="Publish Branch" variant="accent" disabled=${disabled} onClick=${() => ctx.run(actions.publish())} />`;
}
if (primaryAction(status, total) === "sync") {
const counts = [status.behind ? `${status.behind}↓` : null, status.ahead ? `${status.ahead}↑` : null]
.filter(Boolean)
.join(" ");
return htm`<button id="git-sync" icon="refresh-cw" label=${`Sync Changes ${counts}`} variant="accent" disabled=${disabled} onClick=${() => ctx.run(actions.sync())} />`;
}
return htm`<button id="git-commit" icon="check" label="Commit" variant="accent" disabled />`;
}
function branchPicker(status: GitStatus) {
const { query: q, shown, create } = branchOptions(state.branches, state.branchQuery);
const items = [
...(create
? [
{
id: "git-branch-create",
label: `Create branch "${q}"`,
icon: "plus",
onClick: () => ctx.run(actions.checkout(q, true)),
},
]
: []),
...shown.map((b) => ({
id: `git-branch-${b}`,
label: b,
icon: "git-branch",
selected: b === status.branch,
onClick: () => ctx.run(actions.checkout(b, false)),
})),
];
return htm`
<popover id="git-branch-popover" open=${state.branchOpen} align="start" width=${280} onDismiss=${() => {
state.branchOpen = false;
ctx.update();
}}>
<div ...${panelRow} id="git-branch" onPress=${() => ctx.run(actions.openBranches())}>
<icon name="git-branch" small tone="muted" />
<text style="body" size="xs" tone="muted" truncate>${status.branch ?? "(no branch)"}</text>
</div>
<div ...${menuCard}>
<input id="git-branch-query" value=${state.branchQuery} placeholder="Switch to or create a branch"
onChange=${(e: { value: string }) => {
state.branchQuery = e.value;
ctx.update();
}}
onSubmit=${() => {
if (create) ctx.run(actions.checkout(q, true));
else if (shown[0]) ctx.run(actions.checkout(shown[0], false));
}} />
<div ...${column} gap="small" padding="small" maxHeight=${280} overflowY="scroll">
${items.length ? ui.list({ id: "git-branch-list", items }) : htm`<text style="muted">No branches.</text>`}
</div>
</div>
</popover>`;
}
function menu(status: GitStatus, g: Groups) {
const items = MENU.map((item) => ({
id: `git-menu-${item.action}`,
label: item.label,
icon: item.icon,
onClick: () => {
state.menuOpen = false;
ctx.update();
ctx.run(actions.menuAction(item.action, status, g));
},
}));
return htm`
<popover id="git-menu" open=${state.menuOpen} align="end" width=${220} onDismiss=${() => {
state.menuOpen = false;
ctx.update();
}}>
<button id="git-more" icon="ellipsis" variant="ghost" small tooltip="More actions" disabled=${!!state.busy}
onClick=${() => {
state.menuOpen = !state.menuOpen;
ctx.update();
}} />
<div ...${menuCard}>${ui.list({ id: "git-menu-list", items })}</div>
</popover>`;
}
return { primaryButton, branchPicker, menu };
}Versions
| Version | Published | Plugin API | Size | Permissions | Status |
|---|---|---|---|---|---|
| 0.2.0latest | Oct 5, 2026 | >=2 <3 | 13.4 KB | 4 permissions | Listed |
No comments yet.