Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ jobs:
-Version '${{ steps.version.outputs.display }}' `
-FfmpegPath $env:FFMPEG_PATH

- name: Build CLI release package
shell: pwsh
run: |
./packaging/build-cli-package.ps1 `
-Version '${{ steps.version.outputs.display }}'

# Sign the published exe if a code-signing certificate is available.
# Store your PFX as a base64 secret: SIGNING_CERT_B64
# Store the PFX password as: SIGNING_CERT_PASSWORD
Expand Down Expand Up @@ -156,12 +162,15 @@ jobs:
tag_name: v${{ steps.version.outputs.display }}
files: |
installer/output/Pointframe-${{ steps.version.outputs.display }}-x64-Setup.exe
packaging/output/Pointframe.Cli-${{ steps.version.outputs.display }}-win-x64.zip
packaging/output/Pointframe.Cli-${{ steps.version.outputs.display }}-win-x64.zip.sha256
packaging/output/Pointframe.Mcp-${{ steps.version.outputs.display }}-win-x64.mcpb
packaging/output/Pointframe.Mcp-${{ steps.version.outputs.display }}-win-x64.mcpb.sha256
packaging/output/Pointframe.Mcp-${{ steps.version.outputs.display }}-win-x64.server.json
body: |
Pointframe ${{ steps.version.outputs.display }}

- Installer refresh and maintenance release.
- Includes a standalone Pointframe CLI for whole-monitor screenshots.
- Includes the Pointframe MCPB stdio server bundle and registry metadata.
- For the full list of commits, see Compare in this release page.
17 changes: 17 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,23 @@ jobs:
--nologo
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

- name: Publish CLI
shell: pwsh
run: |
$publishDir = Join-Path $env:GITHUB_WORKSPACE 'Pointframe.Cli\bin\publish\win-x64'
dotnet publish Pointframe.Cli/Pointframe.Cli.csproj `
--configuration Release `
--runtime win-x64 `
--self-contained true `
/p:PublishSingleFile=true `
/p:PublishReadyToRun=false `
/p:EnableCompressionInSingleFile=true `
/p:PublishTrimmed=false `
/p:PublishDir="$publishDir\" `
--no-restore `
--nologo
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

- name: MCP stdio smoke test
shell: pwsh
run: >
Expand Down
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,26 @@ winget install DimitarRadenkov.Pointframe

You can complete your first capture workflow in under a minute.

## Pointframe CLI

Each GitHub Release includes `Pointframe.Cli-<version>-win-x64.zip`, a self-contained
Windows CLI for monitor discovery and whole-monitor PNG screenshots. Extract the ZIP
and run `Pointframe.Cli.exe`; the Pointframe desktop app, the .NET runtime, and the
.NET SDK are not required.

The CLI requires an interactive Windows desktop session. It cannot capture a user's
desktop from a Windows service (session 0).

```powershell
.\Pointframe.Cli.exe displays
.\Pointframe.Cli.exe capture --monitor '\\.\DISPLAY1'
```

Use the exact `monitorName` emitted by `displays`. A successful command writes JSON
to standard output and exits with code `0`; invalid arguments exit with code `2`, and
capture failures exit with code `1`. Screenshots and their metadata sidecars are saved
under `%LOCALAPPDATA%\Pointframe\Screenshots`.
Comment on lines +66 to +69

## Pointframe MCP Server

Pointframe also ships a standalone MCP server for agents that need to inspect the Windows desktop and produce verifiable screenshot or recording artifacts. The MCP server uses `Pointframe.Engine` directly; it does not start the Pointframe tray application, create a WPF overlay, or require the full Pointframe installer.
Expand Down
6 changes: 4 additions & 2 deletions docs/knowledge-base/knowledge-base.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,11 @@ Text and Callout edit in a live `TextBox`; `LostFocus` converts it to a `TextBlo

**Packaging and configuration.**

`Pointframe.Cli` is released as a self-contained, single-file `win-x64` ZIP with a SHA-256 checksum. `packaging/build-cli-package.ps1` publishes it and creates the versioned archive. Users extract it and run `Pointframe.Cli.exe`; it has no WPF application or .NET runtime prerequisite.

`Pointframe.Mcp` is published self-contained for `win-x64`. `packaging/build-mcp-package.ps1` copies the published executable and a supplied `ffmpeg.exe` into a versioned legacy ZIP and MCPB bundle. It also emits a SHA-256 checksum and MCP Registry `server.json` metadata pointing at the GitHub Release MCPB asset. The standalone package contains no WPF application. VS Code and other MCP clients launch the executable as a local stdio server.

CI publishes the MCP executable and runs `packaging/test-mcp-stdio.ps1`, which verifies the initialize handshake and expected tool list without starting WPF. CD attaches the MCPB, checksum, and registry metadata to the versioned GitHub Release. The bundle remains Windows-only and requires an interactive desktop session for capture and recording.
CI publishes the CLI and MCP executables and runs `packaging/test-mcp-stdio.ps1`, which verifies the initialize handshake and expected tool list without starting WPF. CD attaches the CLI ZIP/checksum plus the MCPB, checksum, and registry metadata to the versioned GitHub Release. Both standalone hosts remain Windows-only and require an interactive desktop session for capture and recording.

**Invariants.**

Expand All @@ -279,7 +281,7 @@ CI publishes the MCP executable and runs `packaging/test-mcp-stdio.ps1`, which v

**Tests.** `Pointframe.Tests/Cli/CliApplicationTests.cs`, `Pointframe.Tests/Mcp/DirectCaptureServiceTests.cs`, `Pointframe.Tests/Mcp/DirectRecordingMcpServiceTests.cs`, and `Pointframe.Tests/Engine/DirectRecordingServiceTests.cs`. Protocol smoke coverage is in `packaging/test-mcp-stdio.ps1`.

**Files.** `Pointframe.Cli/Program.cs`, `Pointframe.Cli/Application/CliApplication.cs`, `Pointframe.Cli/Commands/CliCommandParser.cs`, `Pointframe.Cli/Commands/CliCommand.cs`, `Pointframe.Mcp/Program.cs`, `Pointframe.Mcp/Tools/PointframeMcpTools.cs`, `Pointframe.Mcp/Resources/PointframeMcpResources.cs`, `Pointframe.Mcp/Services/DirectRecordingMcpService.cs`, `Pointframe.Mcp/Mappers/McpResponseMapper.cs`, `Pointframe.Mcp/Models/DirectRecordingResponse.cs`, `Pointframe.Mcp/Models/McpToolResponses.cs`, `Pointframe.Engine/Capture/Services/DirectCaptureService.cs`, `Pointframe.Engine/Capture/Services/DisplayCaptureEngine.cs`, `Pointframe.Engine/Capture/Models/DirectCaptureModels.cs`, `Pointframe.Engine/Recording/Services/DirectRecordingService.cs`, `Pointframe.Engine/Recording/Services/RawFrameRecordingPipeline.cs`, `Pointframe.Engine/Recording/Services/FfmpegDirectVideoWriter.cs`, `Pointframe.Engine/Recording/Models/DirectRecordingModels.cs`, `Pointframe/Services/Recording/ArtifactMetadataService.cs`, `packaging/build-mcp-package.ps1`, `packaging/test-mcp-stdio.ps1`, `.github/workflows/ci.yml`, `.github/workflows/cd.yml`.
**Files.** `Pointframe.Cli/Program.cs`, `Pointframe.Cli/Application/CliApplication.cs`, `Pointframe.Cli/Commands/CliCommandParser.cs`, `Pointframe.Cli/Commands/CliCommand.cs`, `Pointframe.Mcp/Program.cs`, `Pointframe.Mcp/Tools/PointframeMcpTools.cs`, `Pointframe.Mcp/Resources/PointframeMcpResources.cs`, `Pointframe.Mcp/Services/DirectRecordingMcpService.cs`, `Pointframe.Mcp/Mappers/McpResponseMapper.cs`, `Pointframe.Mcp/Models/DirectRecordingResponse.cs`, `Pointframe.Mcp/Models/McpToolResponses.cs`, `Pointframe.Engine/Capture/Services/DirectCaptureService.cs`, `Pointframe.Engine/Capture/Services/DisplayCaptureEngine.cs`, `Pointframe.Engine/Capture/Models/DirectCaptureModels.cs`, `Pointframe.Engine/Recording/Services/DirectRecordingService.cs`, `Pointframe.Engine/Recording/Services/RawFrameRecordingPipeline.cs`, `Pointframe.Engine/Recording/Services/FfmpegDirectVideoWriter.cs`, `Pointframe.Engine/Recording/Models/DirectRecordingModels.cs`, `Pointframe/Services/Recording/ArtifactMetadataService.cs`, `packaging/build-cli-package.ps1`, `packaging/build-mcp-package.ps1`, `packaging/test-mcp-stdio.ps1`, `.github/workflows/ci.yml`, `.github/workflows/cd.yml`.

**Files.** `Pointframe/Services/Recording/ScreenRecordingService.cs`, `Pointframe/Services/Recording/IScreenRecordingService.cs`, `Pointframe/Services/Recording/IRecordingRedactionSession.cs`, `Pointframe/Services/Recording/RecordingRedactionSession.cs`, `Pointframe/Services/Recording/IRecordingEventTrack.cs`, `Pointframe/Services/Recording/RecordingEventTrack.cs`, `Pointframe/Services/Recording/VideoWriterFactory.cs`, `Pointframe/Services/Recording/FFMpegVideoWriter.cs`, `Pointframe/Services/Recording/FfmpegResolver.cs`, `Pointframe/Models/RecordingSessionGeometry.cs`, `Pointframe/Views/RecordingOverlayWindow.xaml.cs`, `Pointframe/Views/OverlayWindow.Recording.cs`, `Pointframe/Views/OverlayWindow.RecordingHud.cs`, `Pointframe/Views/OverlayWindow.RecordingAnnotation.cs`, `Pointframe/Views/CountdownWindow.xaml.cs`, `Pointframe/ViewModels/RecordingHudViewModel.cs`, `Pointframe/Services/Recording/RecordingHudCoordinator.cs`, `Pointframe/Services/Recording/RecordingAnnotationSurfaceCoordinator.cs`, `Pointframe/Services/Recording/RecordingMousePassthroughCoordinator.cs`, `Pointframe/Services/Recording/RecordingOverlayNativeInterop.cs`, `Pointframe/Services/Recording/RecordingCursorEffectsService.cs`, `Pointframe/Services/Recording/RecordingMicrophoneSession.cs`, `Pointframe/Services/Infrastructure/MicrophoneDeviceService.cs`, `Pointframe/Services/Recording/GifExportService.cs`, `Pointframe/Services/Recording/VideoTrimService.cs`, `Pointframe/ViewModels/TrimViewModel.cs`, `Pointframe/Services/Recording/WatermarkTokenResolver.cs`, `Pointframe/Services/Messaging/RecordingCompletedMessage.cs`, `Pointframe/Services/Messaging/TrimRecordingRequestedMessage.cs`.

Expand Down
50 changes: 50 additions & 0 deletions packaging/build-cli-package.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
[CmdletBinding()]
param(
[string]$Version = "1.0.0"
)

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

$repositoryRoot = Split-Path $PSScriptRoot -Parent
$projectPath = Join-Path $repositoryRoot "Pointframe.Cli\Pointframe.Cli.csproj"
$publishDirectory = Join-Path $repositoryRoot "Pointframe.Cli\bin\publish\win-x64"
$packageDirectory = Join-Path $repositoryRoot "packaging\output\Pointframe.Cli-$Version-win-x64"
$archivePath = "$packageDirectory.zip"
$checksumPath = "$archivePath.sha256"

dotnet publish $projectPath `
--configuration Release `
--runtime win-x64 `
--self-contained true `
/p:PublishSingleFile=true `
/p:PublishReadyToRun=false `
/p:EnableCompressionInSingleFile=true `
/p:PublishTrimmed=false `
/p:PublishDir="$publishDirectory\" `
/p:Version=$Version `
--nologo
if ($LASTEXITCODE -ne 0)
{
exit $LASTEXITCODE
}

if (Test-Path $packageDirectory)
{
Remove-Item $packageDirectory -Recurse -Force
}

New-Item -ItemType Directory -Path $packageDirectory -Force | Out-Null
Copy-Item (Join-Path $publishDirectory "*") $packageDirectory -Recurse -Force

if (Test-Path $archivePath)
{
Remove-Item $archivePath -Force
}

Compress-Archive -Path (Join-Path $packageDirectory "*") -DestinationPath $archivePath
$sha256 = (Get-FileHash $archivePath -Algorithm SHA256).Hash.ToLowerInvariant()
Set-Content $checksumPath "$sha256 $(Split-Path $archivePath -Leaf)" -Encoding utf8NoBOM

Write-Host "CLI ZIP ready: $archivePath"
Write-Host "CLI checksum ready: $checksumPath"
Loading