6ef1c195e3
git boundary: Pull/Push/Commit/DiscardAll (discard is 1.4-destructive). Scanner.RefreshRepo re-scans one repo after a mutation. Service GitFetch/GitPull/GitPush/GitCommit/GitDiscard record a git-* activity event and refresh on success; service.New takes a refresh hook. HTTP POST /api/repo/git. New <repo-menu> overlay with plain-language commands (Get latest/Publish/Check for updates/Save my work/Set active/Ask Claude to switch/Copy path/Discard all changes), summoned by repo-list's repo:contextmenu. Added service test for commit/discard on a temp repo. Verified the menu live for safe commands. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
13 KiB
13 KiB
Changelog
Append-only running history of all changes (AGENT.md §9.1). Newest last.
2026-09-19 — Project scaffold
- What: Initial runnable skeleton for the GitManager multi-repo dashboard.
Added the Go backend (
cmd/server/main.go+internal/{config,logging,git,repos,render}), the Echo HTTP server with/,/help,/healthz, and/api/repos, a read-only repo scanner that discovers repositories underGIT_REPO_ROOTSand keeps an in-memory index, the<repo-list>web component, shared design tokens (web/static/app.css), page shells (web/templates/{index,help}.html), and the dev tooling:Dockerfile(build/dev/runtime stages),docker-compose.yml,.air.toml,.env.example,.gitignore,go.mod. - Why: Stand up the architecture defined in AGENT.md so feature work can begin.
- Affects: whole repo (foundation);
components/repo-list.
2026-09-19 — Repo detail panel
- What: Added the
<repo-detail>component (right dock) that listens forrepo:selectand shows a repo's remotes, local branches (current + upstream), and 20 most recent commits. Backed by a newGET /api/repo?path=endpoint (restricted to indexed repos) and new read-only git readers (LocalBranches,RecentCommits,RemoteDetails) plusrepos.BuildDetailandIndex.Get.<repo-list>now highlights the selected repo;index.htmllays the two panels out left/right; help page documents the detail view. - Why: Make the dashboard drill into a single repository (the detail half of the list+detail default in AGENT.md §4).
- Affects:
components/repo-detail,components/repo-list,internal/git,internal/repos,cmd/server,web/templates.
Notes to confirm (from AGENT.md §11)
- Go module path is the placeholder
gitmanager; change it if this gets a canonical import path (e.g. a GitHub URL). - All items in AGENT.md §11 (discovery strategy, background fetch, forge providers, listen address, container credentials) remain open.
2026-09-19 — Redefine the app as a two-way Claude companion (contract only)
- What: Updated AGENT.md to make the Claude integration the defining pillar,
no code yet. §0 now states the two-way purpose (Claude↔app) and the
non-expert, GUI-first goal; added law §1.7 (one service layer behind both the
GUI and the MCP server); stack table gained MCP server (Go SDK over Streamable
HTTP at
/mcp), SSE (app→browser), and flipped forge to Gitea-first read+write; layout addedinternal/{service,mcp,activity}; §6 added the right-click plain-language command vocabulary; §8 rewritten into "Claude integration" (8.1 MCP server, 8.2 activity feed + active project, 8.3 graceful project handoff, 8.4 forge read+write with "Merge & clean up"); §10 step 4 and §11 updated (three decisions resolved, new open items)..env.examplenow documentsGITEA_TOKEN(read+write scope). - Why: Thomas described the real vision — the app should act as an extension
of Claude: usable like an MCP by Claude, notifying Claude of in-app actions to
stay in sync, cooperative project handoff when he's interrupted, plain-language
right-click commands for non-experts, and one-click "merge & clean up" so PRs
stop cluttering repos. Decisions locked: cooperative pull-first handoff; Gitea
writes enabled (confirmed per §1.4); MCP over HTTP
/mcp. - Affects:
AGENT.md,.env.example(architecture/contract only — no code).
2026-09-19 — Service layer + MCP server (Claude integration, read tools)
- What: Slice 1 — extracted
internal/service, the one capability layer both the HTTP API and the MCP server call (§1.7); the/api/reposand/api/repohandlers now route through it. Slice 2 — addedinternal/mcp: an MCP server (github.com/modelcontextprotocol/go-sdkv1.8.0) served over Streamable HTTP at/mcp, with read toolslist_reposandget_repoas thin adapters over the service. Added a round-trip test (internal/mcp/mcp_test.go) using a real temp git repo + the in-memory MCP transport. Verified the HTTP/mcphandshake locally and in Docker. - Why: First step of the two-way Claude integration (AGENT.md §8.1) — prove Claude can connect to the app over MCP before building deeper features on it.
- Affects:
internal/service(new),internal/mcp(new),cmd/server/main.go,go.mod/go.sum,.air.toml. - Gotcha: Docker-on-Windows bind mounts do NOT deliver filesystem events, so
air's watch-based reload silently never fired. Fixed by enabling air polling
(
poll = true,poll_interval = 500in.air.toml).
2026-09-20 — HTTPS for the MCP connector (local TLS via mkcert)
- What: Added an optional HTTPS listener alongside HTTP. New config
HTTPS_ADDR,TLS_CERT_FILE,TLS_KEY_FILE; when set,cmd/serverstartse.StartTLSon the same Echo app (best-effort — a missing cert logs a warning and stays HTTP-only). docker-compose publishes127.0.0.1:8443and points the TLS vars atcerts/localhost.pem(mounted via the existing source mount)..gitignoreignores/certs/;.env.exampledocuments the mkcert steps. - Why: Claude Desktop's custom MCP connector only accepts
https://URLs. Local TLS with an mkcert-trusted cert letshttps://localhost:8443/mcpwork without exposing the unauthenticated app via a public tunnel (AGENT.md §8.1). - Affects:
internal/config,cmd/server/main.go,docker-compose.yml,.gitignore,.env.example,AGENT.md(§8.1, §11). - Host setup (user-run): the local CA install (
mkcert -install) is a security-settings change performed by the user, not the app.
2026-09-20 — Connect Claude Desktop via local stdio bridge (mcp-remote)
- What: Corrected the Claude Desktop connection method in AGENT.md (§8.1, §11).
The GUI "Add custom connector" flow can NOT reach a localhost server — it probes
and calls tools from Anthropic's cloud, so
https://127.0.0.1:8443/mcpfails "couldn't reach the server" even though a local browser reaches it. The working path is a local stdio bridge inclaude_desktop_config.json:mcpServers.gitmanager = cmd /c npx -y mcp-remote http://127.0.0.1:8080/mcp. Added that entry to the user's Claude Desktop config (backup saved alongside). - Why: Keep the app localhost-only + unauthenticated (§0) while still letting
Claude Desktop drive it.
mcp-remoteruns locally, so it reaches the local endpoint directly — no public exposure, no HTTPS needed for this path. - Affects:
AGENT.md(§8.1, §11); user'sclaude_desktop_config.json(outside the repo). HTTPS/:8443from the prior entry stays available but is now optional.
2026-09-20 — Slice 3: activity feed + active project (§8.2)
- What: Added
internal/activity(thread-safe active project + bounded event feed with subscriber fan-out, mirrored to logs, no datastore). Service gainedActiveProject/SetActiveProject/RecordActivity/Activity/SubscribeActivity(andservice.Newnow takes the feed). New MCP toolsget_active_project,set_active_project,get_activity(object-wrapped outputs). New HTTP:GET/POST /api/active-project,GET /api/activity, andGET /events(SSE). New<activity-feed>component (live via EventSource);<repo-list>now sets the active project on selection (a user action). Extended the MCP test to cover the new tools; help page documents the feature. - Why: The coordination foundation for the graceful project handoff (§8.3):
the app and Claude share one active-project + activity view. User actions are
recorded as
actor:user, Claude's asactor:claude, so each side can see what the other did. - Affects:
internal/activity(new),internal/service,internal/mcp(+test),cmd/server/main.go,components/activity-feed(new),components/repo-list,web/templates/{index,help}.html.
2026-09-20 — Slice 4: graceful project handoff (§8.3)
- What:
internal/activitygained a pending-switch model (RequestSwitch/PendingSwitch/AckSwitch/CancelSwitch);AckSwitchatomically sets the active project to the requested target and records aswitch-completedevent with Claude's summary. Service methods added. New MCP toolsget_pending_switchandack_switch(request is user-only — no MCP tool raises it). HTTP:GET/POST/DELETE /api/switch. New<handoff-bar>component: "Ask Claude to switch to ", the "waiting for a good stopping point" state with Cancel, and the completion notice;<activity-feed>also updates the active project onswitch-completed. Extended the MCP test to cover the full request→ack→clear flow. Help page + AGENT.md §8.3 updated. - Why: The headline feature — the user asks Claude to switch projects; Claude
finishes to a safe stopping point, then
ack_switchcompletes it and the app notifies the user over SSE. The switch is Claude-completed at a checkpoint, never app-forced (§1.4-class rule). - Affects:
internal/activity,internal/service,internal/mcp(+test),cmd/server/main.go,components/handoff-bar(new),components/activity-feed,web/templates/{index,help}.html,AGENT.md(§8.3). - Verified live: request → "waiting" → cancel, all over SSE with activity logging. The ack/completion path is covered by the test; its live ✅ notice needs the two new MCP tools, which appear after the next Claude Desktop restart.
2026-09-20 — Slice 5: Gitea forge — PRs + "Merge & clean up" (§8.4)
- What: New
internal/forge— provider-abstracted forge boundary with a Gitea impl (code.gitea.io/sdk/gitea), a remote-URL parser (ParseRemote, tested), and read+write ops:ListPullRequestsandMergeAndCleanup(squash-merge + delete the head branch, only when head/base share a repo). Service resolves a repo → owner/repo via its remotes (prefers origin) and records apr-mergedactivity event. New configGITEA_URL+GITEA_TOKEN(forge is nil/disabled without both). New MCP toolslist_prsandmerge_and_cleanup_pr(the merge tool's description tells Claude to confirm first, §1.4). HTTPGET /api/repo/prs,POST /api/repo/pr/merge. New<pr-list>component with a confirming "Merge & clean up" button; hidden when no forge is configured. - Why: The feature Thomas asked for — make PRs usable by merging and removing the branch in one tidy step, from the app or via Claude.
- Affects:
internal/forge(new, +test),internal/config,internal/service,internal/mcp,cmd/server/main.go,components/pr-list(new),web/templates/{index,help}.html,.env.example,go.mod. - Not yet live-tested: needs
GITEA_URL+GITEA_TOKENset and a real PR; build/vet/tests pass and the parser is unit-tested. A real merge is irreversible — will only run one against a PR Thomas designates, with confirmation.
2026-09-20 — Forge live-tested (Merge & clean up)
- What: With
GITEA_URL+GITEA_TOKENset, verified end-to-end against git.nilles.net: created an isolated throwaway PR via the Gitea API (on a dedicated base branch somainwas untouched), listed it throughGET /api/repo/prs, then ranPOST /api/repo/pr/merge→{merged:true, branchDeleted:true}; confirmed the branch was gone (404), the PR list emptied, and the feed loggedpr-merged. Cleaned up the base branch afterward. - Why: Prove the write path with real auth before relying on it.
- Affects: none (runtime verification only; no code change).
2026-09-20 — Slice 6: right-click command menu + git write actions (§6)
- What: git boundary gained
Pull/Push/Commit/DiscardAll(the last is §1.4-destructive). Scanner gotRefreshRepo(single-repo re-scan). Service gainedGitFetch/GitPull/GitPush/GitCommit/GitDiscard— each records agit-*activity event (ok/failed) and refreshes the repo after success;service.Newtakes a refresh hook. New HTTPPOST /api/repo/git {path, op, message?}. New<repo-menu>overlay (plain-language commands: Get latest, Publish, Check for updates, Save my work…, Set as active project, Ask Claude to switch here, Copy path, and the confirmed Discard all changes…);<repo-list>emitsrepo:contextmenuon right-click. Addedinternal/servicetest covering commit/discard on a temp repo. - Why: The GUI-first reason the app exists (§0) — run git in plain language without a terminal. Logic lives in the shared service (§1.7) so the same ops can be exposed to Claude via MCP next.
- Affects:
internal/git,internal/repos,internal/service(+test),cmd/server/main.go,components/repo-menu(new),components/repo-list,web/templates/{index,help}.html. - Next: expose these git ops as MCP tools so Claude can run them too.