{
  "id": "django-6-upgrade-guard",
  "type": "loadout",
  "title": "Django 6 guard for removed APIs and django-upgrade",
  "summary": "Stop agents writing url(), ugettext, is_ajax(), index_together and CheckConstraint(check=) into Django 6.1 projects, then run django-upgrade and Django's own checks.",
  "description": "Agents learnt Django from a decade of answers, so they still write url(), ugettext_lazy, force_text, request.is_ajax(), Meta.index_together and {% load staticfiles %}. All of those are gone, and Django 6.0 and 6.1 removed more: CheckConstraint(check=), positional Model.save() arguments, format_html() with no arguments, finders.find(all=) and the Postgres aggregates' ordering=. Django 6.1 also moves mail settings into MAILERS and adds fetch modes.\n\nThis loadout pairs a short Cursor rule and AGENTS.md (a never/always table and the Django 6 version facts) with a skill that checks the work in three layers. A standard-library Python scanner reports removed APIs as errors and behaviour changes as warnings. django-upgrade rewrites what it safely can. Then manage.py check, makemigrations --check and the tests run with the next two deprecation warnings raised as errors. The verifier runs all of it on a small Django 6.1 shop project and a Django 3-era sample, with the pinned Django 6.1.2 and django-upgrade 1.33.0.\n",
  "highlights": [
    "Never/always table for Django 6.1 in a Cursor rule for .py and templates",
    "Scanner flags 17 removed Django APIs as errors, read-only",
    "Runs django-upgrade --check at target 6.1 alongside the scanner",
    "Tests run with RemovedInDjango70Warning and RemovedInDjango2028Warning as errors",
    "Covers 6.1's MAILERS setting and FETCH_RAISE for N+1 queries"
  ],
  "version": "1.0.0",
  "license": "MIT",
  "author": {
    "name": "SetupBay",
    "url": "https://setupbay.com"
  },
  "credits": [
    {
      "title": "Django 6.0 release notes",
      "url": "https://docs.djangoproject.com/en/6.1/releases/6.0/"
    },
    {
      "title": "Django 6.1 release notes",
      "url": "https://docs.djangoproject.com/en/6.1/releases/6.1/"
    },
    {
      "title": "Django deprecation timeline",
      "url": "https://docs.djangoproject.com/en/dev/internals/deprecation/"
    },
    {
      "title": "django-upgrade by Adam Johnson",
      "url": "https://github.com/adamchainz/django-upgrade"
    },
    {
      "title": "Django 6.1.2 on PyPI (released 6 Oct 2026)",
      "url": "https://pypi.org/project/Django/6.1.2/"
    },
    {
      "title": "@rg3915: Django 6.1 moves email settings into MAILERS",
      "url": "https://x.com/rg3915/status/2111940396993421802"
    },
    {
      "title": "@rg3915: Django 6.1 fetch modes make N+1 queries an error",
      "url": "https://x.com/rg3915/status/2112665164847653174"
    }
  ],
  "categories": [
    "web-app"
  ],
  "stacks": [
    "django",
    "python",
    "uv"
  ],
  "files": [
    {
      "path": "AGENTS.md",
      "role": "instructions",
      "description": "Django 6 version facts, rules and the done checklist.",
      "skill": null,
      "agent": null,
      "install_to": {
        "claude-code": "AGENTS.md",
        "codex": "AGENTS.md",
        "cursor": "AGENTS.md",
        "gemini-cli": "AGENTS.md",
        "antigravity-cli": "AGENTS.md",
        "copilot": "AGENTS.md"
      },
      "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/AGENTS.md",
      "raw_latest_url": "https://setupbay.com/raw/django-6-upgrade-guard/latest/AGENTS.md",
      "bytes": 2892,
      "lang": "markdown",
      "content": "# AGENTS.md: Django 6 project (old Django guard)\n\nThis project runs **Django 6.1** on Python 3.12 or later. Much of the Django code you remember is from 2.x–4.x,\nand Django has removed a lot since then: `url()`, `ugettext`, `force_text`, `is_ajax()`, `index_together`,\n`NullBooleanField`, and in 6.0 and 6.1 `CheckConstraint(check=)`, positional `Model.save()` arguments and more.\n\n## Version facts\n- Check the pin first: `uv run python -m django --version`.\n- Django 6.0 needs Python 3.12+, defaults `DEFAULT_AUTO_FIELD` to `BigAutoField`, and assumes `https` in\n  `forms.URLField`. It also adds built-in CSP support, template partials and a background Tasks framework (`django.tasks`).\n- Django 6.1 removes the 5.2 deprecations, for example `finders.find(all=)` → `find_all=`, and\n  `ArrayAgg(ordering=)` → `order_by=`. `login(request, None)` no longer falls back to `request.user`.\n- Django 6.1 deprecates the `EMAIL_*` connection settings: configure mail in `MAILERS`\n  (`{\"default\": {\"BACKEND\": ..., \"OPTIONS\": {...}}}`), in the same style as `DATABASES` and `CACHES`.\n- Django 6.1 adds fetch modes: `Order.objects.fetch_mode(models.FETCH_RAISE)` turns a lazy load (an N+1) into an\n  error, and `FETCH_PEERS` loads the field for every instance from the same query at once.\n- Deprecation warnings for the next removals are `RemovedInDjango70Warning`, then `RemovedInDjango2028Warning`\n  (the class name says which release removes them).\n- If you're not sure an API exists, check the docs for this version (https://docs.djangoproject.com/en/6.1/) and\n  the release notes, not old tutorials.\n\n## Rules\n- Write Django 6 code only. The `django-6-guard` skill has the full table. The common ones are: `path()` /\n  `re_path()`, `gettext_lazy`, `force_str`, `CheckConstraint(condition=)`, `save(update_fields=[...])` with keywords,\n  `Meta.indexes`, `BooleanField(null=True)`, `{% load static %}`, `datetime.UTC` / `zoneinfo`.\n- Run `django-upgrade --target-version 6.1` on files you change. It rewrites many old forms safely.\n- Every model change comes with a migration made by `makemigrations`. Never write or edit migrations by hand to \"fix\" a check.\n- For simple background jobs, look at `django.tasks` before adding Celery, and ask the human.\n- Don't change the Django version or `DEFAULT_AUTO_FIELD` in an existing project without asking.\n\n## Before you say \"done\"\n1. Run the `django-6-guard` scanner on the apps and templates you touched. It must report `0 error(s)`.\n2. Run `django-upgrade --check --target-version 6.1` on the changed `.py` files. It must report nothing to rewrite.\n3. Run `python manage.py check` and `python manage.py makemigrations --check --dry-run`.\n4. Run the tests with next-version deprecations as errors:\n   `python -W error::django.utils.deprecation.RemovedInDjango70Warning -W error::django.utils.deprecation.RemovedInDjango2028Warning manage.py test`.\n"
    },
    {
      "path": "CLAUDE.md",
      "role": "adapter",
      "description": "Imports AGENTS.md for Claude Code.",
      "skill": null,
      "agent": "claude-code",
      "install_to": {
        "claude-code": "CLAUDE.md",
        "codex": null,
        "cursor": null,
        "gemini-cli": null,
        "antigravity-cli": null,
        "copilot": null
      },
      "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/CLAUDE.md",
      "raw_latest_url": "https://setupbay.com/raw/django-6-upgrade-guard/latest/CLAUDE.md",
      "bytes": 393,
      "lang": "markdown",
      "content": "# CLAUDE.md\n\n@AGENTS.md\n\n## Claude Code notes\n\n- Skills from this loadout live in `.claude/skills/`: `django-6-guard`. Use them when their description matches the task.\n- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.\n\n<!-- From SetupBay \"Django 6 guard for removed APIs and django-upgrade\" v1.0.0 — https://setupbay.com/loadouts/django-6-upgrade-guard/ -->\n"
    },
    {
      "path": "GEMINI.md",
      "role": "adapter",
      "description": "Imports AGENTS.md for Gemini CLI.",
      "skill": null,
      "agent": "gemini-cli",
      "install_to": {
        "claude-code": null,
        "codex": null,
        "cursor": null,
        "gemini-cli": "GEMINI.md",
        "antigravity-cli": null,
        "copilot": null
      },
      "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/GEMINI.md",
      "raw_latest_url": "https://setupbay.com/raw/django-6-upgrade-guard/latest/GEMINI.md",
      "bytes": 394,
      "lang": "markdown",
      "content": "# GEMINI.md\n\n@./AGENTS.md\n\n## Gemini CLI notes\n\n- Skills from this loadout live in `.agents/skills/`: `django-6-guard`. Use them when their description matches the task.\n- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.\n\n<!-- From SetupBay \"Django 6 guard for removed APIs and django-upgrade\" v1.0.0 — https://setupbay.com/loadouts/django-6-upgrade-guard/ -->\n"
    },
    {
      "path": ".cursor/rules/django-6-only.mdc",
      "role": "rules",
      "description": "Never/always table for Python files and templates.",
      "skill": null,
      "agent": null,
      "install_to": {
        "claude-code": null,
        "codex": null,
        "cursor": ".cursor/rules/django-6-only.mdc",
        "gemini-cli": null,
        "antigravity-cli": null,
        "copilot": null
      },
      "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/.cursor/rules/django-6-only.mdc",
      "raw_latest_url": "https://setupbay.com/raw/django-6-upgrade-guard/latest/.cursor/rules/django-6-only.mdc",
      "bytes": 1266,
      "lang": "markdown",
      "content": "---\ndescription: Django 6.1 only; no APIs removed in Django 4.0 to 6.1\nglobs: \"**/*.py,**/templates/**/*.html\"\nalwaysApply: false\n---\n\nThis project runs Django 6.1 (Python 3.12+). Never write removed Django APIs.\n\n| Never | Always (Django 6.1) |\n|---|---|\n| `from django.conf.urls import url`; `url(r\"^x/$\", v)` | `path(\"x/\", v)` or `re_path(r\"^x/$\", v)` |\n| `ugettext`, `ugettext_lazy` | `gettext`, `gettext_lazy` |\n| `force_text`, `smart_text` | `force_str`, `smart_str` |\n| `request.is_ajax()` | check the `Accept` or `X-Requested-With` header yourself |\n| `Meta.index_together` | `Meta.indexes = [models.Index(fields=[...])]` |\n| `models.NullBooleanField()` | `models.BooleanField(null=True)` |\n| `CheckConstraint(check=Q(...))` | `CheckConstraint(condition=Q(...))` |\n| `obj.save(False, False)` | `obj.save(update_fields=[...])` (keywords only) |\n| `format_html(\"<b>fixed</b>\")` | `mark_safe(...)`, or `format_html(\"<b>{}</b>\", value)` |\n| `finders.find(p, all=True)` | `finders.find(p, find_all=True)` |\n| `timezone.utc`, `pytz` | `datetime.UTC`, `zoneinfo.ZoneInfo` |\n| `{% load staticfiles %}` | `{% load static %}` |\n\n- After editing, run the `django-6-guard` skill's scanner, `django-upgrade --check --target-version 6.1`, `manage.py check` and the tests.\n"
    },
    {
      "path": "skills/django-6-guard/SKILL.md",
      "role": "skill",
      "description": "Scan for removed Django APIs, run django-upgrade, then Django's checks and the tests with deprecations as errors.",
      "skill": "django-6-guard",
      "agent": null,
      "install_to": {
        "claude-code": ".claude/skills/django-6-guard/SKILL.md",
        "codex": ".agents/skills/django-6-guard/SKILL.md",
        "cursor": ".agents/skills/django-6-guard/SKILL.md",
        "gemini-cli": ".agents/skills/django-6-guard/SKILL.md",
        "antigravity-cli": ".agents/skills/django-6-guard/SKILL.md",
        "copilot": ".agents/skills/django-6-guard/SKILL.md"
      },
      "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/SKILL.md",
      "raw_latest_url": "https://setupbay.com/raw/django-6-upgrade-guard/latest/skills/django-6-guard/SKILL.md",
      "bytes": 2684,
      "lang": "markdown",
      "content": "---\nname: django-6-guard\ndescription: Check a Django project for APIs removed between Django 4.0 and 6.1, run django-upgrade and Django's own checks, before saying a Django change is done. Use after writing or editing models, views, URLs, settings or templates, when Django raises an unexpected keyword or missing attribute error, or when porting older Django snippets or tutorials.\n---\n\n# Django 6 guard\n\nAgents trained on years of Django answers still write `url()`, `ugettext_lazy`, `force_text`, `request.is_ajax()`,\n`index_together` and `{% load staticfiles %}`. All of those are gone. Django 6.0 and 6.1 removed more, including\n`CheckConstraint(check=)`, positional `Model.save()` arguments, `format_html()` without arguments,\n`finders.find(all=)` and the Postgres aggregates' `ordering=`. This skill finds them, lets `django-upgrade` rewrite\nwhat it can, then lets Django check the rest.\n\n## 1. Confirm the version\n- `uv run python -m django --version` should print `6.1.x`. If it doesn't, ask before changing code for a different version.\n\n## 2. Scan\n```bash\npython3 .agents/skills/django-6-guard/scripts/django6_guard.py shop templates\n```\n(Use the path the skill was installed to: `.claude/skills/...` for Claude Code, `.agents/skills/...` for the others.)\n\n- Every `error` line is a removed API. Fix it with the replacement on the line. `references/removals.md` says which\n  release removed each one.\n- `warn` lines are behaviour changes to decide on: `login(request, None)`, an explicit `AutoField` default,\n  positional mail arguments, `EMAIL_*` settings that now belong in `MAILERS`, or Celery added where `django.tasks` might do.\n\n## 3. Let django-upgrade rewrite what it safely can\n```bash\nuvx --from django-upgrade==1.33.0 django-upgrade --target-version 6.1 shop/*.py\n```\n- Then run it again with `--check`. It must print nothing. Review its diff like any other change.\n- It doesn't cover everything the scanner does (for example `NullBooleanField` or `CheckConstraint(check=)`),\n  so run both.\n\n## 4. Let Django check it\n```bash\npython manage.py check\npython manage.py makemigrations --check --dry-run\npython -W error::django.utils.deprecation.RemovedInDjango70Warning \\\n       -W error::django.utils.deprecation.RemovedInDjango2028Warning manage.py test\n```\n- `check` reports removed fields as system-check errors (for example `fields.E903` for `NullBooleanField`).\n- If `makemigrations --check` wants a migration, create it with `makemigrations` and include it in the change.\n\n## 5. Report\nSay which removed APIs you replaced, what django-upgrade rewrote, any migration you added, and that the scanner,\n`check`, `makemigrations --check` and the tests were clean.\n"
    },
    {
      "path": "skills/django-6-guard/scripts/django6_guard.py",
      "role": "reference",
      "description": "Read-only scanner for removed Django APIs and Django 6 behaviour changes.",
      "skill": "django-6-guard",
      "agent": null,
      "install_to": {
        "claude-code": ".claude/skills/django-6-guard/scripts/django6_guard.py",
        "codex": ".agents/skills/django-6-guard/scripts/django6_guard.py",
        "cursor": ".agents/skills/django-6-guard/scripts/django6_guard.py",
        "gemini-cli": ".agents/skills/django-6-guard/scripts/django6_guard.py",
        "antigravity-cli": ".agents/skills/django-6-guard/scripts/django6_guard.py",
        "copilot": ".agents/skills/django-6-guard/scripts/django6_guard.py"
      },
      "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/scripts/django6_guard.py",
      "raw_latest_url": "https://setupbay.com/raw/django-6-upgrade-guard/latest/skills/django-6-guard/scripts/django6_guard.py",
      "bytes": 7783,
      "lang": "markdown",
      "content": "#!/usr/bin/env python3\n\"\"\"Find Django code removed by 6.0 and 6.1 (and older removals agents still write) in a Django 6 project.\n\nUsage: python3 django6_guard.py [PATH ...]        (default: the current folder)\n       python3 django6_guard.py --list            (print every rule)\n\nA \"guard: ok\" comment on a line silences its warnings (never its errors).\nPrints one line per finding:  path:line: level [rule] what is wrong -> what to use\nExit 0 when nothing at \"error\" level is found, 1 when something is, 2 on bad usage.\nStandard library only. Read-only: it never edits a file and makes no network calls.\n\"\"\"\nimport fnmatch\nimport os\nimport re\nimport sys\n\n# (rule id, level, regex, message, file patterns). Patterns run against each line with comments removed.\nRULES = [\n    ('check-constraint-check', 'error', 'CheckConstraint\\\\([^)]*\\\\bcheck\\\\s*=',\n     'CheckConstraint(check=...) was removed in 6.0 -> CheckConstraint(condition=...)', ['*.py']),\n    ('save-positional', 'error', '\\\\.save\\\\(\\\\s*(True|False)\\\\s*,',\n     'Model.save() positional arguments were removed in 6.0 -> save(force_insert=..., force_update=...)', ['*.py']),\n    ('format-html-no-args', 'error', 'format_html\\\\(\\\\s*[frbu]*(\\\\\"[^\\\\\"]*\\\\\"|\\'[^\\']*\\')\\\\s*\\\\)',\n     'format_html() with no args or kwargs raises in 6.0 -> mark_safe() for fixed HTML, or pass the values as arguments', ['*.py']),\n    ('staticfiles-find-all', 'error', 'finders\\\\.find\\\\([^)]*\\\\ball\\\\s*=',\n     'finders.find(all=...) was removed in 6.1 -> find(..., find_all=True)', ['*.py']),\n    ('pg-agg-ordering', 'error', '\\\\b(ArrayAgg|JSONBAgg|StringAgg)\\\\([^)]*\\\\bordering\\\\s*=',\n     'ArrayAgg/JSONBAgg/StringAgg(ordering=...) was removed in 6.1 -> order_by=...', ['*.py']),\n    ('choices-meta', 'error', '\\\\bChoicesMeta\\\\b',\n     'ChoicesMeta was removed in 6.0 -> ChoicesType', ['*.py']),\n    ('urlfield-assume', 'error', 'FORMS_URLFIELD_ASSUME_HTTPS',\n     'FORMS_URLFIELD_ASSUME_HTTPS was removed; URLField now assumes https', ['*.py']),\n    ('log-action', 'error', '\\\\.log_action\\\\(|\\\\.log_deletion\\\\(',\n     'LogEntryManager.log_action() / ModelAdmin.log_deletion() were removed in 6.0 -> log_actions() / log_deletions()', ['*.py']),\n    ('index-together', 'error', '\\\\bindex_together\\\\s*=',\n     'Meta.index_together was removed in 5.1 -> indexes = [models.Index(fields=[...])]', ['*.py']),\n    ('url-function', 'error', 'from\\\\s+django\\\\.conf\\\\.urls\\\\s+import\\\\s+[^#]*\\\\burl\\\\b|\\\\burl\\\\(\\\\s*r?[\\\\\"\\']\\\\^',\n     'django.conf.urls.url() was removed in 4.0 -> path() or re_path()', ['*.py']),\n    ('ugettext', 'error', '\\\\bu(gettext|gettext_lazy|ngettext|ngettext_lazy|pgettext)\\\\b',\n     'ugettext* was removed in 4.0 -> gettext / gettext_lazy', ['*.py']),\n    ('force-text', 'error', '\\\\b(force_text|smart_text)\\\\b',\n     'force_text / smart_text were removed in 4.0 -> force_str / smart_str', ['*.py']),\n    ('is-ajax', 'error', '\\\\.is_ajax\\\\(\\\\)',\n     \"request.is_ajax() was removed in 4.0 -> check request.headers.get('x-requested-with') or the Accept header\", ['*.py']),\n    ('timezone-utc', 'error', 'timezone\\\\.utc\\\\b(?!c)|import\\\\s+pytz|pytz\\\\.',\n     'django.utils.timezone.utc and pytz support were removed -> datetime.UTC / zoneinfo.ZoneInfo', ['*.py']),\n    ('use-l10n', 'error', '^\\\\s*USE_L10N\\\\s*=',\n     'USE_L10N was removed in 5.0 (localisation is always on); delete the setting', ['*.py']),\n    ('null-boolean', 'error', '\\\\bNullBooleanField\\\\(',\n     'NullBooleanField is gone (system check fields.E903) -> BooleanField(null=True)', ['*.py']),\n    ('staticfiles-tag', 'error', '\\\\{%\\\\s*load\\\\s+(staticfiles|admin_static)\\\\s*%\\\\}',\n     '{% load staticfiles %} was removed -> {% load static %}', ['*.html', '*.txt']),\n    ('login-user-none', 'warn', '\\\\b(a?login)\\\\(\\\\s*request\\\\s*,\\\\s*None\\\\b',\n     'login(request, None) no longer falls back to request.user in 6.1 -> pass the user', ['*.py']),\n    ('default-auto-field', 'warn', 'DEFAULT_AUTO_FIELD\\\\s*=\\\\s*[\\\\\"\\']django\\\\.db\\\\.models\\\\.AutoField[\\\\\"\\']',\n     \"Django 6.0 defaults to BigAutoField; keeping AutoField is fine for old apps, but new apps shouldn't set it\", ['*.py']),\n    ('mail-positional', 'warn', '\\\\b(send_mail|send_mass_mail|mail_admins|mail_managers|EmailMessage)\\\\(\\\\s*[^)=]+,\\\\s*[^)=]+,\\\\s*[^)=]+,\\\\s*[^)=]+,\\\\s*[^)=]+[,)]',\n     'positional arguments past the first four in django.core.mail are deprecated in 6.0 -> keywords', ['*.py']),\n    ('email-settings', 'warn', '^\\\\s*EMAIL_(BACKEND|HOST|HOST_USER|HOST_PASSWORD|PORT|USE_TLS|USE_SSL|TIMEOUT|SSL_CERTFILE|SSL_KEYFILE|FILE_PATH)\\\\s*=',\n     'the EMAIL_* connection settings are deprecated in 6.1 (RemovedInDjango2028Warning) -> MAILERS = {\"default\": {\"BACKEND\": ..., \"OPTIONS\": {...}}}', ['*.py']),\n    ('celery-for-simple-task', 'warn', '@shared_task\\\\b|from\\\\s+celery\\\\s+import',\n     'Django 6.0 ships a Tasks framework (django.tasks); ask before adding Celery for simple background jobs', ['*.py']),\n]\nFILES = ['*.py', '*.html', '*.txt']\nCOMMENT = '#'\nSKIP_DIRS = {\".git\", \".venv\", \"venv\", \"node_modules\", \"__pycache__\", \".agents\", \".claude\", \".cursor\", \"dist\", \"build\", \"target\", \".godot\"}\nCOMPILED = [(rid, lvl, re.compile(rx), msg, globs) for rid, lvl, rx, msg, globs in RULES]\n\n\ndef strip_comment(line):\n    \"\"\"Drop a trailing comment, leaving string literals alone.\"\"\"\n    q = None\n    i = 0\n    while i < len(line):\n        c = line[i]\n        if q:\n            if c == \"\\\\\":\n                i += 2\n                continue\n            if c == q:\n                q = None\n        elif c in \"\\\"'`\":\n            q = c\n        elif line.startswith(COMMENT, i):\n            return line[:i]\n        i += 1\n    return line\n\n\ndef wanted(name):\n    return any(fnmatch.fnmatch(name, g) for g in FILES)\n\n\ndef walk(paths):\n    for p in paths:\n        if os.path.isfile(p):\n            yield p\n            continue\n        for root, dirs, files in os.walk(p):\n            dirs[:] = sorted(d for d in dirs if d not in SKIP_DIRS)\n            for f in sorted(files):\n                if wanted(f):\n                    yield os.path.join(root, f)\n\n\ndef scan(path):\n    out = []\n    name = os.path.basename(path)\n    try:\n        with open(path, encoding=\"utf-8\", errors=\"replace\") as fh:\n            lines = fh.read().splitlines()\n    except OSError as e:\n        return [(path, 0, \"error\", \"unreadable\", str(e))]\n    for n, raw in enumerate(lines, 1):\n        code = strip_comment(raw)\n        if not code.strip():\n            continue\n        accepted = \"guard: ok\" in raw  # a person accepted the warnings on this line\n        for rid, lvl, rx, msg, globs in COMPILED:\n            if accepted and lvl == \"warn\":\n                continue\n            if globs and not any(fnmatch.fnmatch(name, g) for g in globs):\n                continue\n            if rx.search(code):\n                out.append((path, n, lvl, rid, msg))\n    return out\n\n\ndef main(argv):\n    if \"--list\" in argv:\n        for rid, lvl, _, msg, globs in RULES:\n            print(f\"{lvl:5} [{rid}] {msg}\" + (f\"  (only {', '.join(globs)})\" if globs else \"\"))\n        return 0\n    if any(a.startswith(\"-\") for a in argv):\n        print(__doc__)\n        return 2\n    paths = argv or [\".\"]\n    for p in paths:\n        if not os.path.exists(p):\n            print(f\"no such path: {p}\", file=sys.stderr)\n            return 2\n    files = list(walk(paths))\n    findings = []\n    for f in files:\n        findings.extend(scan(f))\n    for path, n, lvl, rid, msg in findings:\n        print(f\"{os.path.relpath(path)}:{n}: {lvl} [{rid}] {msg}\")\n    errors = sum(1 for x in findings if x[2] == \"error\")\n    warns = sum(1 for x in findings if x[2] == \"warn\")\n    print(f\"django6_guard: {len(files)} file(s), {errors} error(s), {warns} warning(s)\")\n    return 1 if errors else 0\n\n\nif __name__ == \"__main__\":\n    sys.exit(main(sys.argv[1:]))\n"
    },
    {
      "path": "skills/django-6-guard/references/removals.md",
      "role": "reference",
      "description": "Which release removed each API and what replaces it.",
      "skill": "django-6-guard",
      "agent": null,
      "install_to": {
        "claude-code": ".claude/skills/django-6-guard/references/removals.md",
        "codex": ".agents/skills/django-6-guard/references/removals.md",
        "cursor": ".agents/skills/django-6-guard/references/removals.md",
        "gemini-cli": ".agents/skills/django-6-guard/references/removals.md",
        "antigravity-cli": ".agents/skills/django-6-guard/references/removals.md",
        "copilot": ".agents/skills/django-6-guard/references/removals.md"
      },
      "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/references/removals.md",
      "raw_latest_url": "https://setupbay.com/raw/django-6-upgrade-guard/latest/skills/django-6-guard/references/removals.md",
      "bytes": 2392,
      "lang": "markdown",
      "content": "# Django removals agents still write\n\nFrom the Django release notes (https://docs.djangoproject.com/en/6.1/releases/). Checked against Django 6.1.2.\n\n| Old code | Removed in | Use |\n|---|---|---|\n| `from django.conf.urls import url` | 4.0 | `from django.urls import path, re_path` |\n| `ugettext`, `ugettext_lazy`, `ungettext` | 4.0 | `gettext`, `gettext_lazy`, `ngettext` |\n| `force_text`, `smart_text` | 4.0 | `force_str`, `smart_str` |\n| `request.is_ajax()` | 4.0 | `request.headers.get(\"x-requested-with\") == \"XMLHttpRequest\"`, or better, the `Accept` header |\n| `NullBooleanField()` | 4.0 (model field kept only for old migrations; system check `fields.E903`) | `BooleanField(null=True)` |\n| `django.utils.timezone.utc`, pytz support | 5.0 | `datetime.UTC`, `zoneinfo.ZoneInfo` |\n| `USE_L10N = True` | 5.0 | delete it; always on |\n| `Meta.index_together` | 5.1 | `Meta.indexes = [models.Index(fields=[\"a\", \"b\"])]` |\n| `CheckConstraint(check=...)` | 6.0 | `CheckConstraint(condition=...)` |\n| `obj.save(False, False, None, None)` | 6.0 | `obj.save(force_insert=..., update_fields=[...])` |\n| `format_html(\"<b>fixed</b>\")` with no args | 6.0 | `mark_safe(\"<b>fixed</b>\")` or `format_html(\"<b>{}</b>\", v)` |\n| `ChoicesMeta` | 6.0 | `ChoicesType` |\n| `ModelAdmin.log_deletion()`, `LogEntryManager.log_action()` | 6.0 | `log_deletions()`, `log_actions()` |\n| `FORMS_URLFIELD_ASSUME_HTTPS` | 6.0 | delete it; `URLField` assumes `https` |\n| `finders.find(path, all=True)` | 6.1 | `finders.find(path, find_all=True)` |\n| `ArrayAgg(\"x\", ordering=...)` (also JSONBAgg, StringAgg) | 6.1 | `order_by=...` |\n| `login(request, None)` falling back to `request.user` | 6.1 | pass the user explicitly |\n| `{% load staticfiles %}`, `{% load admin_static %}` | 3.0 | `{% load static %}` |\n\n## New in 6.0 worth knowing\n- `DEFAULT_AUTO_FIELD` defaults to `django.db.models.BigAutoField`.\n- Python 3.12 or later only.\n- Built-in Content Security Policy support (`django.middleware.csp.ContentSecurityPolicyMiddleware`, `SECURE_CSP`).\n- Template partials (`{% partialdef %}` / `{% partial %}`).\n- A background Tasks framework (`django.tasks`), which needs a backend to actually run tasks.\n- Django 6.1: mail is configured in `MAILERS`; the `EMAIL_*` connection settings warn with\n  `RemovedInDjango2028Warning`.\n- Django 6.1: fetch modes (`QuerySet.fetch_mode(models.FETCH_RAISE)`, `FETCH_PEERS`, `FETCH_ONE`).\n"
    },
    {
      "path": "skills/django-6-guard/references/django3-sample.py.txt",
      "role": "reference",
      "description": "A Django 3-era module and settings for checking the guard.",
      "skill": "django-6-guard",
      "agent": null,
      "install_to": {
        "claude-code": ".claude/skills/django-6-guard/references/django3-sample.py.txt",
        "codex": ".agents/skills/django-6-guard/references/django3-sample.py.txt",
        "cursor": ".agents/skills/django-6-guard/references/django3-sample.py.txt",
        "gemini-cli": ".agents/skills/django-6-guard/references/django3-sample.py.txt",
        "antigravity-cli": ".agents/skills/django-6-guard/references/django3-sample.py.txt",
        "copilot": ".agents/skills/django-6-guard/references/django3-sample.py.txt"
      },
      "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/references/django3-sample.py.txt",
      "raw_latest_url": "https://setupbay.com/raw/django-6-upgrade-guard/latest/skills/django-6-guard/references/django3-sample.py.txt",
      "bytes": 1037,
      "lang": "markdown",
      "content": "# A Django 3.x-era module, used to check the guard. Every marked API is gone in Django 6.1.\nfrom django.conf.urls import url\nfrom django.db import models\nfrom django.utils.encoding import force_text\nfrom django.utils.html import format_html\nfrom django.utils.translation import ugettext_lazy as _\n\n\nclass Order(models.Model):\n    total = models.IntegerField()\n    paid = models.NullBooleanField()\n    code = models.CharField(max_length=8)\n\n    class Meta:\n        index_together = [[\"code\", \"total\"]]\n        constraints = [models.CheckConstraint(check=models.Q(total__gte=0), name=\"total_gte_0\")]\n\n    def __str__(self):\n        return force_text(self.code)\n\n    def badge(self):\n        return format_html(\"<span class='paid'>paid</span>\")\n\n\ndef mark_paid(order):\n    order.paid = True\n    order.save(False, False)\n\n\ndef view(request):\n    if request.is_ajax():\n        return None\n\n\nurlpatterns = [url(r\"^orders/$\", view)]\n\n\n# --- settings.py from the same project ---\nUSE_L10N = True\nEMAIL_HOST = \"smtp.example.com\"\nEMAIL_PORT = 587\n"
    }
  ],
  "requires": {
    "tools": [
      "python3",
      "uv"
    ],
    "env": [],
    "mcp": []
  },
  "tested": {
    "status": "untested",
    "last_run": null,
    "fixture": null,
    "per_agent": {
      "claude-code": "untested",
      "codex": "untested",
      "cursor": "untested",
      "gemini-cli": "untested",
      "antigravity-cli": "untested",
      "copilot": "untested"
    }
  },
  "security": {
    "scanned": true,
    "scanner": "intake-precheck/2",
    "verdict": "clean",
    "network": true,
    "scripts": [
      "django6_guard.py"
    ],
    "notes": "The scanner only reads .py, .html and .txt files and prints findings; it never edits files and makes no network calls. Running django-upgrade through uvx, or the project with uv, may download the pinned packages."
  },
  "featured": false,
  "deprecated": false,
  "last_checked": "2026-10-29",
  "published": "2026-10-29",
  "updated": "2026-10-29",
  "compatibility": {
    "claude-code": "native",
    "codex": "native",
    "cursor": "native",
    "gemini-cli": "native",
    "antigravity-cli": "native",
    "copilot": "native"
  },
  "counts": {
    "rules": 2,
    "skills": 1,
    "mcp": 0
  },
  "url": "https://setupbay.com/loadouts/django-6-upgrade-guard/",
  "api_url": "https://setupbay.com/api/loadouts/django-6-upgrade-guard.json",
  "verification": {
    "level": "verified-install",
    "status": "verified",
    "label": "Verified install",
    "verified": true,
    "checked_at": "2026-10-29T12:25:33Z",
    "commit": "c1f7b634c57f2fcceb6a8cb22a465ee52dec160b",
    "content_current": true,
    "agent_tests": "not-run",
    "counts": {
      "pass": 9,
      "fail": 0,
      "skip": 0,
      "not_applicable": 1
    },
    "meaning": "Level 1: automated checks on the files (parse, install paths, MCP config, safety scan, references, size, licence, starter build). No AI agent was run.",
    "checks": [
      {
        "id": "listing",
        "name": "Listing",
        "status": "pass",
        "summary": "Schema valid; 8 files declared, none missing or extra",
        "details": [
          "tested.status: untested (agent tests are separate from Level 1)"
        ]
      },
      {
        "id": "parse",
        "name": "Files parse",
        "status": "pass",
        "summary": "All 8 files parse; front matter valid",
        "details": []
      },
      {
        "id": "adapters",
        "name": "Adapters",
        "status": "pass",
        "summary": "CLAUDE.md and GEMINI.md import AGENTS.md and are up to date",
        "details": [
          "CLAUDE.md: matches the generator",
          "GEMINI.md: matches the generator"
        ]
      },
      {
        "id": "install-paths",
        "name": "Install paths",
        "status": "pass",
        "summary": "Correct paths for all 6 agents; layouts re-discovered",
        "details": [
          "Claude Code: 6 files, 1 skill in .claude/skills/",
          "Codex CLI: 5 files, 1 skill in .agents/skills/",
          "Cursor: 6 files, 1 skill in .agents/skills/, 1 rule",
          "Gemini CLI: 6 files, 1 skill in .agents/skills/",
          "Antigravity CLI: 5 files, 1 skill in .agents/skills/",
          "GitHub Copilot: 5 files, 1 skill in .agents/skills/"
        ]
      },
      {
        "id": "mcp",
        "name": "MCP config",
        "status": "n/a",
        "summary": "No MCP servers in this loadout",
        "details": []
      },
      {
        "id": "safety",
        "name": "Safety scan",
        "status": "pass",
        "summary": "Clean: no credentials, risky shell, hidden text or covert instructions",
        "details": [
          "Scanner intake-precheck/2: verdict clean; network yes (listing says yes)"
        ]
      },
      {
        "id": "references",
        "name": "References",
        "status": "pass",
        "summary": "3 references between files resolve for every agent",
        "details": []
      },
      {
        "id": "size",
        "name": "Size limits",
        "status": "pass",
        "summary": "8 files, 18.4 KB total; largest skills/django-6-guard/scripts/django6_guard.py 7.6 KB",
        "details": [
          "Limits: 30 files, 32 KB per file, 128 KB total, 500 lines per skill or rule"
        ]
      },
      {
        "id": "licence",
        "name": "Licence",
        "status": "pass",
        "summary": "MIT, by SetupBay; text in the repository LICENSE",
        "details": []
      },
      {
        "id": "starter-build",
        "name": "Starter build",
        "status": "pass",
        "summary": "django6_guard.py passes a small Django 6.1 shop project and flags every old line in the skill's Django 3-era sample: 12 removed APIs as errors and 2 EMAIL_* settings as warnings. django-upgrade 1.33.0 finds nothing to rewrite in the project and would rewrite the sample. The pinned Django 6.1.2 passe",
        "details": [
          "Applied 12 loadout files at every agent's paths",
          "✓ scanner: the Django 6.1 project is clean: bash -c python3 .agents/skills/django-6-guard/scripts/django6_guard.py config shop manage.py; echo \"exit=$?\"",
          "✓ scanner: the Django 3-era sample is flagged line by line: bash -c mkdir -p /tmp/django3-sample && cp .claude/skills/django-6-guard/references/django3-sample.py.txt /tmp/django3-sample/models.py && python3 .claude/skills/django-6-guard/scripts/django6_guard.py /tmp/django3-sample; echo \"exit=$?\"",
          "✓ django-upgrade 1.33.0: nothing to rewrite in the project, the sample would be rewritten: bash -c uvx -q --from django-upgrade==1.33.0 django-upgrade --check --target-version 6.1 manage.py config/*.py shop/*.py shop/migrations/*.py; echo \"project=$?\"; cd /tmp/django3-sample && uvx -q --from django-upgrade==1.33.0 django-upgrade --check --target-version 6.1 models.py; echo \"sample=$?\"",
          "✓ Django 6.1.2: system checks and migrations are clean: bash -c uv run --python 3.12 python manage.py check && uv run --python 3.12 python manage.py makemigrations --check --dry-run",
          "✓ tests with RemovedInDjango70Warning and RemovedInDjango2028Warning as errors: uv run --python 3.12 python -W error::django.utils.deprecation.RemovedInDjango70Warning -W error::django.utils.deprecation.RemovedInDjango2028Warning manage.py test -v 1",
          "✓ Django 6.1.2 refuses the sample's removed calls: uv run --python 3.12 python legacy_probe.py",
          "Covers: The scanner's removed-API rules against a real Django 3-era module and settings, and a clean Django 6.1 project (models, services, views, URLs, template, migration)",
          "Covers: django-upgrade 1.33.0 --check at target 6.1 on both",
          "Covers: Django 6.1.2 itself: system checks, makemigrations --check, the tests with the next deprecations as errors, MAILERS mail, the CSP middleware and FETCH_RAISE",
          "Covers: Not covered: Postgres-only aggregates (ArrayAgg ordering=) and login(request, None), which the scanner flags but the SQLite fixture can't run"
        ]
      }
    ]
  },
  "install": {
    "claude-code": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "CLAUDE.md",
          "target": "CLAUDE.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/CLAUDE.md",
          "role": "adapter"
        },
        {
          "path": "skills/django-6-guard/SKILL.md",
          "target": ".claude/skills/django-6-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/django-6-guard/scripts/django6_guard.py",
          "target": ".claude/skills/django-6-guard/scripts/django6_guard.py",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/scripts/django6_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/django-6-guard/references/removals.md",
          "target": ".claude/skills/django-6-guard/references/removals.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/references/removals.md",
          "role": "reference"
        },
        {
          "path": "skills/django-6-guard/references/django3-sample.py.txt",
          "target": ".claude/skills/django-6-guard/references/django3-sample.py.txt",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/references/django3-sample.py.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/django-6-upgrade-guard/claude-code.zip"
    },
    "codex": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "skills/django-6-guard/SKILL.md",
          "target": ".agents/skills/django-6-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/django-6-guard/scripts/django6_guard.py",
          "target": ".agents/skills/django-6-guard/scripts/django6_guard.py",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/scripts/django6_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/django-6-guard/references/removals.md",
          "target": ".agents/skills/django-6-guard/references/removals.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/references/removals.md",
          "role": "reference"
        },
        {
          "path": "skills/django-6-guard/references/django3-sample.py.txt",
          "target": ".agents/skills/django-6-guard/references/django3-sample.py.txt",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/references/django3-sample.py.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/django-6-upgrade-guard/codex.zip"
    },
    "cursor": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": ".cursor/rules/django-6-only.mdc",
          "target": ".cursor/rules/django-6-only.mdc",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/.cursor/rules/django-6-only.mdc",
          "role": "rules"
        },
        {
          "path": "skills/django-6-guard/SKILL.md",
          "target": ".agents/skills/django-6-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/django-6-guard/scripts/django6_guard.py",
          "target": ".agents/skills/django-6-guard/scripts/django6_guard.py",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/scripts/django6_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/django-6-guard/references/removals.md",
          "target": ".agents/skills/django-6-guard/references/removals.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/references/removals.md",
          "role": "reference"
        },
        {
          "path": "skills/django-6-guard/references/django3-sample.py.txt",
          "target": ".agents/skills/django-6-guard/references/django3-sample.py.txt",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/references/django3-sample.py.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/django-6-upgrade-guard/cursor.zip"
    },
    "gemini-cli": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "GEMINI.md",
          "target": "GEMINI.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/GEMINI.md",
          "role": "adapter"
        },
        {
          "path": "skills/django-6-guard/SKILL.md",
          "target": ".agents/skills/django-6-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/django-6-guard/scripts/django6_guard.py",
          "target": ".agents/skills/django-6-guard/scripts/django6_guard.py",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/scripts/django6_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/django-6-guard/references/removals.md",
          "target": ".agents/skills/django-6-guard/references/removals.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/references/removals.md",
          "role": "reference"
        },
        {
          "path": "skills/django-6-guard/references/django3-sample.py.txt",
          "target": ".agents/skills/django-6-guard/references/django3-sample.py.txt",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/references/django3-sample.py.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/django-6-upgrade-guard/gemini-cli.zip"
    },
    "antigravity-cli": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "skills/django-6-guard/SKILL.md",
          "target": ".agents/skills/django-6-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/django-6-guard/scripts/django6_guard.py",
          "target": ".agents/skills/django-6-guard/scripts/django6_guard.py",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/scripts/django6_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/django-6-guard/references/removals.md",
          "target": ".agents/skills/django-6-guard/references/removals.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/references/removals.md",
          "role": "reference"
        },
        {
          "path": "skills/django-6-guard/references/django3-sample.py.txt",
          "target": ".agents/skills/django-6-guard/references/django3-sample.py.txt",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/references/django3-sample.py.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/django-6-upgrade-guard/antigravity-cli.zip"
    },
    "copilot": {
      "files": [
        {
          "path": "AGENTS.md",
          "target": "AGENTS.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/AGENTS.md",
          "role": "instructions"
        },
        {
          "path": "skills/django-6-guard/SKILL.md",
          "target": ".agents/skills/django-6-guard/SKILL.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/SKILL.md",
          "role": "skill"
        },
        {
          "path": "skills/django-6-guard/scripts/django6_guard.py",
          "target": ".agents/skills/django-6-guard/scripts/django6_guard.py",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/scripts/django6_guard.py",
          "role": "reference"
        },
        {
          "path": "skills/django-6-guard/references/removals.md",
          "target": ".agents/skills/django-6-guard/references/removals.md",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/references/removals.md",
          "role": "reference"
        },
        {
          "path": "skills/django-6-guard/references/django3-sample.py.txt",
          "target": ".agents/skills/django-6-guard/references/django3-sample.py.txt",
          "raw_url": "https://setupbay.com/raw/django-6-upgrade-guard/1.0.0/skills/django-6-guard/references/django3-sample.py.txt",
          "role": "reference"
        }
      ],
      "manual_steps": [],
      "zip_url": "https://setupbay.com/download/django-6-upgrade-guard/copilot.zip"
    }
  },
  "source_zip_url": "https://setupbay.com/download/django-6-upgrade-guard/source.zip",
  "claude_code_plugin": {
    "name": "django-6-upgrade-guard",
    "marketplace_url": "https://setupbay.com/marketplace.json",
    "install": [
      "/plugin marketplace add https://setupbay.com/marketplace.json",
      "/plugin install django-6-upgrade-guard@setupbay"
    ],
    "zip_url": "https://setupbay.com/plugins/django-6-upgrade-guard.zip",
    "sha256": "f7ea84ab06e26c3f7ba1179ecc63e8ce0fb8efe06772dd87388fffc3b8d35455",
    "carries": [
      "skills"
    ],
    "note": "Plugins do not carry project rules (AGENTS.md, CLAUDE.md); install those from install.claude-code."
  }
}