komikku/AGENTS.md
Cuong-Tran c1806e13b3
Agent.md (#1658)
* Generate `AGENTS.md` using CoPilot

* Re-generate by Cursor & manual merge

* Review again with Cursor
2026-05-22 23:49:37 +07:00

6.4 KiB
Raw Blame History

Komikku AI Agent Guide

Komikku is an Android manga reader (min SDK 26, target SDK 36, JVM 17 / Kotlin) forked from Mihon + TachiyomiSY. Stack: Jetpack Compose + Material3, Voyager navigation, SQLDelight, Injekt DI. applicationId: app.komikku.


Module layout

Module Purpose
app/ UI (eu.kanade.*, exh/, mihon/), DI, workers, build variants
domain/ Use cases in …/interactor/ (e.g. GetManga), models, repo interfaces
data/ SQLDelight DB, *RepositoryImpl (tachiyomi.data.*)
core:common/ Network (OkHttp), security, storage, shared utils
core:archive/ CBZ/archive reading with optional encryption
core-metadata/ Comic-info metadata parsing
source-api/ / source-local/ Extension Source API + local source
presentation-core/ Shared Compose components
presentation-widget/ Home-screen Glance widget
i18n/ Mihon strings → MR (moko-resources)
i18n-kmk/ Komikku strings → KMR
i18n-sy/ TachiyomiSY strings → SYMR
flagkit/ Country-flag drawables
telemetry/ Firebase/Crashlytics (noop unless -Pinclude-telemetry)
macrobenchmark/ Macrobenchmark tests

Dependency flow: appdomainsource-api; data implements domain repos.

Version catalogs: gradle/libs.versions.toml, kotlinx.versions.toml, androidx.versions.toml, compose.versions.toml, sy.versions.toml.


Architecture

DI uy.kohesive.injekt (not Hilt). Register in AppModule.kt, DomainModule.kt, KMKDomainModule.kt, SYDomainModule.kt via addSingleton / addSingletonFactory. Resolve with Injekt.get<T>() or injectLazy<T>().

UI & navigation Voyager: Screen in eu.kanade.tachiyomi.ui.*, composables in eu.kanade.presentation.*. Base type: eu.kanade.presentation.util.Screen. State via rememberScreenModel { … }; most models extend StateScreenModel<State> or bases like SearchScreenModel; some use plain ScreenModel. Prefer screenModelScope and ioCoroutineScope; use launchIO / withIOContext from tachiyomi.core.common.util.lang. rememberCoroutineScope() is fine in Compose; long-lived services may use their own CoroutineScope.

Activities (not Voyager) MainActivity (shell), ReaderActivity + ReaderViewModel, WebViewActivity, UnlockActivity, OAuth login activities, DeepLinkActivity. Reader: ReaderActivity.newIntent(context, mangaId, chapterId). Web: both WebViewScreen (Voyager) and WebViewActivity.newIntent(...).

Example: DeepLinkScreen + DeepLinkScreenModel in app/src/main/java/eu/kanade/tachiyomi/ui/deeplink/.

Domain / data One class per operation under domain/…/interactor/ (verb names, not *Interactor suffix). Also app/src/main/java/eu/kanade/domain/…/interactor/ for app-specific cases. Wire repos in eu.kanade.domain.DomainModule.kt (+ KMKDomainModule, SYDomainModule).

Database SQLDelight in data/src/main/sqldelight/tachiyomi/ (.sq queries, migrations/*.sqm). After schema changes add a new .sqm and often // KMK blocks in .sq / mappers. Regenerate: ./gradlew :data:generateSqlDelightInterface (or any compile that touches :data).

App preference migrations app/src/main/java/mihon/core/migration/migrations/ (mihon.core.migration.Migration).

Images Coil 3 (coil3.*, context.imageLoader). No Glide/Picasso.


Komikku-specific work

  • New user-facing strings: KMR in i18n-kmk/src/commonMain/moko-resources/base/. Shared/upstream: MR (i18n). SY-only: SYMR (i18n-sy).
  • Do not edit locale strings.xml in i18n/ or i18n-sy/ except when syncing upstream; translations via Weblate.
  • Komikku code/DI: search // KMK (e.g. KMKDomainModule, HideCategory, library-update errors).
  • Prefs: eu.kanade.domain.*.service.*Preferences (e.g. SourcePreferences.relatedMangas()).

Extensions & sources

  • Catalog sources: installable APK extensions (not in this repo).
  • In-repo: delegated sources and metadata in exh/ (E-Hentai, NHentai, MangaDex, exh/recs/).
  • source-api: eu.kanade.tachiyomi.source.* — avoid breaking extension ABI.

Build & CI

Build types: debug (.dev), release, releaseTest (.rt), foss (.foss), preview (.beta, CI default), benchmark.

Gradle -P flags (buildSrc/.../BuildConfig.kt):

Flag Effect
include-telemetry Firebase Analytics + Crashlytics
enable-updater In-app update checker
disable-code-shrink Skip R8 minification
include-dependency-info Dependency metadata in APK
./gradlew spotlessApply              # format (CI: spotlessCheck)
./gradlew assemblePreview            # main CI/dev APK
./gradlew assemblePreview -Pinclude-telemetry -Penable-updater  # full upstream CI build
./gradlew testReleaseUnitTest        # CI unit tests (or ./gradlew test for all modules)
./gradlew installDebug               # device install
./gradlew :data:generateSqlDelightInterface  # after .sq / .sqm changes

JDK 17.


Fork-origin markers

Preserve inline blocks when editing:

// KMK -->  … // KMK <--   Komikku
// SY -->   … // SY <--    TachiyomiSY
// EXH -->  … // EXH <--   E-Hentai / exh (existing); prefer KMK for new Komikku-only code

Package roots: eu.kanade.tachiyomi.* (legacy UI), tachiyomi.* (domain/data), mihon.* (Mihon upstream), exh.* (enhanced sources).


Tests

  • Unit tests: domain/src/test/; app: app/src/test/.../MigratorTest.kt. No broad UI test suite.

Conventions

  • Logging Prefer xLogE() / xLog() helpers from exh.log for Komikku code, Mihon uses logcat { } from tachiyomi.core.common.util.system. Avoid raw android.util.Log.
  • Formatting Spotless + ktlint (buildSrc/.../mihon.code.lint.gradle.kts).
  • Fork edits New Komikku features inside // KMK islands; keep // SY / // EXH blocks intact when merging upstream.

Key files

  • App.kt Injekt bootstrap, logging setup
  • MainActivity.kt Voyager host
  • app/src/main/java/eu/kanade/tachiyomi/di/AppModule.kt core DI
  • app/src/main/java/eu/kanade/domain/DomainModule.kt domain interactors
  • buildSrc/.../BuildConfig.kt, AndroidConfig.kt flags, SDK versions
  • app/build.gradle.kts, settings.gradle.kts