agentleFS
rjstonerjstone/agent-skills/skills/capturing-tk-screenshots-headless/SKILL.md

capturing-tk-screenshots-headless

Skill0 starsChanged 6 days agoMITView on GitHub

Use when a Tkinter, Thonny, IDLE or other Tk/X11 desktop GUI must be run, seen or screenshotted in a headless Linux sandbox or CI with no monitor - "no display name and no $DISPLAY environment variable", black or overlapping captures, checking UI/editor themes, fonts, glyphs or emoji rendering, or showing a person what a widget looks like.

The file

We split this skill into the rules it gives an agent

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

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Run the GUI on a virtual X server (Xvfb) and capture with ImageMagick import.

    line 15
  2. Very specific:

    Use a Python that has tkinter: python -c "import tkinter".

    line 18
  3. Distinctive:

    Keep scratch files out of the project.

    line 48

≈ “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

Capturing Tk screenshots headless

Overview

Run the GUI on a virtual X server (Xvfb) and capture with ImageMagick import. There is no window manager: no title bars, every window opens at 0,0, and import -window <id> copies whatever is on screen in that window's rectangle, including other windows covering it.

Before you start

  • Use a Python that has tkinter: python -c "import tkinter". Sandbox system python3 often lacks it; a venv with Thonny or python3-tk has it.
  • Tools: Xvfb, xvfb-run, import, convert (ImageMagick). Often missing: xdotool, xwininfo, scrot. Don't plan on them.

Recipe A: your own widget or test window

xvfb-run -a -s "-screen 0 1600x1200x24" PY capture.py
import subprocess, tkinter as tk
root = tk.Tk(); root.withdraw()
wins = [make_window_1(root), make_window_2(root)]      # your Toplevels
for i, w in enumerate(wins, 1):
    for o in wins:                                       # show ONE window at a time
        o.deiconify() if o is w else o.withdraw()
    root.update(); root.after(300); root.update()        # let Tk finish drawing
    subprocess.run(["import", "-window", str(w.winfo_id()), f"win{i}.png"], check=True)
root.destroy()

Skip mainloop() in capture scripts; update() draws everything.

Recipe B: a real application (Thonny, IDLE, ...)

  1. Xvfb :77 -screen 0 1200x800x24 & (explicit display number, screen = desired image size).
  2. Give the app a throwaway config dir with theme, font size and window geometry preset to fill the screen at 0,0 (most apps take a config-directory environment variable or option; check the app's docs). An empty config dir often opens a first-run or welcome dialog instead of the main window: preset the settings that skip it. Never touch the user's real config.
  3. Open a file with real content so themes, syntax colors and fonts are visible.
  4. Launch with DISPLAY=:77 ... &, then wait for it to settle instead of sleeping a guessed time: python3 scripts/grab_stable.py :77 out.png (waits until the screen is non-blank and stops changing, tolerates a blinking cursor; --crop WxH+X+Y, --timeout).
  5. Kill the app, then Xvfb. Read the app's log for "Could not find ..." warnings.

Always

  • Open every PNG yourself (whatever image-viewing tool your harness has) before reporting, and describe what it actually shows: a capture that ran without errors can still be black, half-drawn or the wrong window.
  • Keep scratch files out of the project; hand finished images to the person with your harness's file-sharing mechanism.
  • Captures are 1:1 pixels at Tk's 1x rendering.
  • Running in Claude Code? Also read claude-code.md for its tool names and container notes.

Common mistakes

SymptomCause / fix
Black or another window inside a captureWindows overlap at 0,0: show one at a time, or place with geometry("+X+Y") and crop -window root
Capture of a half-built windowMissing update()/after(), or fixed sleep too short: use grab_stable.py
App ignored the themeWrong theme name or UI vs editor theme mixed up; check log
App at an offset on a black screenGeometry not preset; screen size not matched
Emoji gray/outline, extra blank cell after ⬅️Tk 8.6 draws no color emoji; U+FE0F takes a cell. fc-list ":charset=274c" family shows which font supplies a glyph
OSError: AF_UNIX path too long at launchThe app's socket path (under a long config or runtime dir) exceeds the ~108-byte limit: use a shorter dir, or set XDG_RUNTIME_DIR to one
Fonts differ from the user's OSSandbox fonts (e.g. DejaVu) ≠ Windows Consolas/Segoe; say so

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.