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
10 changes: 10 additions & 0 deletions .github/badges/conformance.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 13 additions & 12 deletions .github/conformance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
# Criteria: https://github.com/trsdn/.github/blob/main/docs/repository-quality-standard.md
# Evidence: docs/self-assessment.md (only for results that aren't a clean pass)

standard_version: "1.11.1"
assessed_on: "2026-09-17"
state: "Needs work"
standard_version: "1.15.0"
assessed_on: "2026-09-20"
state: "Healthy"
evidence: "docs/self-assessment.md"

criteria:
B01: pass
B02: pass
B03: pass
B04: pass
B05: partial
B05: pass
B06: pass
B07: pass
B08: pass
Expand All @@ -33,12 +33,12 @@ criteria:
P05: pass
P06: pass
P07: pass
P08: partial
P08: pass
P09: partial
P10: pass
P11: pass
S01: pass
S02: pass
S02: partial
S03: pass
S04: pass
S05: pass
Expand All @@ -56,8 +56,8 @@ criteria:
D04: na
D05: na
D06: na
R01: partial
R02: partial
R01: pass
R02: pass
R03: pass
R04: pass
R05: pass
Expand All @@ -66,7 +66,7 @@ criteria:
R08: pass
I01: pass
I02: pass
I03: partial
I03: pass
I04: pass
I05: pass
I06: pass
Expand All @@ -79,10 +79,11 @@ criteria:
W02: pass
W03: pass
W04: pass
W05: pass
W06: pass
W05: na
W06: na
W07: pass
W08: pass
W09: pass
G01: pass
G02: pass
G03: pass
Expand All @@ -93,7 +94,7 @@ criteria:
G08: na
L01: pass
L02: pass
L03: partial
L03: pass
L04: na
L05: na
L06: na
Expand Down
16 changes: 16 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ jobs:
run: swift test
- name: Lint formatting
run: swift format lint --strict --recursive Sources Tests Package.swift
- name: Check the README platform badge against Package.swift
run: |
v="$(sed -n 's/.*\.macOS(\.v\([0-9]*\)).*/\1/p' Package.swift)"
test -n "$v"
grep -q "Platform-macOS%20${v}%2B" README.md

plugin:
name: Stream Deck plugin
runs-on: macos-15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Node version
run: node --version
- name: Format, static checks and tests
working-directory: Tools/openpromptr-streamdeck
run: npm test

bundle:
name: App bundle
Expand Down
29 changes: 29 additions & 0 deletions .github/workflows/stats.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Repository stats

# Renders the repository statistics card (standard criterion P09) and commits it
# to the generated `stats` branch, because `main` is protected. This is the only
# workflow here that may write, and it never runs for a pull request.

on:
workflow_dispatch:
schedule:
- cron: "23 5 * * *"
push:
branches:
- main
paths:
- .github/workflows/stats.yml

permissions: {}

jobs:
stats:
permissions:
contents: write
uses: trsdn/.github/.github/workflows/repo-stats.yml@38969dfb6575240ff1c7096672e503022aa0910a # main
with:
output-dir: .github/stats
theme: both
cards: repo-card
branch: stats
commit-message: "chore(stats): update repository stats"
31 changes: 22 additions & 9 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,17 @@ swift build
# Unit tests (swift-testing: @Test / #expect, no XCTest)
swift test

# Stream Deck plugin: format, static checks and tests (Node 20+; run in CI too)
(cd Tools/openpromptr-streamdeck && npm test)

# Formatting check (must be clean; CI enforces this)
swift format lint --strict --recursive Sources Tests Package.swift

# Build, bundle, and sign -> dist/OpenPromptr.app
./build-app.sh

# Smoke-test a published release (downloads it; no operator needed)
Scripts/smoke-published.sh v<version>
```

There is no Xcode project. Everything goes through SwiftPM; the app bundle is
Expand All @@ -28,12 +34,8 @@ assembled manually in `build-app.sh`.
(`git fetch --tags` / a non-shallow checkout) to produce a meaningful version;
outside a git checkout it falls back to whatever is in `Config/Info.plist`.

Optional runtime self-test, once the built app already holds Screen Recording
permission:

```bash
open "dist/OpenPromptr.app" --args --self-test
```
The optional runtime self-test is described in the
[README](README.md#optional-runtime-self-test).

`--version` prints the version/build and exits — no window is created.

Expand All @@ -45,9 +47,15 @@ open "dist/OpenPromptr.app" --args --self-test
Connect key to this repository**, in any form. Distributable, notarized
builds go through `trsdn/macos-notarization-broker` specifically so this
never has to happen.
- **Add a secret or a write permission to any workflow here.** `ci.yml` runs
with `contents: read` and no secrets, which is what makes it safe to run
against any pull request, including from a fork.
- **Add a secret to any workflow, or a write permission to any workflow other
than `stats.yml`.** `ci.yml` runs with `contents: read` and no secrets, which
is what makes it safe to run against any pull request, including from a
fork. `stats.yml` is the one exception: it renders the repository statistics
card (criterion `P09`) and may hold `contents: write`, declared on its job
only, because it commits to the generated `stats` branch. It must stay that
narrow: no secrets, no `pull_request` trigger, only `schedule`,
`workflow_dispatch` and a `push` to `main` of its own file, and it writes
only the `stats` branch, never `main`.
- **Rewrite published history.** No `git rebase`, `commit --amend`, or
`push --force` against `main`. A ruleset blocks force pushes and deletion of
`main`; branches with an open pull request are on trust.
Expand Down Expand Up @@ -148,6 +156,11 @@ Sources/
process, main.swift's dispatch between the two,
Update/ (AppUpdater integration, see #7), and
LocalAPI/ (the loopback HTTP control API, see #4).

Tools/
└── openpromptr-streamdeck/ OpenDeck / Stream Deck plugin (plain JavaScript,
no dependencies, no build step). A client of the local
API; installed with its own `install.sh`.
```

Three source types feed one output pipeline: a private virtual display, a
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- The app bundle now embeds its licence identifier and product description in
`Info.plist`.
- A repository statistics card, generated daily to the `stats` branch, in the
README.

## [1.3.0] - 2026-09-20

### Added
Expand Down
35 changes: 9 additions & 26 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,42 +6,25 @@ section before making larger changes.

## Requirements

- macOS 13 or newer (developed and tested on current versions)
- Xcode Command Line Tools with Swift 6.1 or newer
(`swift-tools-version: 6.1`, see `Package.swift`)
- The platform and toolchain requirements in the
[README](README.md#requirements)
- For signed builds: a "Developer ID Application" or "Apple Development"
certificate in the keychain

There are no third-party dependencies. `swift build` is enough.
The only third-party dependencies are `AppUpdater` and `Swifter`, resolved by
SwiftPM; `swift build` is enough.

## Development workflow

```bash
swift build # build
swift test # run unit tests
./build-app.sh # create signed .app bundle in dist/
```
The build, test, format and bundle commands are in
[`AGENTS.md`](AGENTS.md#build--validate), which is their one home.

The app icon is generated from code and is present in the repository as
`Resources/AppIcon.icns`. Regenerate it after changes to
`Scripts/make-icon.swift`:

```bash
swift Scripts/make-icon.swift
```

There is a self-test for a smoke test without a real target display:

```bash
open "dist/OpenPromptr.app" --args --self-test
```

It reports `SELF_TEST_PASS` when capture setup and output work.
The app icon and the runtime self-test are described in the
[README](README.md#app-icon) and [its self-test section](README.md#optional-runtime-self-test).

## Before the pull request

- `swift build` completes without warnings.
- `swift test` is green.
- The validation commands in [`AGENTS.md`](AGENTS.md#build--validate) pass.
- The change was checked manually with at least one source.
- Behavior changes are described in `README.md`.

Expand Down
4 changes: 4 additions & 0 deletions Config/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@
<string>https://github.com/trsdn/OpenPromptr/issues</string>
<key>OPRRepositoryURL</key>
<string>https://github.com/trsdn/OpenPromptr</string>
<key>OPRLicenseIdentifier</key>
<string>MIT</string>
<key>OPRProductDescription</key>
<string>Native macOS app that mirrors and rotates a virtual display, a physical display, or a single window onto a teleprompter screen.</string>
</dict>
</plist>
40 changes: 29 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

# OpenPromptr

[![CI](https://github.com/trsdn/OpenPromptr/actions/workflows/ci.yml/badge.svg)](https://github.com/trsdn/OpenPromptr/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![License: MIT](https://img.shields.io/github/license/trsdn/OpenPromptr)](LICENSE)
[![Platform: macOS 13+](https://img.shields.io/badge/Platform-macOS%2013%2B-lightgrey.svg)](#requirements)
[![Swift 6.1](https://img.shields.io/badge/Swift-6.1-orange.svg)](Package.swift)
[![CI](https://github.com/trsdn/OpenPromptr/actions/workflows/ci.yml/badge.svg)](https://github.com/trsdn/OpenPromptr/actions/workflows/ci.yml)
[![Latest release](https://img.shields.io/github/v/release/trsdn/OpenPromptr)](https://github.com/trsdn/OpenPromptr/releases/latest)
[![Conformance](.github/badges/conformance.svg)](.github/conformance.yml)

</div>

Expand Down Expand Up @@ -92,16 +93,23 @@ the invisible virtual display.
- Xcode or Command Line Tools with Swift 6
- Screen Recording permission for the built app bundle

## Building and testing
## Versioning and language

```bash
git clone https://github.com/trsdn/OpenPromptr.git
cd OpenPromptr
swift test
./build-app.sh
```
Releases are tagged `vMAJOR.MINOR.PATCH` and follow
[Semantic Versioning](https://semver.org/spec/v2.0.0.html): a patch release only
fixes bugs, a minor release adds behavior without breaking what exists, and a
major release may change or remove it. That covers the app, its local HTTP API
and the Stream Deck plugin. Every version's changes are in
[`CHANGELOG.md`](CHANGELOG.md).

The app's interface is **English only**; there are no localizations and none are
planned.

The script creates `dist/OpenPromptr.app`. It automatically prefers an
## Building and testing

Clone the repository, then build and validate with the commands in
[`AGENTS.md`](AGENTS.md#build--validate) — that is their one home.
`./build-app.sh` creates `dist/OpenPromptr.app`. It automatically prefers an
available identity of type **Developer ID Application**, falls back to **Apple
Development**, and only falls back to an ad-hoc signature with a warning if no
stable identity is available. There is no hard-coded team or certificate
Expand Down Expand Up @@ -378,6 +386,16 @@ now also carries an icon. This has not been tested end-to-end with VoiceOver.
Automatic-recovery and status changes are conveyed visually and in text only;
there are no sound cues.

## Repository statistics

<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/trsdn/OpenPromptr/stats/.github/stats/repo-card-dark.svg">
<img alt="Repository statistics" src="https://raw.githubusercontent.com/trsdn/OpenPromptr/stats/.github/stats/repo-card.svg">
</picture>

Generated daily by [`stats.yml`](.github/workflows/stats.yml) and committed to
the `stats` branch, because `main` is protected.

## Contributing

Contributions are welcome. The development workflow, language and commit
Expand Down
Loading