Agent Use

This repository is intended to be usable by coding agents, not only by human readers.

What An Agent Should Read First

Recommended order:

  1. llms.txt

  2. specification.md

  3. architecture.md

  4. release.md for packaging/release tasks

  5. decisions.md

  6. repo-local skill at skills/wrap-existing-django-in-electron/SKILL.md

What This Repo Should Help An Agent Do

  • understand the minimum desktop-Django architecture quickly

  • identify the integration seams in an existing Django codebase

  • avoid copying djdesk product complexity into a smaller project

  • preserve a server-rendered Django app while adding an Electron shell

  • plan for packaging, Windows behavior, signing, and update constraints early

Guardrails For Agents

  • keep the app generic and minimal unless the target repo already has domain complexity

  • prefer server-rendered templates over a SPA rewrite

  • keep the preload bridge narrow

  • do not assume DEBUG=True behavior in packaged mode

  • do not assume online-only update flows; account for air-gapped environments

  • do not import djdesk code wholesale

Wrapping An Existing Django Project

This repo provides an automated workflow for wrapping an existing Django project in an Electron shell using an AI coding agent.

Quick start

From inside the target Django project:

# Preflight: checks the target repo and prints the agent command
~/projects/desktop-django-starter/scripts/wrap

# Run the agent
~/projects/desktop-django-starter/scripts/wrap --run

This requires an existing desktop-django-starter checkout on disk. The starter repo is inferred from the script’s location, or specified with --starter:

~/projects/desktop-django-starter/scripts/wrap --starter ~/projects/desktop-django-starter

The packaged CLI can be run without a local starter checkout:

uvx desktop-django-starter init
uvx desktop-django-starter wrap --run
uvx desktop-django-starter wrap --run --harness pi --model openai-codex/gpt-5.4

dds init saves a user-level default harness plus an optional freeform default model. Then dds wrap --run resolves the harness in this order: explicit CLI flags, saved config, then auto-detect when exactly one supported harness is installed. If no config exists yet and stdin is a TTY, wrap --run launches the same setup flow inline. Non-interactive runs never prompt; if the harness is ambiguous they fail and point to dds init or --harness.

When using the claude harness, current dds builds stream concise progress while the agent works. Older builds delegated to Claude’s default -p text output, which could make a long wrapping run look idle until Claude exited. Use --harness and --model to choose the agent harness and model. --agent remains available as a backward-compatible alias.

After wrapping, the target repo has an electron/ directory and justfile targets:

just desktop-dev          # Electron + Django dev mode
just desktop-dev-smoke    # headless boot + health check
npm --prefix electron test  # node-side tests

Benchmarking local models with Ollama

For local-model experiments, benchmark the real wrap prompt before running the agent. The repo includes a small helper script for this:

# Terminal 1
ollama serve

# Terminal 2
~/projects/desktop-django-starter/scripts/bench-wrap-local-models \
  --target ~/projects/django-resume \
  --pull

By default the script compares qwen3-coder and glm-4.7-flash. It generates the resolved wrap prompt with scripts/wrap --emit-prompt, appends a snapshot of the target repo, sends the benchmark prompt to Ollama’s /api/generate, and writes:

  • the exact prompt used

  • raw Ollama responses per model

  • a summary.tsv table with prompt tokens, prompt tokens/sec, generated tokens, generated tokens/sec, model load time, and total wall time

The helper disables model-native thinking by default so the generated-output comparison is visible and stable across models. If you want to include each model’s native thinking behavior in the benchmark, add --with-thinking.

The default context request is 32768, which is a conservative starting point for 64 GB shared-memory systems. Increase it only after the smaller context works:

~/projects/desktop-django-starter/scripts/bench-wrap-local-models \
  --target ~/projects/django-resume \
  --num-ctx 65536

When you are ready to try a real wrapping run with Pi through Ollama, configure Pi for Ollama first and then run the standard CLI from a clean target repo clone:

ollama launch pi --config --model qwen3-coder

cd ~/projects/django-resume-clean
time uvx desktop-django-starter wrap --run --harness pi --model ollama/qwen3-coder

Use a clean clone or disposable worktree for these tests. wrap --run edits the target repository.

For smaller local models that drift on the one-shot wrap prompt, use the experimental staged workflow in skills/wrap-existing-django-in-electron-staged/ instead of editing the original wrap skill. That path starts with a deterministic scaffold helper and then narrows the model work into separate Electron, Django, and fix-from-failures prompts.

The scaffold prepares the wrapped target for those later stages by:

  • adapting the brittle Electron identity and wrapped-repo path boilerplate before Stage 2 starts, including electron/package.json

  • recording deterministic target facts in electron/wrap-target.json, including development and packaged manage/settings paths

  • laying down the common Django desktop baseline for Stage 3 so local models verify or narrowly adjust it instead of building packaged settings and middleware from scratch

  • appending explicit target-side just shortcuts such as just desktop-install, just desktop-stage, just desktop-packaged-start, and just desktop-smoke

  • enabling desktop auto-login defaults in the wrapped Electron runtime, with a single-user fallback when no username override is configured

  • adding a minimal native Home, Back, and Forward menu plus small in-page back-to-list links for known wrapped-template shapes such as django_resume’s headwind pages

Stage 2 and Stage 3 are both verification-first and stop-early. Once the required checks for a stage pass, the model should end that stage instead of re-reading scaffolded files. If a target app still has no persistent in-page navigation after the native menu is in place, Stage 3 may add the smallest possible Django-side home/list link.

The Django scaffold handles both flat settings modules and common settings/ package layouts, including targets that need the desktop middleware inserted into a shared base settings file. It also covers targets with no committed seed SQLite database by generating a small runtime bootstrap that can run migrations on the first real desktop app request. It still assumes a recognizable urlpatterns = [ layout rather than arbitrary project structure.

Lab workflow (experiment harness)

For iterating on the wrapping skill itself, the desktop-django-lab tooling creates paired worktrees for reset-and-rerun experiments:

# Create a paired workspace for any target Django app
djl new wiki-demo ~/projects/django-wiki

# Run the agent from the target worktree
cd ~/workspaces/wiki-demo/django-wiki
time claude --dangerously-skip-permissions \
  -p "$(cat ../desktop-django-starter/skills/wrap-existing-django-in-electron/prompt.md)" \
  --add-dir ../desktop-django-starter

# Reset for another run
djl reset wiki-demo

The lab tooling lives in dotfiles (~/.config/desktop-django-lab/), not in this repo.

Key files

  • scripts/wrap — front-door command for wrapping a target Django project

  • skills/wrap-existing-django-in-electron/SKILL.md — the wrapping workflow, strategy, output shape, and verification steps

  • skills/wrap-existing-django-in-electron/prompt.md — the prompt template used by scripts/wrap and the lab workflow

  • skills/wrap-existing-django-in-electron/run-log.md — results from each test run, with git refs linking to the skill/prompt version used

  • skills/wrap-existing-django-in-electron-staged/SKILL.md — experimental staged alternative for smaller local models

  • skills/wrap-existing-django-in-electron-staged/scripts/scaffold-target.sh — deterministic stage-1 scaffold helper

  • skills/wrap-existing-django-in-electron-staged/prompt-stage-2-electron.md, prompt-stage-3-django.md, prompt-stage-4-fix-from-failures.md — narrower stage prompts for reset-and-rerun experiments

  • skills/wrap-existing-django-in-electron-staged/run-log.md — staged experiment log

Iteration loop

  1. Create a fresh workspace with the lab tooling (djl new)

  2. Run the agent with the prompt (timed)

  3. Check results against the verification steps in the skill

  4. Record the run in run-log.md (see instructions in that file)

  5. If it failed: improve the skill or prompt, commit, reset workspace, re-run

The workspace is disposable — reset and re-create freely. The skill, prompt, and run log live in this repo and persist across workspace resets.

Verification tiers

  • Tier 1 (dev mode): existing tests pass, just desktop-dev-smoke passes, root URL returns 200/302, npm --prefix electron test passes

  • Tier 2 (packaged mode): just desktop-stage and just desktop-smoke pass

  • Tier 3 (CI/cross-platform): GitHub Actions packaging on Linux, macOS, Windows

Repo Outputs For Agents

  • llms.txt provides a concise entry point

  • the specification defines the product and technical boundaries

  • the architecture notes define the expected runtime contract

  • the release guide defines signing inputs, installer artifacts, and the manual update model

  • the skill provides a reusable workflow for adapting another Django repo

  • the run log tracks iteration results and links them to skill/prompt versions