SeaDve/Kooha
Elegantly record your screen
Mixed signals — read the receipts
weakest axiscopyleft license (GPL-3.0) — review compatibility; no tests detected
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 1w ago
- ✓2 active contributors
- ✓GPL-3.0 licensed
Show all 8 evidence items →Show less
- ✓CI configured
- ⚠Small team — 2 contributors active in recent commits
- ⚠Concentrated ownership — top contributor handles 68% of recent commits
- ⚠GPL-3.0 is copyleft — check downstream compatibility
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Concerns → Mixed if: relicense under MIT/Apache-2.0 (rare for established libs)
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/seadve/kooha)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/seadve/kooha on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: SeaDve/Kooha
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/SeaDve/Kooha shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Mixed signals — read the receipts
- Last commit 1w ago
- 2 active contributors
- GPL-3.0 licensed
- CI configured
- ⚠ Small team — 2 contributors active in recent commits
- ⚠ Concentrated ownership — top contributor handles 68% of recent commits
- ⚠ GPL-3.0 is copyleft — check downstream compatibility
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live SeaDve/Kooha
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/SeaDve/Kooha.
What it runs against: a local clone of SeaDve/Kooha — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in SeaDve/Kooha | Confirms the artifact applies here, not a fork |
| 2 | License is still GPL-3.0 | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 39 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of SeaDve/Kooha. If you don't
# have one yet, run these first:
#
# git clone https://github.com/SeaDve/Kooha.git
# cd Kooha
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of SeaDve/Kooha and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "SeaDve/Kooha(\\.git)?\\b" \\
&& ok "origin remote is SeaDve/Kooha" \\
|| miss "origin remote is not SeaDve/Kooha (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(GPL-3\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"GPL-3\\.0\"" package.json 2>/dev/null) \\
&& ok "license is GPL-3.0" \\
|| miss "license drift — was GPL-3.0 at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "src/application.rs" \\
&& ok "src/application.rs" \\
|| miss "missing critical file: src/application.rs"
test -f "Cargo.toml" \\
&& ok "Cargo.toml" \\
|| miss "missing critical file: Cargo.toml"
test -f "meson.build" \\
&& ok "meson.build" \\
|| miss "missing critical file: meson.build"
test -f "data/resources/ui/window.ui" \\
&& ok "data/resources/ui/window.ui" \\
|| miss "missing critical file: data/resources/ui/window.ui"
test -f "data/resources/profiles.yml" \\
&& ok "data/resources/profiles.yml" \\
|| miss "missing critical file: data/resources/profiles.yml"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 39 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~9d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/SeaDve/Kooha"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Kooha is a minimal GNOME screen recorder built in Rust that captures screen video with configurable audio sources (microphone, desktop audio, or both) and exports to WebM, MP4, GIF, or Matroska formats. It uses GStreamer (0.25+) for encoding and the gtk4-plugin-gtk to interface with system framebuffers via xdg-desktop-portal, providing hardware-accelerated encoding as an experimental feature. Monolithic Rust application (210KB of Rust code) built with Meson build system. Core structure: src/ contains the main app logic, data/resources/ holds UI definitions (GTK4 .ui files), profiles.yml, and icons, data/ manages desktop integration (service files, schema, metadata). CI orchestrated via .github/workflows, vendoring support in build-aux/.
👥Who it's for
Linux desktop users (particularly GNOME/Wayland users) who want to record screencasts without complex configuration, and open-source contributors interested in Rust GTK4 applications, GStreamer pipelines, or desktop portal integration.
🌱Maturity & risk
Actively developed and production-ready. Version 2.3.1 with CI/CD via GitHub Actions (audit.yml, ci.yml), distributed on Flathub, and translated into multiple languages via Weblate. The Rust edition is 2024 and MSRV is 1.90, indicating recent maintenance.
Single maintainer (SeaDve) and relatively niche scope (screen recording only on Linux). Depends on GStreamer ecosystem and xdg-desktop-portal availability which vary by distro—the README explicitly acknowledges compatibility issues. Experimental hardware encoding feature is marked unstable. No visible open issue data in provided metadata, but Flathub distribution provides good real-world testing surface.
Active areas of work
Active maintenance with recent Rust edition updates to 2024 and MSRV bump to 1.90. Experimental features gated behind KOOHA_EXPERIMENTAL env var indicate ongoing feature stabilization work. Build optimization (LTO in release profile) shows performance focus.
🚀Get running
Clone, install Rust (1.90+) and Meson build system, then: git clone https://github.com/SeaDve/Kooha.git && cd Kooha && meson setup builddir && meson compile -C builddir && meson install -C builddir. Requires GStreamer 1.22+, libadwaita 0.9+, and gtk4 0.11+ as runtime deps.
Daily commands:
meson compile -C builddir && ./builddir/src/kooha (debug) or use KOOHA_EXPERIMENTAL=all ./builddir/src/kooha to test unstable features. For Flathub: flatpak install io.github.seadve.Kooha && flatpak run io.github.seadve.Kooha.
🗺️Map of the codebase
src/application.rs— Main application entry point and initialization; every contributor must understand how the GTK/Libadwaita app lifecycle works.Cargo.toml— Defines all Rust dependencies including GStreamer, GTK4, and Libadwaita; critical for understanding build requirements and version constraints.meson.build— Primary build configuration for Meson; contributors must know how the project compiles and links GStreamer pipelines.data/resources/ui/window.ui— Root GTK4 UI layout defining the main window structure; essential for understanding the presentation layer.data/resources/profiles.yml— Screen recording profiles and codec configurations; defines supported output formats and quality settings.data/io.github.seadve.Kooha.gschema.xml.in— GSettings schema defining application preferences and persistent state; required for understanding configuration persistence.src/about.rs— Application metadata and version info; contributors need to know app identity and feature flags.
🧩Components & responsibilities
- undefined — undefined
🛠️How to make changes
Add a new recording codec/profile
- Define the codec and quality settings in the profiles file (
data/resources/profiles.yml) - Update GSettings schema if new preferences are needed (
data/io.github.seadve.Kooha.gschema.xml.in) - Update UI preference dialog to expose new codec option (
data/resources/ui/preferences_dialog.ui)
Add a new UI screen or dialog
- Create a new .ui file in the resources/ui directory (
data/resources/ui/) - Register the UI resource in the resource manifest (
data/resources/resources.gresource.xml) - Implement Rust handler in src/ to manage the UI component lifecycle (
src/application.rs)
Add a new application preference/setting
- Define the key and type in the GSettings schema (
data/io.github.seadve.Kooha.gschema.xml.in) - Add UI control in preferences dialog (
data/resources/ui/preferences_dialog.ui) - Bind the setting to the control in application.rs (
src/application.rs)
Add translations for new strings
- Mark user-visible strings in .ui and .rs files with gettext macros (
data/resources/ui/preferences_dialog.ui) - Update the potfile list to include new source files (
po/POTFILES.in) - Run meson compile to regenerate .pot template, then upload to Weblate (
po/kooha.pot)
🔧Why these technologies
- GTK4 + Libadwaita — Modern, native GNOME desktop UI framework with hardware acceleration and responsive design; provides high-quality user experience for screen recording UI.
- GStreamer — Industry-standard multimedia pipeline framework; enables efficient hardware-accelerated screen capture, real-time encoding with multiple codec support (H.264, VP8, VP9, AV1).
- Rust — Memory-safe systems language preventing undefined behavior in time-sensitive recording loops; strong type system reduces encoding bugs; excellent GStreamer/GTK bindings.
- Meson + Cargo — Meson handles system integration (GSettings, D-Bus, icons); Cargo manages Rust dependencies and compilation; dual system allows proper GNOME/Flatpak integration.
- GSettings + D-Bus — GSettings provides per-user persistent configuration; D-Bus enables platform integration and potential remote control; native GNOME patterns.
- Flatpak — Containerized sandbox distribution enables secure distribution across distributions; handles permission model for screen capture and microphone access.
⚖️Trade-offs already made
-
Use GStreamer for encoding rather than FFmpeg
- Why: GStreamer integrates tightly with GNOME platform, provides direct access to hardware encoders, and supports live encoding pipelines.
- Consequence: Adds GStreamer dependency (large, but widespread); more efficient resource usage during recording.
-
Profiles-based codec selection via YAML
- Why: Pre-defined profiles reduce user confusion and ensure safe, tested codec/bitrate combinations.
- Consequence: Less flexibility for advanced users; simpler UI and reliable output quality.
-
GTK4 UI in .ui files rather than code-generated
- Why: Declarative UI enables designer collaboration, easier localization, and separation of UI logic from business logic.
- Consequence: Requires Meson/libglade infrastructure; slightly larger resource overhead at startup for parsing.
-
Rust + GStreamer bindings instead of C
- Why: Memory safety and modern language ergonomics reduce crashes in the critical path; strong type system catches encoding errors early.
- Consequence: Smaller ecosystem than C; requires stable Rust 1.90+; some GStreamer APIs may have less-polished bindings.
🚫Non-goals (don't propose these)
- Does not provide live streaming to remote servers (records to local file only).
- Does not support multi-monitor recording as separate files (captures single selected region).
- Does not include built-in video editing or post-processing.
- Does not provide real-time audio level monitoring UI (audio tracks are captured but not visible during recording).
- Does not support recording scheduled/time-delayed starts.
- Not cross-platform: Linux/GNOME only (requires X11 or Wayland, GStreamer, GTK4).
🪤Traps & gotchas
KOOHA_EXPERIMENTAL env var must be set to 'all' or specific feature keys to enable unstable encoding modes—defaults disable hardware acceleration. Requires active Wayland or X11 session with xdg-desktop-portal daemon; fails silently on unsupported distros (see troubleshooting wiki link in README). GStreamer plugin availability varies by system (gst-plugin-gtk4 with dmabuf/wayland features must be compiled in). Meson build requires exact libadwaita 0.9 and gtk4 0.11 minor versions—patch mismatches may cause runtime crashes.
🏗️Architecture
💡Concepts to learn
- GStreamer Pipeline — Kooha's entire recording flow (capture → encode → mux) is a GStreamer pipeline; understanding pad negotiation, element states, and caps is essential to debugging or extending codecs
- xdg-desktop-portal (Screencast Interface) — Kooha uses portal's org.freedesktop.portal.ScreenCast API to request framebuffer access from the compositor; understanding portal negotiation (version, stream tokens, formats) explains why it fails on unsupported distros
- libadwaita Preferences (GSettings + Schemas) — User settings (frame rate, saving location, pointer visibility) are persisted via GSettings + gschema.xml templates; modifying settings requires understanding schema compilation and dconf backend integration
- GTK4 UI Markup (.ui files) — Kooha's interface is declarative XML in .ui files (window.ui, preferences_dialog.ui) bound to Rust code via gtk-rs bindings; changes to layout, buttons, or dialogs happen here, not in imperative code
- Hardware-Accelerated Encoding (NVENC/VA-API) — Experimental feature (gated by KOOHA_EXPERIMENTAL) using GPU codecs instead of CPU; requires understanding GStreamer HW encoder elements (nvencav1, vaapih264enc) and format constraints
- Meson Build System — Unlike Cargo-only Rust projects, Kooha uses Meson to orchestrate build, resource embedding, schema compilation, and desktop integration; modifying build outputs requires meson.build edits
- Async Futures Coordination (futures-util) — Recording state machine (idle → delay → recording → stopped) likely uses futures channels for event coordination across GStreamer callbacks and UI interactions; understanding channel semantics is key to async bug fixes
🔗Related repos
emersion/xdg-desktop-portal-wlr— Upstream portal implementation Kooha depends on for Wayland screencast capability; troubleshooting wiki referenced in READMEGNOME/gstreamer-plugin-gtk4— GStreamer sink plugin that Kooha uses (gst-plugin-gtk4 in Cargo.toml) to capture GTK4 framebuffer contentgnome/libadwaita— UI toolkit dependency (adw 0.9) providing GNOME design patterns; understanding it is essential for modifying Kooha's interfaceSeaDve/Clipped— Companion GNOME app by the same author; demonstrates similar GTK4+Rust patterns and may share utility code approachesobsproject/obs-studio— Feature-rich alternative screen recorder; Kooha deliberately strips down OBS complexity for minimal UX, so comparing architecture shows design philosophy
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add integration tests for GStreamer pipeline configurations
The repo uses GStreamer for screen recording with complex plugin dependencies (gst-plugin-gtk4, gst-plugin-gif, wayland/x11 backends). Currently, there are no visible integration tests to verify pipeline initialization, format negotiation, or backend-specific codec handling. This would catch regressions when updating GStreamer versions or changing encoding profiles.
- [ ] Create tests/gst_pipeline_tests.rs to test GStreamer pipeline initialization with different profiles from data/resources/profiles.yml
- [ ] Add tests for wayland vs x11 backend selection (gdk-wayland vs gdk-x11 features)
- [ ] Test encoding profile validation and fallback behavior when codecs are unavailable
- [ ] Integrate tests into .github/workflows/ci.yml to run on each commit
Add localization completeness checks to CI workflow
The project has 30+ translations (po/*.po files) but no automated validation that translation files are syntactically valid or that POTFILES.in stays synchronized. Missing or outdated translations can cause build failures in CI that only appear during release.
- [ ] Create a new GitHub Action workflow .github/workflows/i18n-check.yml
- [ ] Add msgfmt validation for all .po files in po/ directory
- [ ] Add check that po/POTFILES.in references only existing source files
- [ ] Validate po/LINGUAS matches actual .po files present
- [ ] Run on pull requests to catch translation-related issues early
Document and add UI state machine tests for recording lifecycle
The UI files (data/resources/ui/*.ui) define complex state transitions (idle → recording → paused → saving). There's no visible test coverage for these state transitions, making refactoring fragile. The preferences_dialog.ui, view_port.ui, and window.ui components need validation that UI state matches recording state.
- [ ] Create tests/ui_state_machine_tests.rs to model recording states (Idle, Recording, Paused, Finalizing)
- [ ] Add tests verifying UI widget sensitivity changes match state transitions (e.g., pause button only visible during Recording)
- [ ] Test that GSetting changes from preferences_dialog.ui persist and affect recording behavior
- [ ] Add test fixtures that load .ui files via GTK to catch UI definition syntax errors
- [ ] Document state machine in README.md with state diagram
🌿Good first issues
- Add unit tests for profiles.yml deserialization logic in Cargo.toml's serde_yaml integration; currently no test files visible for YAML parsing
- Document the GStreamer pipeline construction (likely in src/ but not visible) by adding code comments explaining how gst-plugin-gtk4 framebuffer input connects to codec elements
- Add fallback UI layout for small screens (phones/tablets) in data/resources/ui/window.ui since current .ui is likely desktop-centric; test on GTK4 mobile simulators
📝Recent commits
Click to expand
Recent commits
805b3cc— po: Translated using Weblate (Slovak) (weblate)7e940a9— fix(pipeline): fix incorrect duration when recording (SeaDve)cea8ac8— build(flatpak): remove unused x264 and gst-plugins-ugly modules (SeaDve)3707e91— feat: port to AdwShortcutsDialog (SeaDve)d8b0443— update dependencies and fix dialog response handling (SeaDve)9866d86— po: Translated using Weblate (Slovak) (weblate)26f8dab— po: Translated using Weblate (Slovak) (weblate)cf0cd53— po: Translated using Weblate (Japanese) (weblate)d2b0370— po: Translated using Weblate (Tamil) (weblate)79a672e— po: Translated using Weblate (French) (weblate)
🔒Security observations
Kooha's security posture is generally good. The codebase is written in Rust (memory-safe language) with proper build profiles. Main concerns are: (1) an invalid Rust edition declaration that must be corrected, (2) potentially outdated media processing dependencies that should be audited with 'cargo audit', and (3) missing security disclosure policy. The application handles screen recording and media streams, so careful dependency management of GStreamer bindings is important. No hardcoded secrets, injection risks, or obvious misconfigurations were detected in the provided file structure. Consider implementing security scanning in the CI/CD pipeline (the repo has GitHub Actions setup that could include cargo-audit).
- Medium · Outdated Rust Edition Declaration —
Cargo.toml. The Cargo.toml specifies edition = '2024' which does not exist. Valid Rust editions are 2015, 2018, and 2021. This appears to be a typo that could cause build failures or unexpected behavior. Fix: Update to a valid Rust edition, likely '2021' which is the current stable edition. Verify with 'rustc --version' and update accordingly. - Medium · Potentially Outdated Dependencies —
Cargo.toml - dependencies section. Several dependencies use versions that may be outdated relative to current security patches: gstreamer (0.25), libadwaita (0.9), gtk4 (0.11). While specific CVEs weren't identified in provided context, media processing libraries like GStreamer have historically had security issues. Fix: Run 'cargo audit' to check for known vulnerabilities. Update dependencies to their latest versions: 'cargo update'. Particularly review GStreamer plugin versions for buffer overflow or memory safety issues. - Low · Debug Info Stripped in Development —
Cargo.toml - [profile.dev]. The [profile.dev] section strips debug information (strip = 'debuginfo'), which may complicate debugging during development and security incident analysis. Fix: Consider keeping debuginfo for development builds. Change to 'strip = false' or remove the strip directive. Reserve debuginfo stripping for release builds only if necessary for binary size. - Low · No Explicit Security Policy —
Repository root. No SECURITY.md or security policy file visible in the repository structure, which could delay security vulnerability reporting. Fix: Create a SECURITY.md file documenting how to responsibly disclose security vulnerabilities. Include contact information and expected response timeline.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.