# Development ## Writing your own plugin 1. Run `python3 tools/bundle.py --check` once. It enables the git hooks that auto-bump the version on commit (see [Git hooks and versioning](versioning-and-releases.md#git-hooks-and-versioning)). 2. Edit `plugin.json` (id, name, description, etc.). 3. Write your plugin under `src/`, with `src/main.py` as the entry module (absolute imports only — it's executed at plugin-module top level, not inside a package). 4. `python3 tools/bundle.py --release && python3 tools/verify_bundle.py dist/.plugin` (substitute your `id` from `plugin.json`). 5. `bash scripts/deploy.sh --enable` with a device connected. ## Repo layout ``` plugin.json single source of truth for plugin metadata src/ the plugin, written as an ordinary Python package main.py entry module — exactly one BasePlugin subclass, absolute imports only config.py setting keys, defaults and tunables diagnostics.py bounded in-memory log, mirrored to a file (logcat is restricted here) providers/ endpoint settings, prompt assembly and SSE streaming services/ history fetch, anonymized transcript, markdown→RichMessage, injection, SQLite store hooks/ Xposed hooks (unread-button entry points, summary restore on chat open, forgetting a summary when its card is deleted) ui/ summarize dialog, bulletin and theme helpers tools/ bundle.py compiles plugin.json + src/ into dist/.plugin devclient.py speaks the on-device dev-server protocol (127.0.0.1:42690) verify_bundle.py offline harness that proves a built bundle behaves correctly, no phone needed release.py publishes a built bundle to a Gitea release (used by CI) icon_png.py renders images/icon.svg to a square PNG images/icon.svg the plugin icon, source of truth for any PNG export .gitea/workflows/ CI that builds, verifies and publishes the .plugin to Releases scripts/ ADB debug-loop automation and the git hooks docs/ these notes + sdk-notes.md, the condensed SDK API surface ``` ## The three commands that matter ```bash python3 tools/bundle.py --release # compile src/ -> dist/.plugin python3 tools/verify_bundle.py dist/.plugin # offline proof the bundle works, no device needed bash scripts/deploy.sh --enable # build (--dev) + push to a connected device + enable + reload ``` `bundle.py` walks `src/` recursively, embeds every `.py` file's source and dotted module name into a compressed, base64-encoded payload, and appends a small runtime preamble that installs a private import hook (scoped to a per-module `__builtins__` dict, never touching `sys.modules`) so cross-module and cross-package imports resolve exactly as they would if the files were still on disk. `--dev` (the default) embeds absolute local paths so a debugger resolves breakpoints against your real source files; `--release` embeds repo-relative paths for distribution. Both modes produce byte-reproducible output for a given `src/` + `plugin.json`. Its first run in a clone also enables the repo's git hooks (see [Git hooks and versioning](versioning-and-releases.md#git-hooks-and-versioning)). ## Exporting the icon as PNG `tools/icon_png.py` renders `images/icon.svg` to `images/icon.png`, 512x512 by default. `--resolution` sets the size of both sides, so `--resolution 1024` gives 1024x1024: ```bash python3 tools/icon_png.py # images/icon.png, 512x512 python3 tools/icon_png.py --resolution 1024 # images/icon.png, 1024x1024 python3 tools/icon_png.py some.svg -o out.png ``` The output is always PNG; any other `-o` extension is rejected. The script itself is stdlib only and hands the rendering to the first renderer it finds: the `cairosvg` Python package, `rsvg-convert` (librsvg), ImageMagick or Inkscape. Install any one of them.