Building from source¶
You only need this to work on Costas itself. To use it, install the release.
Costas is C# on .NET 10 with Avalonia for the UI. Decoding is done by WSJT-X's jt9 and radio control by Hamlib's
rigctld, both run as child processes. The design documents are in
docs/ in the repository.
Prerequisites¶
- The .NET 10 SDK.
jt9and Hamlib. Fetch them intothird_party/with:- Windows:
pwsh third_party/fetch.ps1(needs 7-Zip onPATHto unpack the WSJT-X installer) - Linux:
third_party/fetch.sh(uses the distribution packageswsjtxandlibhamlib-utils)
- Windows:
Build, test, run¶
dotnet build
dotnet test
dotnet run --project src/Ft8Client.App
Run with no radio, replaying the sample recordings, with a simulated station that answers your calls:
dotnet run --project src/Ft8Client.App -- --simulate samples/ft8 --simulate-partner
Simulation never keys a radio, never uploads spots and does not write the decode journal or WAV files. The window
title says simulation. Add --home <folder> to use a separate data folder, so testing does not touch your real
log and settings.
Decode one recording through jt9:
dotnet run --project tools/Ft8Client.DecodeCli -- samples/ft8/210703_133430.wav
--keep-running decodes every file through one jt9 that stays running, as the app does, so a portable call heard
in one file resolves in the next. --live also replays each FT8 file against the real slot clock and prints when the
early pass and the full decode finished, which is the way to measure decode speed on your PC:
dotnet run --project tools/Ft8Client.DecodeCli -- --live samples/ft8/210703_133430.wav samples/ft8/181201_180245.wav
Installer¶
scripts/build-installer.ps1 builds artifacts/Costas-Setup-<version>.exe with jt9 and Hamlib bundled. CI builds
it on every push. Releases are cut on demand: running the CI workflow on main from the Actions tab (CI > Run
workflow) publishes that build as a GitHub Release if it passes, and installed copies offer it as an update.
Release runs code-sign every unsigned .exe and .dll in the app, both installers and the uninstaller with
Microsoft's Artifact Signing (formerly Trusted Signing),
through scripts/sign.ps1. Signing turns on when the repository has these settings (Settings › Secrets and
variables › Actions):
| Kind | Name | Value |
|---|---|---|
| Variable | ARTIFACT_SIGNING_ENDPOINT |
The account's endpoint, for example https://wus2.codesigning.azure.net/ |
| Variable | ARTIFACT_SIGNING_ACCOUNT |
The Artifact Signing account name |
| Variable | ARTIFACT_SIGNING_PROFILE |
The certificate profile name |
| Secret | AZURE_TENANT_ID |
The Microsoft Entra tenant ID |
| Secret | AZURE_CLIENT_ID |
The app registration's client ID |
| Secret | AZURE_CLIENT_SECRET |
The app registration's client secret |
The app registration needs the Artifact Signing Certificate Profile Signer role on the certificate profile.
Without ARTIFACT_SIGNING_ACCOUNT a release goes out unsigned, with a warning on the run; test and pull-request
builds are never signed. A signed release run fails rather than publish an unsigned installer.
This manual¶
The manual is in manual/, built with MkDocs and the Material theme, and published to
GitHub Pages by .github/workflows/manual.yml on every push to main. To preview it locally:
pip install mkdocs-material
mkdocs serve
Screenshots in manual/images/ were taken from the app running in simulation under a virtual display
(Xvfb), so they show real screens with recorded band activity.