agentleFS
rjstonerjstone/agent-skills/skills/thonny-plugin/SKILL.md

thonny-plugin

Skill0 starsChanged 6 days agoMITView on GitHub

Use when writing, installing, testing or debugging a plugin for the Thonny Python IDE (thonnycontrib namespace, load_plugin, workbench, editor, runner or debugger APIs), or when a Thonny plugin "does nothing" after install.

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 2 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Keep a module-level reference to anything that must outlive the call (servers, threads).

    line 31
  2. Very specific:

    After copying, strip __pycache__ and restart Thonny (full quit.

    line 55
  3. Distinctive:

    Read-only Tk getters also count — call them on the UI thread.

    line 64

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Thonny plugin authoring

Thonny discovers 3rd-party plugins at startup: any module or package under the thonnycontrib namespace exposing a parameterless load_plugin(), which Thonny calls exactly once. Everything else is convention around that.

Layout

thonnycontrib/
    __init__.py          # empty (namespace marker; a regular package works,
                         # but then this directory shadows namespace installs
                         # anywhere earlier on sys.path)
    my_plugin/
        __init__.py      # defines load_plugin()

load_plugin() registers with the workbench — typically get_workbench().add_command(...) and/or get_workbench().add_view(...). Keep a module-level reference to anything that must outlive the call (servers, threads); Thonny keeps only what you bind or thread yourself.

Install location (the failure that matters)

Thonny's interpreter runs isolated (no_user_site=1, ignore_environment=1, isolated=1 — confirm with <thonny python> -c "import sys; print(sys.flags)"). Its plugin loader only looks in Thonny's own plugin folder:

  • <Thonny user data folder>/plugins/ plus the user-site layout of Thonny's Python: PythonXY\site-packages on Windows, lib/pythonX.Y/site-packages on Linux, lib/python/site-packages for a macOS framework Python. Put thonnycontrib/ inside that.
  • The user data folder: %APPDATA%\Thonny (Windows), ~/Library/Thonny (macOS), $XDG_CONFIG_HOME/Thonny or ~/.config/Thonny (Linux); user_data beside the program for a portable Thonny; THONNY_USER_DIR overrides all of them. Tools > "Open Thonny data folder..." opens it.
  • Example (Windows, Thonny 5.0.1 with Python 3.14): %APPDATA%\Thonny\plugins\Python314\site-packages\thonnycontrib\
  • NOT the interpreter's user-site (e.g. %APPDATA%\Python\Python314\site-packages): it is not on Thonny's path, so a plugin installed there silently never loads — no error, no menu item, nothing in the log.
  • After copying, strip __pycache__ and restart Thonny (full quit; the new process is what loads it). Verify with the menu item, not the import.

UI-thread rule

HTTP threads, background threads, and timers must never touch Tk or Thonny objects directly. Marshal with get_workbench().after(0, fn) and block the worker on a queue.Queue for the result (10 s timeout is plenty). Read-only Tk getters also count — call them on the UI thread.

Test ladder (each step proves strictly more)

  1. Syntax/import with Thonny's bundled interpreter (Windows: %LOCALAPPDATA%\Programs\Thonny\python.exe; never a bare python, which on Windows may be the Microsoft Store stub). Proves the file parses and load_plugin exists. Proves nothing about loading. Running the file directly (python.exe plugin.py) proves even less — it never calls load_plugin.
  2. Restart Thonny, check the Tools menu (or view) for your item. Absent item = wrong install location (see above) or an exception at load — the latter IS logged (frontend.log in the user data folder; look for "Failed loading plugin"). No log error + no item = location problem.
  3. Exercise it live against the running Thonny (click it; or call its HTTP endpoint if it serves one). Import checks cannot replace this.

API reference

Verified against Thonny 5.0.1 — do not trust memory or newer upstream; signatures drift (e.g. get_current_breakpoints() keys by get_filename() in 5.0.1). Re-verify anything not listed with inspect.signature/inspect.getsource against the installed thonny package (Windows: %LOCALAPPDATA%\Programs\Thonny\Lib\site-packages\thonny\). Full table: references/api-5.0.1.md.

Gotchas

  • Thonny runs the file on disk, not the editor buffer — a "run this" feature must save first (save_all_named_editors()), or it executes stale code.
  • WorkbenchClose fires only on window close (workbench.py:_on_close is its sole event_generate). Cleanup bound to it never runs otherwise; files your plugin writes are never auto-removed while Thonny lives.
  • Two localhost listeners on one Thonny pid is normal. Thonny's own single-instance IPC server binds 127.0.0.1:0 (_create_server_socket). It accepts-then-hangs on HTTP and logs ast.literal_eval errors for GET /ping in frontend.log. Don't mistake it for your server, and don't probe unknown localhost ports with HTTP unless you accept log spam.
  • Windows liveness: os.kill(pid, 0) raises WinError 87 even for live GUI processes of the same user — it cannot distinguish them from dead PIDs. Probe with ctypes OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION): non-NULL handle (or access-denied) = alive, NULL + error 87 = dead.
  • Breakpoints mirror gutter clicks: tag_add("breakpoint_line", ...) on the code view text + update_gutter(); skip blank/# lines; read back with editors.get_current_breakpoints().

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.