RepoPilotOpen in app →

SeaDve/Kooha

Elegantly record your screen

Mixed

Mixed signals — read the receipts

weakest axis
Use as dependencyConcerns

copyleft license (GPL-3.0) — review compatibility; no tests detected

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

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 →
  • 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 ConcernsMixed 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.

Variant:
RepoPilot: Forkable
[![RepoPilot: Forkable](https://repopilot.app/api/badge/seadve/kooha?axis=fork)](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:

  1. 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.
  2. 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.
  3. 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 |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>SeaDve/Kooha</code></summary>
#!/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).

</details>

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

  1. Define the codec and quality settings in the profiles file (data/resources/profiles.yml)
  2. Update GSettings schema if new preferences are needed (data/io.github.seadve.Kooha.gschema.xml.in)
  3. Update UI preference dialog to expose new codec option (data/resources/ui/preferences_dialog.ui)

Add a new UI screen or dialog

  1. Create a new .ui file in the resources/ui directory (data/resources/ui/)
  2. Register the UI resource in the resource manifest (data/resources/resources.gresource.xml)
  3. Implement Rust handler in src/ to manage the UI component lifecycle (src/application.rs)

Add a new application preference/setting

  1. Define the key and type in the GSettings schema (data/io.github.seadve.Kooha.gschema.xml.in)
  2. Add UI control in preferences dialog (data/resources/ui/preferences_dialog.ui)
  3. Bind the setting to the control in application.rs (src/application.rs)

Add translations for new strings

  1. Mark user-visible strings in .ui and .rs files with gettext macros (data/resources/ui/preferences_dialog.ui)
  2. Update the potfile list to include new source files (po/POTFILES.in)
  3. 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
  • emersion/xdg-desktop-portal-wlr — Upstream portal implementation Kooha depends on for Wayland screencast capability; troubleshooting wiki referenced in README
  • GNOME/gstreamer-plugin-gtk4 — GStreamer sink plugin that Kooha uses (gst-plugin-gtk4 in Cargo.toml) to capture GTK4 framebuffer content
  • gnome/libadwaita — UI toolkit dependency (adw 0.9) providing GNOME design patterns; understanding it is essential for modifying Kooha's interface
  • SeaDve/Clipped — Companion GNOME app by the same author; demonstrates similar GTK4+Rust patterns and may share utility code approaches
  • obsproject/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

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 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.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Mixed signals · SeaDve/Kooha — RepoPilot