Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
7148258
feat(ui): enable Changes/commit tab in the timeline webview
AlyNotMe Sep 3, 2026
2340496
fix(ui): keep branch dropdown on-screen in short containers
AlyNotMe Sep 3, 2026
e608ba8
feat(timeline): rebuild the view as a self-contained GitHub Desktop l…
AlyNotMe Sep 3, 2026
f538082
fix(timeline): stop tab panes overlapping; collapse diff pane when idle
AlyNotMe Sep 3, 2026
c4ffd18
feat(timeline): GitHub account avatar + keep file list visible
AlyNotMe Sep 3, 2026
65bc993
style(timeline): compact density pass so the file list has room
AlyNotMe Sep 3, 2026
9fc874e
fix(branches): never check out a remote ref directly (detached HEAD)
AlyNotMe Sep 3, 2026
c77d854
fix(remote-status): detect upstream via rev-parse @{upstream}
AlyNotMe Sep 3, 2026
b1e42c2
fix(toolbar): default sync cell to Fetch unless positively unpublished
AlyNotMe Sep 3, 2026
d7b2dc2
chore: remove dead React timeline superseded by vanilla webview
AlyNotMe Sep 8, 2026
039a24a
refactor(timeline): split the message handler into SOLID services
AlyNotMe Sep 8, 2026
3538b20
style(timeline): density pass on the toolbar sync cell
AlyNotMe Sep 8, 2026
9561980
feat(timeline): restore commit context menu, new-branch & load-more
AlyNotMe Sep 8, 2026
5313534
refactor(timeline): trim dead interface types
AlyNotMe Sep 8, 2026
26f3d1e
style(timeline): rework the webview to match GitHub Desktop
AlyNotMe Sep 8, 2026
f193ef5
feat(timeline): undo, amend, co-authors, conflict resolution & stash
AlyNotMe Sep 8, 2026
4f59538
chore: release 1.2.0
AlyNotMe Sep 8, 2026
bb36aeb
fix(timeline): compact toolbar + restore scroll to the commit box
AlyNotMe Sep 8, 2026
0ad0a40
fix(timeline): single scroll on the Changes pane, tighter chrome
AlyNotMe Sep 8, 2026
df1562b
Merge: SOLID backend rewrite + GitHub Desktop UI + git-flow features
AlyNotMe Sep 9, 2026
c9d6c55
chore: remove History Explorer + dead declarations
AlyNotMe Sep 9, 2026
bf63277
feat(timeline): force-push and branch comparison
AlyNotMe Sep 9, 2026
ce3fc6b
feat(timeline): match the real GitHub Desktop layout (from Figma rede…
AlyNotMe Sep 9, 2026
29e1108
style(timeline): compact toolbar again — the panel is short on height
AlyNotMe Sep 9, 2026
3cf7cf4
fix(git): auth via -c http.extraheader; repository picker
AlyNotMe Sep 9, 2026
a71da64
feat(timeline): switching repository opens its folder in VS Code
AlyNotMe Sep 9, 2026
93e3136
fix(timeline): commit box is a flex footer, not position:sticky
AlyNotMe Sep 9, 2026
6adf944
fix(timeline): commit form is part of the single Changes scroll
AlyNotMe Sep 9, 2026
bbec639
feat(timeline): branch dropdown ordered most-recently-used
AlyNotMe Sep 9, 2026
4339ff9
refactor: drop React/MUI commit-detail panel, render it in the timeli…
AlyNotMe Sep 9, 2026
a3bca19
feat(timeline): native-style diff renderer in the right pane
AlyNotMe Sep 9, 2026
8243494
feat(timeline): list and check out pull requests from the branch drop…
AlyNotMe Sep 9, 2026
0308877
chore: trim src/webviews/tsconfig.json to silence TS7 deprecations
AlyNotMe Sep 9, 2026
5176870
feat(branches): merge UI + confirm before merging the default branch
AlyNotMe Sep 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 94 additions & 84 deletions docs/overview.md
Original file line number Diff line number Diff line change
@@ -1,90 +1,100 @@
# GitHub Desktop for VS Code � Overview
# GitHub Desktop for VS Code — Overview

This document describes the structure, capabilities, and data flow for the GitHub Desktop-inspired VS Code extension contained in this workspace.
A VS Code extension that brings a GitHub Desktop-style workflow into the editor:
a Changes/History panel with a commit box, branch and sync controls, commit
actions, conflict resolution and stash management, plus multi-account GitHub
sign-in.

## Goals
- Provide a GitHub Desktop-like workflow without leaving VS Code.
- Allow simultaneous authentication with multiple GitHub accounts and easy context switching.
- Reuse existing local credentials (GitHub CLI) whenever possible to avoid pasting tokens.
- Simplify cloning, opening, and tracking repositories from the editor.
- Offer a lightweight entry point for issue creation and future GitHub interactions.
## Activation

## Extension Activation
The extension activates on startup (`onStartupFinished`), whenever one of the contributed commands runs, or when the GitHub Desktop views are opened. Activation wires up managers, registers commands, syncs workspace repositories, and initializes the panel UI.
`activate()` (`src/extension.ts`) runs on `onStartupFinished`. It:

- creates `AccountManager` and `RepositoryManager` (state in `globalState`,
tokens in `SecretStorage`);
- registers the **Accounts** and **Repositories** tree views, and the
**History** webview view (`githubDesktop.timeline`);
- registers the sign-in / account / clone / open / issue / refresh commands;
- scans workspace folders for a `.git` dir and tracks the repositories it finds.

## Surfaces

| Surface | Provider | Notes |
|---|---|---|
| **History** webview | `TimelineViewProvider` | The main panel. Self-contained HTML/CSS/JS (no bundle) generated by `WebviewHtmlService`; all logic runs through `TimelineController`. |
| **Commit detail** panel | `CommitDetailViewProvider` | Opened on demand as a `WebviewPanel`; React/MUI bundle (`out/webview/commit-detail.js`). |
| **Accounts** / **Repositories** trees | `AccountsProvider` / `RepositoriesProvider` | Plain `TreeDataProvider`s. |

## Timeline architecture (`src/webviews/timeline/`)

The webview and the extension host talk over `postMessage`. Messages are typed
discriminated unions in `messages.ts` (`InboundMessage` / `OutboundMessage`).

```ts
activate(context: vscode.ExtensionContext)
```
- Instantiates `AccountManager` and `RepositoryManager` using the extension's global state and secret storage.
- Boots the combined **Changes & History** webview alongside the Accounts and Repositories tree view providers.
- Registers command handlers for sign-in/out, account switching, repository cloning/opening, issue creation, and manual refresh.
- Focuses the custom activity bar container and reconciles workspace folders so repos with `.git` are listed immediately.

## Core Components

### AccountManager (`src/accountManager.ts`)
- Persists account metadata (`StoredAccount`) in global state.
- Stores personal access tokens (PATs) in VS Code Secret Storage under randomized keys.
- Attempts to reuse GitHub CLI (`gh auth token`) credentials before prompting for a PAT.
- Emits `onDidChangeAccounts` for tree providers or other features to react to changes.
- Provides helpers to fetch authenticated Octokit clients scoped to the active or selected account.

### RepositoryManager (`src/repositoryManager.ts`)
- Tracks cloned or opened repositories (`TrackedRepository`) in global state, including whether they are linked to a signed-in account.
- Guarantees unique entries per local path or remote URL and exposes `updateRepository` for metadata changes.
- Emits `onDidChangeRepositories` whenever the repository list mutates.

### TimelineViewProvider (`src/webviews/timelineView.ts`)
- Supplies the HTML/CSS/JS for the combined Changes & History panel with GitHub Desktop-style commit cards.
- Reads git status/log output via `simple-git`, formats commit cards, and renders file-level detail, inline diffs, and responds to interactions (file selection, refresh).
- Refreshes automatically when repositories change, when files are saved, or when the user triggers a manual refresh.

### Tree Data Providers (`src/treeViews/`)
- `AccountsProvider` renders the list of signed-in accounts and indicates which one is active.
- `RepositoriesProvider` surfaces tracked repositories (local or remote) and exposes quick entry points for cloning or opening projects.

### Commands (`contributes.commands` in `package.json`)
- `githubDesktop.signIn` / `githubDesktop.signOut` / `githubDesktop.switchAccount`
- `githubDesktop.cloneRepository` / `githubDesktop.openRepository`
- `githubDesktop.createIssue`
- `githubDesktop.refreshViews`

Each command is registered in `src/extension.ts` and depends on the managers above to read or mutate state.

## Authentication Flow
1. The extension tries `gh auth token`; if successful, the token is used immediately and stored securely.
2. If the CLI is unavailable, the user is prompted for a PAT (`repo`, `read:org`, `workflow`).
3. Octokit validates the token by requesting `GET /user`.
4. Account details are stored; tokens remain in Secret Storage.
5. The active account defaults to the newest signed-in account but can be changed via the switch command.

Tokens are never written to disk outside VS Code's secure storage. If secret storage removes a token (for example, due to a user action), the manager prunes the corresponding account on the next activation.

## Repository Detection Flow
1. On activation�and whenever workspace folders change�the extension scans each folder for a `.git` directory.
2. If a match is found, `simple-git` inspects remotes to derive the owner/name pair.
3. The repository is added to the global store (without requiring a clone) and linked to the active account if one is present.
4. Repositories without linked accounts can be associated later when issue creation or other account-dependent commands run.

## Data Persistence
- `context.globalState` keeps serialized lists of accounts and repositories.
- `context.secrets` retains PATs mapped to generated token keys.
- Both stores survive across VS Code sessions; tree views read from them during activation.

## UI Surface
- Activity bar container `githubDesktop` hosts the combined **Changes & History** webview and the **Accounts**/**Repositories** tree views (collapsed by default).
- Commit cards mimic GitHub Desktop styling with author/time metadata and highlight the currently selected entry.
- Selecting a commit displays a detail pane with aggregate stats and per-file changes (additions, deletions, status code).

## Extensibility Notes
- Add new GitHub workflows by requesting Octokit clients from `AccountManager`.
- Extend repository metadata by updating `TrackedRepository` and handling state migrations in `RepositoryManager`.
- Timeline templates can be extended by posting additional messages through `TimelineViewProvider`.

## Development Workflow
1. `npm install`
2. `npm run compile` (one-off build) or `npm run watch`
3. Launch the **Run Extension** debug configuration (see `.vscode/launch.json`).

Tests are not yet implemented. When adding tests, prefer VS Code's extension test harness and bind them in `package.json` scripts.
webview ──InboundMessage──▶ TimelineController
│ (composition root)
├─ MessageRouter Map<command, handler>, no switch
├─ RepositoryDataService read model → RepositorySnapshot
└─ write services:
WorkingTreeService stage / commit / amend / undo / discard / diff
SyncService fetch / pull / push / publish (+ conflict detect)
BranchService checkout / create / merge
CommitActionsService reset / checkout / revert / cherry-pick / branch-from / tag / view-on-GitHub
ConflictService markResolved / continue / abort
StashService push / apply / pop / drop
PullRequestService open compare page
DiffService commit detail / per-file patch
webview ◀─OutboundMessage── (services broadcast via WebviewChannel; a mutation
triggers Refresher.refresh() → a fresh snapshot)
```

### Ports and adapters

Services depend on small interfaces (`ports.ts`), never on `vscode` or
`simple-git` directly:

- `RepositoryContext` — the active repository
- `Notifier` — info/warn/error, confirm, prompt
- `Browser` — open external URLs
- `WebviewChannel` — post an `OutboundMessage`
- `Refresher` — recompute-and-broadcast (implemented by `TimelineController`)
- `GitClientFactory` — creates `simple-git` clients; `withAuth()` injects the
active account's token through ephemeral `GIT_CONFIG_*` env vars, so it is
**never written to `.git/config`**

VS Code implementations live in `adapters/vscode-adapters.ts`; the git factory
is `AccountGitClientFactory` (`src/core/git/git-authenticator.ts`).

### Read model

`RepositoryDataService.getSnapshot()` assembles one `RepositorySnapshot`
(changes, history page, branches + activity, remote status, tags, in-progress
operation, conflicted paths, `canUndo`, stashes) per refresh.
`TimelineViewProvider` debounces refreshes (400 ms) so a burst of file saves
triggers a single recompute.

## Authentication

`AccountManager` tries `gh auth token`, then VS Code's built-in GitHub auth,
then a manually entered PAT. Tokens live only in `SecretStorage`. Git network
operations get the token via `GitClientFactory.withAuth`.

## Build

- `npm run compile` — webpack bundles the extension to `dist/extension.js`
(the timeline webview HTML/JS is inlined here).
- `npm run build-webview` — Vite builds the React panels to `out/webview/`
(currently just `commit-detail.js`).
- `npm run package` — runs both, then `vsce package`.

## Extending

- New timeline command: add a member to `InboundMessage`, a method on the
relevant service (or a new service), and one `.on(...)` line in
`TimelineController`. The router and the rest of the services are untouched.
- New git read data: add a field to `RepositorySnapshot` and populate it in
`RepositoryDataService`, then broadcast it from `TimelineController.refresh()`.

## Not yet implemented

Force-push UI, branch comparison, PR list / checkout, CI status on commits,
repository context menu, tests.
Loading