@kurokeita/add-skill 1.20.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/README.md +17 -8
  2. package/dist/bin/cli.js +576 -792
  3. package/dist/skills/git-commit/SKILL.md +101 -37
  4. package/dist/skills/handoff/SKILL.md +16 -0
  5. package/dist/skills/init-agents-md/SKILL.md +51 -0
  6. package/dist/skills/init-agents-md/references/agents_template.md +42 -0
  7. package/dist/skills/init-agents-md/references/patterns_template.md +19 -0
  8. package/dist/skills/koreader-plugin-development/SKILL.md +141 -0
  9. package/dist/skills/koreader-plugin-development/examples/2-example-patch.lua +17 -0
  10. package/dist/skills/koreader-plugin-development/examples/_meta.lua +6 -0
  11. package/dist/skills/koreader-plugin-development/examples/helloworld.lua +36 -0
  12. package/dist/skills/koreader-plugin-development/references/debugging.md +92 -0
  13. package/dist/skills/koreader-plugin-development/references/events-and-widgets.md +102 -0
  14. package/dist/skills/koreader-plugin-development/references/patches.md +118 -0
  15. package/dist/skills/koreader-plugin-development/references/plugin-anatomy.md +97 -0
  16. package/dist/skills/statusline-setup/SKILL.md +211 -66
  17. package/dist/skills/universalize-agents/SKILL.md +245 -0
  18. package/dist/skills/universalize-agents/reference/hook-templates/README.md +30 -0
  19. package/dist/skills/universalize-agents/reference/hook-templates/claude-code.json +15 -0
  20. package/dist/skills/universalize-agents/reference/hook-templates/codex.toml +10 -0
  21. package/dist/skills/universalize-agents/reference/hook-templates/copilot.json +9 -0
  22. package/dist/skills/universalize-agents/reference/hook-templates/gemini.json +11 -0
  23. package/dist/skills/universalize-agents/reference/mapping.md +100 -0
  24. package/dist/skills/universalize-agents/scripts/agent-setup.ps1 +83 -0
  25. package/dist/skills/universalize-agents/scripts/agent-setup.sh +98 -0
  26. package/dist/skills/update-agents-md/SKILL.md +43 -0
  27. package/package.json +2 -5
@@ -1,22 +1,95 @@
1
1
  ---
2
2
  name: git-commit
3
- description: This skill should be used when the user asks to "commit changes", "commit message", or "follow conventional commits". Provides guidelines for Conventional Commits specification and commit message formatting.
4
- version: 1.0.0
3
+ description: Use BEFORE running any write-side git or gh command (git commit, git commit --amend, git push --force / --tags, git reset --hard, git rebase, gh pr create, gh pr merge), and whenever the user asks to commit changes, write a commit message, or follow conventional commits. Provides the hard pre-commit protocol (stop, summarize, propose, ask, wait) plus the Conventional Commits format used for the proposed message.
4
+ version: 2.0.0
5
5
  ---
6
6
 
7
7
  # Git Commit
8
8
 
9
- Guide for managing version control commit message formatting following the Conventional Commits specification.
9
+ This skill enforces the pre-commit protocol AND specifies the commit-message format. Both are mandatory before any gated git/gh write operation runs.
10
10
 
11
- ## When to Use This Skill
11
+ ## When to Use
12
12
 
13
- - Formatting commit messages to follow project standards
14
- - Learning the Conventional Commits specification
15
- - Ensuring consistency across the repository's history
13
+ Invoke this skill BEFORE calling Bash for any of:
16
14
 
17
- ## Conventional Commits
15
+ - `git commit` (any form, including `-m`, `-am`, no-args, heredoc, chained via `&&`/`;`)
16
+ - `git commit --amend` (any form)
17
+ - `git push --force` / `git push -f` / `git push --force-with-lease`
18
+ - `git push --tags`
19
+ - `git reset --hard`
20
+ - `git rebase` (any form, interactive or non-interactive)
21
+ - `gh pr create`
22
+ - `gh pr merge`
18
23
 
19
- Format commit messages according to the [Conventional Commits](https://www.conventionalcommits.org/) specification to enable automated changelog generation and easier history browsing.
24
+ Also invoke when the user asks to commit changes, write a commit message, or follow conventional commits.
25
+
26
+ The `permissions.ask` rule in `~/.claude/settings.json` will surface a permission prompt for these commands regardless. This skill ensures the prompt arrives with a proper proposal already presented to the user.
27
+
28
+ ## Pre-Commit Protocol (HARD RULE)
29
+
30
+ Every gated command, every time. No exceptions for "tiny" or "obvious" changes. Each commit gets its own gate even within the same session. Plan approval, prior "go ahead" signals, and approvals of earlier commits do NOT carry over.
31
+
32
+ ### Step 1 — STOP
33
+
34
+ Do not retry the command yet. The first attempt is your trigger, not your green light.
35
+
36
+ ### Step 2 — Emit a detailed technical summary
37
+
38
+ ```bash
39
+ ### Technical summary
40
+ - Scope: <files added/modified/deleted, one-line purpose each>
41
+ - Behavior change: <user-visible / API-visible effect, or "none" for pure refactors>
42
+ - Architecture/contract impact: <new exports, removed symbols, changed signatures, new dependencies, or "none">
43
+ - Tests: <what was added/updated, what was run, the result>
44
+ - Risk notes: <edge cases, deferred follow-ups, impact-analysis severity>
45
+ ```
46
+
47
+ Fill every bullet. "None" is a valid answer; an omitted bullet is not.
48
+
49
+ ### Step 3 — Propose a commit message
50
+
51
+ Format per the Conventional Commits section below. No `Co-Authored-By: Claude` trailer. Imperative present tense, no trailing period in the subject. When a body is included, it explains the why.
52
+
53
+ **Match the message size to the change.** For small commits — single file, trivial scope, narrow type change, doc tweak, small revert, one-line config flip, renamed prop — propose a title-only message. No body, no bullets. The subject alone conveys intent and a body adds friction without value.
54
+
55
+ ```bash
56
+ ### Proposed commit message
57
+ <type>(<scope>): <imperative subject>
58
+ ```
59
+
60
+ Reserve the full proposal format (body + bullets) for commits that touch multiple files, change behavior in subtle ways, or introduce risk worth flagging:
61
+
62
+ ```bash
63
+ ### Proposed commit message
64
+ <type>(<scope>): <imperative subject>
65
+
66
+ <body paragraph(s) explaining motivation and behavior change>
67
+
68
+ - bullet of notable change
69
+ - bullet of notable change
70
+ ```
71
+
72
+ ### Step 4 — Ask the user verbatim
73
+
74
+ Print exactly: **"Commit as-is, edit the message, or skip?"**
75
+
76
+ ### Step 5 — Wait for explicit approval
77
+
78
+ Only after the user replies with an affirmative answer may you re-attempt the command. The OS permission prompt will then surface for final confirmation.
79
+
80
+ If the user declines or asks to edit, do not commit. Update the proposal and re-ask.
81
+
82
+ ## Multi-commit work
83
+
84
+ If you have several logical commits ready, emit one full proposal per commit and gate each independently. Do not batch proposals. Do not commit any of them until each is individually approved.
85
+
86
+ ## Subagent delegation
87
+
88
+ If you dispatch a subagent that will end in a gated command, you (the orchestrator) own the proposal step. Either instruct the subagent to stop before the command and report back, or require it to wait for an "approved" signal you forward only after the user approves the proposal. A subagent that commits on its own initiative is a rule violation.
89
+
90
+ ## Conventional Commits format
91
+
92
+ Format the proposed message per the [Conventional Commits](https://www.conventionalcommits.org/) specification.
20
93
 
21
94
  ### Structure
22
95
 
@@ -30,36 +103,27 @@ Format commit messages according to the [Conventional Commits](https://www.conve
30
103
 
31
104
  ### Types
32
105
 
33
- - `feat`: A new feature
34
- - `fix`: A bug fix
35
- - `docs`: Documentation only changes
36
- - `style`: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc.)
37
- - `refactor`: A code change that neither fixes a bug nor adds a feature
38
- - `perf`: A code change that improves performance
39
- - `test`: Adding missing tests or correcting existing tests
40
- - `build`: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
41
- - `ci`: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
42
- - `chore`: Other changes that don't modify src or test files
43
- - `revert`: Reverts a previous commit
106
+ - `feat`: a new feature
107
+ - `fix`: a bug fix
108
+ - `docs`: documentation only changes
109
+ - `style`: changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc.)
110
+ - `refactor`: a code change that neither fixes a bug nor adds a feature
111
+ - `perf`: a code change that improves performance
112
+ - `test`: adding missing tests or correcting existing tests
113
+ - `build`: changes that affect the build system or external dependencies
114
+ - `ci`: changes to CI configuration files and scripts
115
+ - `chore`: other changes that do not modify src or test files
116
+ - `revert`: reverts a previous commit
44
117
 
45
118
  ### Guidelines
46
119
 
47
- - **Description**: Use the imperative, present tense (e.g., "add", not "added" or "adds").
48
- - **Case**: The description should be in lower-case or sentence-case.
49
- - **Scope**: Use a scope to provide additional contextual information (e.g., `feat(auth): add login validation`).
50
- - **Body**: Use the body to explain the "what" and "why" of the change, not the "how".
51
- - **Footer**: Use the footer to reference issues (e.g., `Closes #123`) or breaking changes.
52
-
53
- ## Additional Resources
54
-
55
- ### Reference Files
56
-
57
- For detailed patterns and advanced git workflows, consult:
58
-
59
- - **`references/conventional-commits.md`** - Detailed Conventional Commits specification.
60
-
61
- ### Example Files
120
+ - **Description**: imperative, present tense ("add", not "added" or "adds")
121
+ - **Case**: lower-case or sentence-case, no trailing period
122
+ - **Scope**: noun in parentheses describing a section of the codebase (e.g., `feat(auth): add login validation`)
123
+ - **Body**: explain the what and why, not the how
124
+ - **Footer**: reference issues (`Closes #123`) or breaking changes (`BREAKING CHANGE: ...`)
125
+ - **Breaking changes**: indicate with `!` after the type/scope OR a `BREAKING CHANGE:` footer
62
126
 
63
- Working examples in `examples/`:
127
+ ### Reference files
64
128
 
65
- - **`commit-messages.txt`** - Examples of well-formatted commit messages.
129
+ For detailed patterns and edge cases, see `references/conventional-commits.md`.
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: handoff
3
+ description: Compact the current conversation into a handoff document for another agent to pick up.
4
+ argument-hint: "What will the next session be used for?"
5
+ disable-model-invocation: true
6
+ ---
7
+
8
+ Write a handoff document summarising the current conversation so a fresh agent can continue the work. Save to the temporary directory of the user's OS - not the current workspace.
9
+
10
+ Include a "suggested skills" section in the document, which suggests skills that the agent should invoke.
11
+
12
+ Do not duplicate content already captured in other artifacts (PRDs, plans, ADRs, issues, commits, diffs). Reference them by path or URL instead.
13
+
14
+ Redact any sensitive information, such as API keys, passwords, or personally identifiable information.
15
+
16
+ If the user passed arguments, treat them as a description of what the next session will focus on and tailor the doc accordingly.
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: init-agents-md
3
+ description: Analyze a codebase to initialize or update its AGENTS.md (or CLAUDE.md) file, extract architectural patterns to docs/architectural_patterns.md, and procedural skills to .agents/skills/. Use when initializing a project's agent instructions, updating CLAUDE.md/AGENTS.md, or documenting project structure and workflows.
4
+ ---
5
+
6
+ # Initialize Agent Instructions & Patterns
7
+
8
+ Use this skill to analyze a workspace and create or update standard developer onboarding and workflow guidelines.
9
+
10
+ ## Workflow
11
+
12
+ ### 1. Analyze Codebase
13
+
14
+ Explore the codebase to identify:
15
+
16
+ - **WHAT**: Core technology stack, languages, frameworks, main libraries.
17
+ - **WHY**: Core business logic or project purpose.
18
+ - **HOW**: Scripts and CLI commands (e.g., in package.json, Makefile, etc.).
19
+ - **Files/Docs**: Existing documentation, configuration files, and key source directories.
20
+ - **Workflows**: Critical operational workflows (specifically: build, test, release).
21
+
22
+ ### 2. Generate or Update AGENTS.md
23
+
24
+ Create or update the `AGENTS.md` (or `CLAUDE.md`) file in the project root.
25
+
26
+ - Keep the file **under 150 lines** (optimum is 100–150 lines).
27
+ - Reference [agents_template.md](references/agents_template.md) for the structure.
28
+ - Follow these constraints strictly:
29
+ 1. Cover: WHAT (tech stack), WHY (purpose), and HOW (commands).
30
+ 2. Index all major documentation files or folders using progressive disclosure (one-line description each).
31
+ 3. Use **file:line references** (e.g., `src/main.ts:L42`) instead of embedding code snippets.
32
+ 4. Document exactly 2–3 critical workflows (e.g., build, test, release) as numbered steps.
33
+ 5. Do not include formatting or code styling rules (assume linters handle them).
34
+ 6. Always include these two lines under rules/guidelines:
35
+ - `Be extremely concise. Sacrifice grammar for concision.`
36
+ - `At the end of each plan, list unresolved questions.`
37
+
38
+ ### 3. Extract Architectural Patterns
39
+
40
+ Identify recurring design patterns, folder structure conventions, or key abstractions in the codebase.
41
+
42
+ - Extract these into `docs/architectural_patterns.md`.
43
+ - Reference [patterns_template.md](references/patterns_template.md) for the structure.
44
+ - Provide file:line references for concrete code examples of these patterns.
45
+
46
+ ### 4. Extract Procedural Know-How
47
+
48
+ Identify step-by-step procedures, deployment configurations, setup guides, or domain-specific instructions that would clutter the main `AGENTS.md` file.
49
+
50
+ - Extract these into `.agents/skills/<name>/SKILL.md` under the project scope.
51
+ - Reference the newly created skills in `AGENTS.md` or `docs/architectural_patterns.md` where relevant.
@@ -0,0 +1,42 @@
1
+ # AGENTS.md
2
+
3
+ ## Purpose & Tech Stack
4
+
5
+ - **WHAT**: [Tech stack, e.g., Next.js, TypeScript, TailwindCSS]
6
+ - **WHY**: [Core project purpose, target users, problem solved]
7
+
8
+ ## Commands
9
+
10
+ ```bash
11
+ pnpm dev # Run local dev server
12
+ pnpm build # Build project for production
13
+ pnpm test # Run test suite
14
+ pnpm lint # Check types and linting
15
+ ```
16
+
17
+ ## Documentation Index
18
+
19
+ - [docs/architecture.md](file:///path/to/docs/architecture.md) — One-line overview of architecture
20
+ - [docs/api.md](file:///path/to/docs/api.md) — One-line overview of API design
21
+
22
+ ## Critical Workflows
23
+
24
+ ### 1. Development & Build
25
+
26
+ 1. Run local environment: `command`
27
+ 2. Validate changes: `command`
28
+
29
+ ### 2. Testing
30
+
31
+ 1. Run unit tests: `command`
32
+ 2. Run integration tests: `command`
33
+
34
+ ### 3. Release/Deployment
35
+
36
+ 1. Build assets: `command`
37
+ 2. Deploy command or CI pipeline trigger: `command`
38
+
39
+ ## Guidelines
40
+
41
+ - Be extremely concise. Sacrifice grammar for concision.
42
+ - At the end of each plan, list unresolved questions.
@@ -0,0 +1,19 @@
1
+ # Architectural & Design Patterns
2
+
3
+ This document details the recurring architectural, design, and structural patterns found in this codebase.
4
+
5
+ ## 1. [Pattern Name]
6
+
7
+ - **Intent**: [What problem does this pattern solve?]
8
+ - **Location/Example**: [e.g., src/utils/paths.ts:L10-L40]
9
+ - **Implementation Details**:
10
+ - [Key implementation note 1]
11
+ - [Key implementation note 2]
12
+
13
+ ## 2. [Pattern Name]
14
+
15
+ - **Intent**: [What problem does this pattern solve?]
16
+ - **Location/Example**: [e.g., src/commands/add.ts:L45-L90]
17
+ - **Implementation Details**:
18
+ - [Key implementation note 1]
19
+ - [Key implementation note 2]
@@ -0,0 +1,141 @@
1
+ ---
2
+ name: koreader-plugin-development
3
+ description: This skill should be used when the user asks to "create a KOReader plugin", "write a koplugin", "build a KOReader patch", "userpatch", "modify KOReader behavior", "add a menu item to KOReader", "develop for KOReader", or mentions ".koplugin", "koreader/patches/", `WidgetContainer`, `UIManager`, or KOReader event handlers. Provides plugin and patch development guidance for the KOReader e-reader application (Lua, LuaJIT).
4
+ ---
5
+
6
+ # KOReader Plugin and Patch Development
7
+
8
+ KOReader is a document viewer for e-ink readers, written in Lua on LuaJIT. It exposes two main extension mechanisms:
9
+
10
+ - **Plugins** — self-contained `.koplugin/` directories loaded by `pluginloader` from `DEFAULT_PLUGIN_PATH` or `extra_plugin_paths`. Use for new features, menu entries, or background tasks.
11
+ - **Patches** — Lua files in `koreader/patches/` applied at startup by the `userpatch` module. Use for runtime monkey-patching of KOReader internals when a plugin is too heavy or the change must run before plugin load.
12
+
13
+ Choose plugins when the change is a feature you can ship as a folder. Choose patches for surgical fixes to existing modules, behavior overrides, or hotfixes that target a specific KOReader version.
14
+
15
+ ## Mental Model
16
+
17
+ KOReader's UI is a tree of `WidgetContainer` instances (subclasses of `EventListener`) managed by a top-level `UIManager`. Communication happens via `Event` objects with a `handler` name and `args`. `WidgetContainer:handleEvent` propagates events to children first; if no child returns `true`, the container's own `on<EventName>` method runs.
18
+
19
+ Plugins are typically classes built via `WidgetContainer:extend{...}` and returned from `main.lua`; they register themselves to the UI host (`ReaderUI` or `FileManager`) via `addToMainMenu`, dispatcher actions, or by listening to events.
20
+
21
+ Patches manipulate already-loaded modules (`require("apps.reader.readerui")`, `require("ui.widget.infomessage")`, etc.) to change methods, add hooks, or replace functions before or after the UI is built. Module paths must be the full namespaced form KOReader uses internally — short forms silently no-op.
22
+
23
+ ## Workflow
24
+
25
+ ### To create a plugin
26
+
27
+ 1. Create a directory `MyPlugin.koplugin/` containing at least:
28
+ - `main.lua` — module returning a `WidgetContainer`-derived class
29
+ - `_meta.lua` — table with `name`, `fullname`, `description`, optional `version`
30
+ 2. Place it under KOReader's `plugins/` directory (or set `extra_plugin_paths`).
31
+ 3. Implement the plugin class. Required pieces:
32
+ - `local MyPlugin = WidgetContainer:extend{ name = "myplugin" }` at the top of `main.lua`, with `return MyPlugin` at the bottom (return the class, not an instance — the loader instantiates it per host)
33
+ - `function MyPlugin:init() ... end` to wire dispatcher actions and event handlers
34
+ - `function MyPlugin:addToMainMenu(menu_items) ... end` if the plugin needs a menu entry
35
+ 4. Surface UI via `UIManager:show(InfoMessage:new{ text = "..." })` or custom widgets.
36
+ 5. React to events via `onEventName(self, ...)` methods. Return `true` to consume.
37
+ 6. Restart KOReader (or re-enter file manager) to pick up the plugin.
38
+
39
+ See `examples/helloworld.lua` for a minimal plugin and `references/plugin-anatomy.md` for full structure rules and lifecycle.
40
+
41
+ ### To create a patch
42
+
43
+ 1. Create `koreader/patches/2-my-fix.lua` (the leading number sets priority; see priorities below).
44
+ 2. `require` the target module and replace or wrap methods on it.
45
+ 3. Keep the patch small and version-pin it via a header comment that names the KOReader version it targets — patches break across releases.
46
+ 4. Restart KOReader. Errors during patch application surface in `crash.log`.
47
+
48
+ Priority is encoded in the filename prefix passed by `userpatch.applyPatches(priority)`. Common values:
49
+
50
+ | Prefix | Phase | Use for |
51
+ |--------|-------|---------|
52
+ | `1-` | early-once (very early) | Startup-only configuration, env tweaks |
53
+ | `2-` | early (before UI) | Patch core modules before UI builds |
54
+ | `3-` | late (after UI) | Override running widgets, add menu items |
55
+
56
+ See `references/patches.md` for monkey-patch idioms, version-guards, and pitfalls.
57
+
58
+ ## Common Tasks
59
+
60
+ ### Add a menu item
61
+
62
+ Implement `addToMainMenu(self, menu_items)` in a plugin and push an entry into the proper sub-table (`menu_items.tools`, `menu_items.plugins`, etc.). The host UI calls this once when the menu is built.
63
+
64
+ ### Listen for an event
65
+
66
+ Add `onEventName(self, arg1, arg2)` to the plugin class. Returning `true` stops further propagation; returning `nil`/`false` lets sibling widgets see the event. Common reader events include `PosUpdate`, `UpdatePos`, `PageUpdate`, `ReaderReady`, `CloseDocument`. See `references/events-and-widgets.md` for the wider catalog.
67
+
68
+ ### Show something to the user
69
+
70
+ Quick info: `UIManager:show(InfoMessage:new{ text = _("Done") })`.
71
+ Transient toast: `Notification:notify("Saved")`.
72
+ Custom UI: subclass `WidgetContainer` (or use `ButtonDialog`, `InputDialog`), then `UIManager:show(self)`. Always pair with `UIManager:close(self)` when dismissing.
73
+
74
+ ### Run code on a schedule
75
+
76
+ `UIManager:scheduleIn(seconds, function() ... end)` and `UIManager:unschedule(callback)`. For repeating background work, prefer subclassing `BackgroundTaskPlugin` (`ui.plugin.background_task_plugin`).
77
+
78
+ ### Persist plugin state
79
+
80
+ Use `LuaSettings` (`require("luasettings")`) backed by a file under `DataStorage:getSettingsDir()`. For document-scoped state, write to `self.ui.doc_settings` so it follows the document.
81
+
82
+ ## Debugging
83
+
84
+ - Enable debug mode (`./kodev run --debug` in dev, or `Settings -> Developer options -> Enable debug logging` on device) to get stack traces for event handlers and `logger.dbg(...)` output.
85
+ - `logger.dbg("label", value)` prints to stdout and to `koreader/crash.log`. Lua arguments evaluate eagerly — guard heavy expressions with `if dbg.is_on then ... end`.
86
+ - Read `crash.log` first when something fails silently; missing menu entries usually trace back to a load-time error in the plugin.
87
+ - Iterate on widget code without booting the reader: `./kodev wbuilder` spins up a minimal UI host. Add `UIManager:show(MyWidget:new{...})` lines to `tools/wbuilder.lua` to preview.
88
+
89
+ See `references/debugging.md` for emulator setup, asserts, and breakpoint strategies.
90
+
91
+ ## Important Gotchas
92
+
93
+ - **Module identity:** patches must target the exact module path KOReader uses (`require("apps.reader.readerui")`, not `require("readerui")` from outside the source root). Mismatched paths silently no-op.
94
+ - **Event return contract:** forgetting to `return true` causes events to keep propagating, often manifesting as duplicated actions.
95
+ - **String translation:** wrap user-visible strings in `_(...)` from `gettext` so they participate in translations.
96
+ - **Reader vs. FileManager host:** plugins can run under either. Check `self.ui.name == "ReaderUI"` or use `if self.ui.document then` to branch.
97
+ - **Version drift:** KOReader internals change between releases. Both patches and plugins that touch private fields must declare a target version in the header and degrade gracefully if internals shift.
98
+ - **No pcall around plugin init:** an error during `init` disables the plugin without obvious user feedback. Keep `init` defensive and short; defer heavy work to lazy methods or first-event.
99
+
100
+ ## File Layout Reference
101
+
102
+ ```
103
+ koreader/
104
+ ├── plugins/
105
+ │ └── MyPlugin.koplugin/
106
+ │ ├── _meta.lua
107
+ │ ├── main.lua
108
+ │ └── (assets, sub-modules, README.md)
109
+ ├── patches/
110
+ │ ├── 2-fix-something.lua
111
+ │ └── 3-override-menu.lua
112
+ └── crash.log
113
+ ```
114
+
115
+ ## Source-of-Truth Links
116
+
117
+ These pages back the rules above. Verify against them when behavior diverges.
118
+
119
+ - Development guide (frontend layout): <https://koreader.rocks/doc/topics/Development_guide.md.html>
120
+ - Events guide (propagation, builtin events): <https://koreader.rocks/doc/topics/Events.md.html>
121
+ - Hacking guide (debugging, wbuilder): <https://koreader.rocks/doc/topics/Hacking.md.html>
122
+ - `pluginloader` module: <https://koreader.rocks/doc/modules/pluginloader.html>
123
+ - `userpatch` module: <https://koreader.rocks/doc/modules/userpatch.html>
124
+ - HelloWorld example plugin: <https://github.com/koreader/koreader/tree/master/plugins/helloworld.koplugin>
125
+
126
+ ## Additional Resources
127
+
128
+ ### Reference Files
129
+
130
+ - `references/plugin-anatomy.md` — `_meta.lua`, `main.lua`, lifecycle, `addToMainMenu`, dispatcher integration, plugin disable/enable settings.
131
+ - `references/events-and-widgets.md` — `WidgetContainer` propagation rules, common reader/filemanager events, `UIManager` lifecycle.
132
+ - `references/patches.md` — patch priorities, monkey-patch idioms, version-guard patterns, removal/cleanup.
133
+ - `references/debugging.md` — `logger`, `dbg`, `crash.log`, `wbuilder`, emulator workflow.
134
+
135
+ ### Examples
136
+
137
+ - `examples/helloworld.lua` — minimal plugin `main.lua` showing menu registration and `InfoMessage`.
138
+ - `examples/_meta.lua` — minimal metadata file.
139
+ - `examples/2-example-patch.lua` — early-phase patch that wraps an existing method.
140
+
141
+ When information conflicts, the source-of-truth links above take precedence over this skill — verify against them before changing production code.
@@ -0,0 +1,17 @@
1
+ -- koreader/patches/2-example-patch.lua
2
+ -- Early-phase patch: wrap InfoMessage:init to prefix every message with "[patched]".
3
+ -- Targets KOReader v2025.05+. Remove if upstream changes the InfoMessage API.
4
+
5
+ local Version = require("version")
6
+ if Version:getCurrentRevision() < "v2025.05" then return end
7
+
8
+ local InfoMessage = require("ui.widget.infomessage")
9
+ local original_init = InfoMessage.init
10
+
11
+ function InfoMessage:init()
12
+ if self.text and not self._patched then
13
+ self.text = "[patched] " .. self.text
14
+ self._patched = true
15
+ end
16
+ return original_init(self)
17
+ end
@@ -0,0 +1,6 @@
1
+ local _ = require("gettext")
2
+ return {
3
+ name = "helloworld",
4
+ fullname = _("Hello World"),
5
+ description = _([[A minimal plugin that adds a menu entry showing an InfoMessage.]]),
6
+ }
@@ -0,0 +1,36 @@
1
+ -- Minimal KOReader plugin: HelloWorld.koplugin/main.lua
2
+ -- Add to plugins/HelloWorld.koplugin/ alongside _meta.lua, then restart KOReader.
3
+
4
+ local InfoMessage = require("ui.widget.infomessage")
5
+ local UIManager = require("ui.uimanager")
6
+ local WidgetContainer = require("ui.widget.container.widgetcontainer")
7
+ local logger = require("logger")
8
+ local _ = require("gettext")
9
+
10
+ local HelloWorld = WidgetContainer:extend{
11
+ name = "helloworld",
12
+ is_doc_only = false,
13
+ }
14
+
15
+ function HelloWorld:init()
16
+ self.ui.menu:registerToMainMenu(self)
17
+ end
18
+
19
+ function HelloWorld:addToMainMenu(menu_items)
20
+ menu_items.helloworld = {
21
+ text = _("Hello World"),
22
+ sorting_hint = "tools",
23
+ callback = function()
24
+ UIManager:show(InfoMessage:new{
25
+ text = _("Hello, plugin world."),
26
+ })
27
+ end,
28
+ }
29
+ end
30
+
31
+ function HelloWorld:onPageUpdate(new_pageno)
32
+ logger.dbg("HelloWorld saw PageUpdate", new_pageno)
33
+ -- Do not return true; let other widgets handle the event too.
34
+ end
35
+
36
+ return HelloWorld
@@ -0,0 +1,92 @@
1
+ # Debugging KOReader Plugins and Patches
2
+
3
+ ## Quick logger
4
+
5
+ ```lua
6
+ local logger = require("logger")
7
+ logger.dbg("foo", { a = 1 }) -- prefixed with DEBUG
8
+ logger.info("startup ok")
9
+ logger.warn("recoverable issue")
10
+ logger.err("failure", err)
11
+ ```
12
+
13
+ `logger.dbg` only prints when debug logging is enabled. Lua evaluates arguments eagerly, so wrap heavy work:
14
+
15
+ ```lua
16
+ local dbg = require("dbg")
17
+ if dbg.is_on then
18
+ logger.dbg("expensive view", buildSnapshot())
19
+ end
20
+ ```
21
+
22
+ ## Where logs go
23
+
24
+ - Desktop emulator: stdout of the `./kodev run` process.
25
+ - On device: `koreader/crash.log`. Lines tagged `04/06/17-21:44:53 DEBUG …`.
26
+
27
+ `crash.log` is the first place to look when a plugin "doesn't load" or a patch "didn't run". Plugin-load errors land here with the plugin path.
28
+
29
+ ## Enable debug mode
30
+
31
+ - Dev: `./kodev run --debug`
32
+ - On device: `Settings -> Developer options -> Enable debug logging`. Optionally `Enable verbose debug logging` for finer detail. Restart KOReader for the change to take effect.
33
+
34
+ In debug mode the loader logs stack traces from event handlers — this is how you find which plugin or patch raised an exception during event dispatch.
35
+
36
+ ## Emulator workflow
37
+
38
+ `./kodev` is the dev driver. Useful targets:
39
+
40
+ - `./kodev run` — start the SDL emulator with the bundled plugins.
41
+ - `./kodev run --debug` — same with debug logging.
42
+ - `./kodev wbuilder` — minimal UI host for prototyping a single widget without booting reader/file-manager. Append `UIManager:show(MyWidget:new{...})` lines to `tools/wbuilder.lua`.
43
+ - `./kodev test` — run the unit suite (`busted`).
44
+ - `./kodev clean` / `./kodev fetch-thirdparty` — when builds drift.
45
+
46
+ For out-of-tree plugin development, point KOReader at your folder via the `extra_plugin_paths` setting (UI: Plugin manager) so you do not have to copy files on each iteration.
47
+
48
+ ## Inspecting state
49
+
50
+ - `dbg.dump(any_value)` — pretty-prints a Lua table to the log.
51
+ - `require("dump")(any_value)` — alternative dumper used elsewhere in the codebase.
52
+ - `UIManager._window_stack` — the live widget stack, top of stack is the topmost visible widget.
53
+ - `self.ui` from inside a plugin gives access to the host (`ReaderUI` or `FileManager`) and all sibling modules (`self.ui.menu`, `self.ui.document`, `self.ui.dictionary`, etc.).
54
+
55
+ ## Asserts and fail-fast
56
+
57
+ Plugin `init` errors disable the plugin silently in production; let them propagate during development:
58
+
59
+ ```lua
60
+ function MyPlugin:init()
61
+ assert(self.ui, "no host UI")
62
+ -- ...
63
+ end
64
+ ```
65
+
66
+ Wrap the assert in `if dbg.is_on then` if you need a forgiving build.
67
+
68
+ ## Common diagnostics
69
+
70
+ | Symptom | First check |
71
+ |---------|-------------|
72
+ | Plugin not in plugin manager | `crash.log` for load error; verify `_meta.lua` returns a table |
73
+ | Menu entry missing | `addToMainMenu` actually called? `self.ui.menu:registerToMainMenu(self)` in `init`? |
74
+ | Event handler not firing | Event name typo; `is_doc_only` true while in FileManager; child widget consuming first |
75
+ | Patch silently no-op | Wrong module path passed to `require`; another patch already replaced the same method |
76
+ | UI not redrawing | Missing `UIManager:setDirty(widget, "ui")` after mutating widget state |
77
+
78
+ ## Reproducing on device vs emulator
79
+
80
+ Emulator runs the same Lua but uses SDL for framebuffer and lacks real Wi-Fi, real e-ink refresh quirks, and some device-specific paths. Behaviors that depend on the framebuffer driver (waveform modes, partial refresh) only repro on hardware. Path-sensitive logic (case-sensitive filesystems, mount points) usually shows up on Linux but not on macOS.
81
+
82
+ ## Reading the source effectively
83
+
84
+ When the docs are silent (most plugin internals), grep:
85
+
86
+ ```
87
+ git grep "Event:new(\"PageUpdate\""
88
+ git grep "registerToMainMenu"
89
+ git grep "applyPatches"
90
+ ```
91
+
92
+ The KOReader codebase is the authoritative reference; treat upstream code as documentation.