Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Installing and self-checking

✅ verified · the setup, self-check and ComfyUI scripts are listed in appendix A · the code behind them: appendix B

What you need

thingversion and notes
Fedora44. No other distribution has been tried; the package names here are Fedora’s
Krita6.0 or newer, installed from RPM. Node.paintLine and paintPath are new in 6.0 and are the foundation of all of this; 5.x leaves only injected tablet events (coordinate calibration unknowable, strokes landing only on the first layer, saveAs segfaulting, throughput a few hundred strokes a minute) and is not supported. Flatpak does not work either: the sandboxed Python has no numpy, and the paths are moved to ~/.var/app/org.kde.krita/
XvfbHeadless Krita still needs an X display (QT_QPA_PLATFORM=offscreen segfaults)
uv0.12 or newer. The library is a uv workspace whose member is dtp/
the system PythonKrita embeds the system Python (3.14). The numpy / Pillow / scipy / scikit-learn a job imports have to be system packages; it cannot see the ones in a venv
ComfyUIThree stages need it (segment, lineart, per-layer lineart), through two custom_nodes: comfyui_controlnet_aux (lineart) and comfyui_segment_anything (GroundingDINO + SAM). 16 GB of VRAM is enough
See-throughCompletion needs it (ch. 3). It lives in see-through/ (beside dtp/; seethrough_dir in dtp.toml) with its own venv (torch 2.8 + cu128, transformers 5.0, diffusers 0.37 – leave ComfyUI’s alone), and its weights download from Hugging Face on the first run. 12 GB of VRAM or more, and stop ComfyUI before running it
sudo dnf install krita python3-numpy python3-pillow python3-scipy python3-scikit-learn python3-matplotlib xorg-x11-server-Xvfb
cd Krita/ && uv sync          # the library's dependencies (numpy scipy pillow scikit-learn matplotlib) plus pytest
uv run pytest                 # the library's unit tests, which never touch Krita

ComfyUI lives in ComfyUI/ (beside dtp/ and diffusion-to-painting/; the location can be changed with comfy_dir in dtp.toml or DTP_COMFY_DIR) with its own .venv (Python 3.12, torch + cu130, transformers 5). ComfyUI itself is not modified; only custom_nodes and models are added. comfyui_segment_anything needs two patches on transformers 5 (in local_groundingdino/models/GroundingDINO/bertwarper.py: BertModel.get_head_mask is gone, so pass None; and the third positional argument of get_extended_attention_mask became a dtype, so drop it), with the originals kept as .orig.

The harness: a separate HOME

Running jobs in headless Krita rests on a separate HOME, krita-bot/ (the location can be changed with harness_home in dtp.toml). The harness script (appendix A) creates it; it is idempotent and is done once:

krita-bot/
  run_job.sh                                   the launcher
  .config/kritarc                              the minimal config: autosave off, undoStackLimit=3
  .local/share/krita/pykrita/autopaint/        a Krita extension: 3s after startup it execs
                                               $KRITA_JOB, then os._exit

Two reasons for a separate HOME: a batch job’s settings never pollute your own Krita preferences, and rm *autosave*.kra cannot reach your real recovery files.

What run_job.sh does: sets HOME, XDG_RUNTIME_DIR, LANG=C.UTF-8 and PYTHONIOENCODING=utf-8, puts every package’s src on PYTHONPATH (colon-separated: the library is one distribution per rank, all sharing the one dtp. namespace), deletes any leftover *autosave*.kra, and runs xvfb-run -a krita --nosplash (with --gui it runs on a real desktop, which is how tools/gui.py <step dir> replays a step). The job process imports the library’s source directly – no code is copied, and changing the library needs no re-setup. Before starting Krita, harness.run_job() strips the uv venv’s PYTHONHOME, PYTHONPATH, VIRTUAL_ENV and .venv/bin: Krita’s embedded system Python reads them, its plugin system fails to start (“Please make sure that the needed packages are installed”), and the job never begins while the process hangs.

31 self-checks

The self-check script (appendix A) starts Krita once and really runs each check, reading the pixels back: version at least 6 / filling the ground / preset / stroke / path / ellipse / a selection confining and releasing / select_mask feathering / erase / a filter’s box / blending / stage and final saving / the output layout / building the tree / nesting order / the GroupLayer type / addressing / by_role / by_label / rejecting a duplicate name / clipping / a partial box read and write / the manifest / the .kra round trip (layer count, clip, blend / opacity / label). After changing the session wrapper, all of them have to pass.

ComfyUI

uv run python dtp/tools/comfy.py     # starts on 127.0.0.1:8188 in the background, logging to work/comfy.log; exits 1 if it is not up within 60 seconds
fuser -k 8188/tcp             # to stop it: kill by port

Which stages need it: segment (one mask per SAM word), lineart (extracting lineart) and lines (one lineart per layer). complete (See-through, its own process), trace, draft, paint and gauge do not. ComfyUI’s output is cached in the step’s ai/, and it is not called again when that is present. The driver is HTTP (POST /prompt plus polling /history); LoadImage only accepts a filename under ComfyUI/input/, so the driver copies the file there first.

How far each model can be trusted: lineart extraction is discriminative and steady; text-prompted segmentation depends on the word (ch. 1). The completion model (See-through) is generative, so only the shape and pixels of what is hidden are taken from it, and every one of them is reviewed (ch. 3).

It will not start, or it dies halfway

symptomcausefix
Krita segfaults on startupQT_QPA_PLATFORM=offscreenIt needs Xvfb or a real display (run_job.sh already uses xvfb-run)
the job never starts and the process hangsKrita was started from inside a uv venv, carrying VIRTUAL_ENV / PYTHONHOME in with itharness.run_job() already strips them; do the same if you start it yourself
print("中文") raises UnicodeEncodeError partway throughonly LANG was setPYTHONIOENCODING=utf-8 has to be set too, and job files must be read with encoding='utf-8'
every later run fails with no error and no tracebackan autosave left by a crash popped up the recovery dialogrm -f krita-bot/*autosave*.kra (run_job.sh deletes them every time too), and EnableAutosave=false
a segfault in the C++ layer, with no Python tracebackpaint* was called with no viewSession.__init__ already calls addView; if you create a document yourself you must too
the criteria report on the previous round’s outputa failed job was swallowedthe harness raises on JOB FAIL; do not work around it
“the harness is not installed”krita-bot/ was deletedrun the harness script, then the self-check (appendix A)

Ending a session kills the background processes and can leave a krita zombie: pkill -x krita and rerun. Do not pkill -f "<a pattern that matches your own command line>", and do not for pid in $(pgrep -f ...) grepping your own keyword either – both kill the shell that issued the command (exit 144). Before starting a long job, pgrep -a -f main.py shows whether one is still running from an earlier session.