Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
bf52db7
style: apply modern triple-A visual system and responsive foundation
capjan Nov 3, 2026
100a266
feat(ui): implement modern shell layout, remove double breadcrumbs an…
capjan Nov 3, 2026
8aff8a1
feat(ui): add channel tags, command pills and responsive mobile fixes
capjan Nov 3, 2026
91669f6
feat(ui): implement instant client-side filtering, command palette an…
capjan Nov 3, 2026
90a01ce
fix(ui): remove redundant filter button and tools count badge
capjan Nov 3, 2026
c9c6eea
feat(ui): add 1-click copy affordance for sha512 checksums
capjan Nov 3, 2026
28d0779
feat(preflight): implement interactive pre-flight check and system di…
capjan Nov 3, 2026
2c02e91
feat(preflight): make preflight fullscreen, add gradient check and sk…
capjan Nov 3, 2026
40f176a
feat(ui): dynamically show preflight in sidebar only when issues exis…
capjan Nov 3, 2026
2876a92
feat(preflight): separate sdk and runtime steps with setup actions an…
capjan Nov 3, 2026
720e529
feat(versions): implement versions hub channel cards and detail drawer
capjan Nov 3, 2026
1d5929c
feat(versions): align versions hub and detail drawer with v2 redesign
capjan Nov 3, 2026
417e018
feat(ui): complete v2 redesign across overview, tools,dialogs, and se…
capjan Nov 3, 2026
bd1d14c
feat(tools): polish tools table, add-tool sheet defaults, and keyboar…
capjan Nov 3, 2026
db5680e
feat(ui): polish v2 redesign visuals, light mode drawer, timeline and…
capjan Nov 3, 2026
813b241
feat(ui): complete versions drawer reflow, tool context menus, and re…
capjan Nov 3, 2026
705523e
fix(ui): resolve table overflow, drawer header overlap, timeline clip…
capjan Nov 3, 2026
1b00b84
feat(versions): complete channel patch indicators, detail drawer pack…
capjan Nov 4, 2026
efce7e1
feat(versions): replace inline All releases tab with Install .NET sid…
capjan Nov 4, 2026
32c31ef
feat(tools): add tool logos, descriptions, detail drawer, and UI polish
capjan Nov 4, 2026
07e27a8
feat(ui): add Latest install filter, live NuGet tool metadata, and si…
capjan Nov 4, 2026
158d112
feat(ui): group install channels, add tool update actions, and unify …
capjan Nov 4, 2026
80980f7
fix(ui): prevent page scroll when toggling version kind filter pills
capjan Nov 4, 2026
435802b
feat(ui): align tool remove column, add update all actions, and suppo…
capjan Nov 4, 2026
4fd3386
feat(ui): add smart cleanup modal, 3-state appearance switch, and res…
capjan Nov 4, 2026
a6b8c24
feat(ui): compute support status from the release catalog and confirm…
capjan Nov 4, 2026
e6a8459
feat(ui): calm the normal state with a token design system and one fi…
capjan Nov 4, 2026
d201b71
feat(ui): make every control work without JavaScript and at desktop w…
capjan Nov 4, 2026
f273b01
test(ui): guard the design with screenshot baselines and fixed fixtures
capjan Nov 4, 2026
c6af2a3
feat(ui): refine layout, refresh after installs and tool installation…
capjan Nov 4, 2026
ea7faf9
fix(versions): remove several versions with one administrator approval
capjan Nov 4, 2026
4339c53
fix(ui): keep the navigation compact in narrow windows and show tool …
capjan Nov 4, 2026
80162f2
feat(settings): add macOS, GitHub and Codex color palettes
capjan Nov 4, 2026
5931949
feat(settings): make the macOS palette follow the system accent color
capjan Nov 4, 2026
b541475
chore: set the version to 0.2.0
capjan Nov 4, 2026
a9b794e
test(ui): allow machines without the uninstall tool in the install sh…
capjan Nov 4, 2026
33cc223
fix(overview): keep timeline bars of channels that are not installed …
capjan Nov 4, 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
11 changes: 9 additions & 2 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@
"version": 1,
"isRoot": true,
"tools": {
"markdownutil": {
"version": "4.8.0",
"mdu": {
"version": "6.0.1",
"commands": [
"mdu"
],
"rollForward": false
},
"dotnet-ef": {
"version": "10.0.14",
"commands": [
"dotnet-ef"
],
"rollForward": false
}
}
}
15 changes: 11 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
inputs:
version:
type: string
default: '0.1.0'
default: '0.2.0'

permissions:
contents: read
Expand Down Expand Up @@ -62,7 +62,7 @@ jobs:
- name: Publish Native AOT executable
shell: bash
env:
PACKAGE_VERSION: ${{ inputs.version || '0.1.0' }}
PACKAGE_VERSION: ${{ inputs.version || '0.2.0' }}
run: dotnet publish src/DotnetCockpit/DotnetCockpit.csproj --configuration Release --runtime ${{ matrix.rid }} --self-contained true -p:PublishAot=true -warnaserror:IL2026,IL2104,IL3050,IL3053 -p:Version="$PACKAGE_VERSION" --output artifacts/native
- name: Smoke test published executable
run: node scripts/smoke.mjs artifacts/native/${{ matrix.exe }}
Expand All @@ -73,6 +73,13 @@ jobs:
- name: Test UI against native backend
if: runner.os == 'Linux'
run: npm --prefix ui run test:browser
- name: Install browser for screenshot comparison
if: matrix.os == 'macos-latest'
working-directory: ui
run: npx playwright install chromium
- name: Compare screenshots
if: matrix.os == 'macos-latest'
run: npm --prefix ui run test:visual
- name: Archive native executable
shell: pwsh
env:
Expand Down Expand Up @@ -116,11 +123,11 @@ jobs:
npm --prefix ui run build
- name: Pack .NET tool
env:
PACKAGE_VERSION: ${{ inputs.version || '0.1.0' }}
PACKAGE_VERSION: ${{ inputs.version || '0.2.0' }}
run: dotnet pack src/DotnetCockpit/DotnetCockpit.csproj --configuration Release -p:Version="$PACKAGE_VERSION" --output artifacts/packages
- name: Install and smoke test tool package
env:
PACKAGE_VERSION: ${{ inputs.version || '0.1.0' }}
PACKAGE_VERSION: ${{ inputs.version || '0.2.0' }}
run: |
dotnet tool install dotnet-cockpit --tool-path "$PWD/artifacts/tool" --add-source "$PWD/artifacts/packages" --version "$PACKAGE_VERSION"
PATH="$PWD/artifacts/tool:$PATH" dotnet cockpit --help
Expand Down
8 changes: 6 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Repository guide

.NET Cockpit is a local browser application: a Native AOT ASP.NET Core Minimal API host renders HTML in C#. Fluent UI Web Components enhance the server-rendered page; React is not used.
.NET Cockpit is a local browser application: a Native AOT ASP.NET Core Minimal API host renders HTML in C#. A small module script enhances the server-rendered page; no UI framework is used.

- Keep native startup independent of an installed .NET runtime or SDK. The optional managed .NET tool is an additional distribution.
- Build browser assets before compiling .NET: `npm --prefix ui ci` and `npm --prefix ui run build`. Node is only a build/test dependency.
Expand All @@ -11,8 +11,12 @@
- Inventory reflects the selected dotnet host on PATH. Distinguish a missing host from a failed query.
- `/tools` lists user-global tools and local manifest declarations for Cockpit's startup working directory. Do not scan arbitrary projects or imply that a listed local package has been restored. Keep the two scopes independent when a query fails.
- Tool mutations run only through explicit local forms: search results install globally until a local manifest exists, initialized workspaces offer global/local targets, installed rows offer uninstall, and the current workspace can remove its own local manifest. Keep POST actions scoped to the startup working directory and preserve server-rendered behavior without JavaScript; never remove an inherited parent manifest.
- Every mutation asks first through `ConfirmActions`: the shared dialog with JavaScript, the `/confirm` page without it.
- Support dates, end-of-life state and the timeline come only from the release catalog. When it is unavailable, say the status is unknown instead of guessing.
- Preferences live in `SettingsStore`, not browser storage, because the free port changes the origin on every launch.
- Styles use the tokens in `ui/src/styles/tokens.css`: six type sizes, three radii, semantic colors. Add no literal colors, other sizes or `!important`. Palettes in `palettes.css` override color roles only and must pass the contrast test in both themes.
- `/setup` may detect, install, update, and remove only the official global `dotnet-core-uninstall` installation for Windows and macOS. Global installs use the platform paths and must surface administrator approval. Release discovery must follow every page of the official GitHub Releases API, filter stable releases to those with a compatible asset, and treat an incomplete/failed response as unavailable rather than presenting a partial list. Do not download arbitrary URLs or claim Linux support.
- The CLI's bracketed path is a base directory. Display `InstallationPath` (base path plus version) for an individual SDK or runtime; retain `Path` in the JSON API for compatibility.
- Run `dotnet test DotnetCockpit.sln`, publish the native binary, run `node scripts/smoke.mjs <binary>`, and run the browser tests for UI changes.
- Run `dotnet test DotnetCockpit.sln`, publish the native binary, run `node scripts/smoke.mjs <binary>`, and run the browser tests for UI changes. For visual changes also run `npm --prefix ui run test:visual`; after an intended change, update the baselines with `npm --prefix ui run test:visual:update` and review them.
- Use `gh` for GitHub operations. Commit messages follow Conventional Commits and contain no AI attribution.
- Keep changes focused and avoid speculative abstractions or functionality.
6 changes: 4 additions & 2 deletions docs/Features.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ The **.NET Tools** page keeps the two scopes separate:

A local declaration is not proof that its package has been restored. Cockpit never scans unrelated projects. Tool changes are deliberate POST actions: search results install globally until the current workspace has a manifest; initialized workspaces can choose global or local installation; installed rows can uninstall; and Cockpit only removes a manifest owned by its own startup directory.

## Setup
## Settings

On macOS and Windows, Cockpit can detect, install, update, and remove the official global `dotnet-core-uninstall` installation. These operations request administrator approval where the platform requires it. Linux is not supported by the official tool.

On macOS, **Setup** also lists official `.pkg` installers for the host architecture. The catalog comes from Microsoft's release metadata and includes SDKs and standalone .NET Runtimes, release channels, support status, release dates, SHA-512 checksums, and release CVEs where Microsoft provides them. Downloading a package is separate from installing it: open the downloaded package in macOS Installer to complete installation.
On macOS, **Versions → Install .NET** lists official `.pkg` installers for the host architecture. The catalog comes from Microsoft's release metadata and includes SDKs and standalone .NET Runtimes, release channels, support status, release dates, SHA-512 checksums, and release CVEs where Microsoft provides them. Downloading a package is separate from installing it: open the downloaded package in macOS Installer to complete installation.

The SDK installer includes the matching .NET Runtime and ASP.NET Core Runtime. Use the standalone Runtime package only when you do not need the SDK.

The colors can be switched under **Settings** between the Cockpit, macOS, GitHub and Codex styles, each in light and dark. On macOS, the macOS style follows the accent color from System Settings.
2 changes: 1 addition & 1 deletion docs/Getting-Started.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ The .NET tool is optional. Use the native download on machines without an SDK.

1. Open **Installations** to inspect the SDKs and runtimes reported by the selected `dotnet` host.
2. Open **.NET Tools** to see global tools and local manifest declarations for the directory where Cockpit was launched.
3. Open **Setup** to manage the supported uninstall tool or download an official macOS SDK or runtime package.
3. Open **Settings** to manage the supported uninstall tool, or **Versions → Install .NET** to download an official macOS SDK or runtime package.

Restart Cockpit after changing its inherited `PATH` or installing a new `dotnet` host.
6 changes: 5 additions & 1 deletion docs/Privacy-and-Safety.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@ Cockpit reads the .NET host selected by its own `PATH`, the output of the standa

## Network requests

The application starts without an internet connection. The Setup page requests release metadata only when it needs current installer or uninstall-tool release information. Installer links target official Microsoft-hosted files; uninstall-tool release discovery uses the official GitHub releases API.
The application starts without an internet connection. The Settings page requests release metadata only when it needs current installer or uninstall-tool release information. Installer links target official Microsoft-hosted files; uninstall-tool release discovery uses the official GitHub releases API.

## Explicit changes

Cockpit never changes .NET installations or tool manifests during inventory. Mutations require a local form submission and are scoped to the startup directory. An inherited parent tool manifest is displayed but cannot be removed from Cockpit.

Before removing an installation, confirm that it is not needed by another application. Cockpit surfaces the command result, but the underlying platform installer and .NET tooling remain authoritative.

## Local files

Cockpit stores your appearance and pre-flight choices in `settings.json` in the `dotnet-cockpit` folder of your user configuration directory. Delete the file to reset them.
2 changes: 1 addition & 1 deletion scripts/smoke.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ await runWithoutRepositoryFiles(process.env, async (data, html, get, url) => {
const setupPage = await get('setup');
assert.equal(setupPage.status, 200);
const setupHtml = await setupPage.text();
assert.ok(setupHtml.includes('<h1>Setup</h1>'));
assert.ok(setupHtml.includes('<h1>Settings</h1>'));
assert.ok(setupHtml.includes('.NET Uninstall Tool'));
assert.ok(setupHtml.includes('learn.microsoft.com/en-us/dotnet/core/additional-tools/uninstall-tool-overview'));
const invalidAction = await fetch(new URL('tools/install', url), {
Expand Down
4 changes: 4 additions & 0 deletions src/DotnetCockpit/AppJsonContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ namespace DotnetCockpit;
[JsonSerializable(typeof(InstallationSnapshot))]
[JsonSerializable(typeof(HealthStatus))]
[JsonSerializable(typeof(ToolsSnapshot))]
[JsonSerializable(typeof(ToolSearch))]
[JsonSerializable(typeof(AppSettings))]
[JsonSerializable(typeof(SystemAccentStatus))]
internal partial class AppJsonContext : JsonSerializerContext;

internal sealed record HealthStatus(string Status);
internal sealed record SystemAccentStatus(string? Accent);
Loading
Loading