13 Aug 2026
Planet Python
Wingware: Wing Python IDE Version 12.0.2 - August 13, 2026
Wing Python IDE version 12.0.2 has been released. This release adds a native ARM64 Windows version of Wing, improves remote development on Windows, streamlines Claude Code setup, and improves performance and responsiveness, particularly when working with very large projects and on Windows. It also reduces the size of the analysis cache database by about 20% and fixes a number of bugs. See the change log for details.
Wing 12 integrates the Claude Code AI coding agent directly into the IDE, with a new Claude Code tool, a Tasks tool for planning and reviewing AI agent work, and a set of MCP servers that give the agent access to Wing's source code analysis, unit testing, debugger, and code review features. See the list of Wing 12 features below for details.

Downloads
Wing 12 -- the full Python IDE, available as Wing Pro (for agentic development) or Wing Classic (for manual development) depending on your license, with a free 30-day trial of Wing Pro.
Wing 101 v. 12 -- a simplified free Python IDE for teaching beginning programmers.
Wing 11 and earlier versions are not affected by installation of Wing 12 and may be installed and used independently. However, project files for Wing 11 and earlier are converted when opened by Wing 12 and should be saved under a new name, since Wing 12 projects cannot be opened by older versions of Wing.
New in Wing 12
AI Coding Agent Integration with Claude Code
Wing 12 adds a Claude Code tool that integrates the Claude Code AI coding agent with the IDE. Set Up for Claude Code in the Project menu configures the active project for AI agent development.
A set of MCP (Model Context Protocol) servers gives Claude Code access to Wing's source code analysis, testing, and debugger functionality, so the agent can more efficiently navigate and understand your code, write, run, and fix unit tests, and use the debugger to diagnose difficult runtime errors. In our benchmarks, giving Claude Code access to Wing's MCP servers made agent-driven coding tasks both faster and cheaper.
Tasks Tool
The new Tasks tool lets you plan, queue, execute, review, and audit the history of AI agent development tasks, making it easier to supervise and inspect the agent's work before committing it to revision control.
FIX Features and Write Tests
Wing 12 adds AI agent driven FIX features that hand the current debugger bug, failing unit tests, or code warnings to Claude Code for resolution. New Write Tests items in the Testing and editor context menus prompt the agent to write unit tests for selected code.
Code Actions
Wing 12 also adds AI Code Actions, accessed from the FIX icon in the editor toolbar, that operate on selected code or the enclosing scope. Built-in actions include explaining code, reviewing it for quality or security risks, fixing code warnings, optimizing for performance, and updating comments and docstrings. The action list is user-extensible, so you can add your own prompts for tasks you run often.
Pseudo-Terminal for OS Commands and Debug I/O
The OS Commands and Debug I/O tools now default to using a pseudo-terminal that implements full ANSI terminal emulation, so you can run and debug programs that use color output, cursor positioning, or full-screen TUIs.
Redesigned OS Commands Capability
The OS Commands tool has been replaced with configurable OS Commands in the Tools menu. Each OS Command acts like its own tool, for use in any tool or editor split.
Tools in Editor Splits and Reorganized Tools Menu
Tools can now also be added or dragged to editor splits, allowing for much more flexible workspace layout. The Tools menu has been reorganized into related groups, with less-used and legacy tools in an Other sub-menu, so more commonly used tools are easier to find.
Test Discovery and Preferences Search
Wing 12 adds automatic test file discovery and discovery of individual unit tests within files, so you usually don't need to specify test file patterns or add test files individually. The Preferences dialog now supports text search and back/forward navigation.
Other Minor Features and Improvements
Wing 12 also includes many other improvements, including:
- IDE build for ARM64 Windows
- Improved performance and responsiveness
- Improved remote agent installation and remote development
- Significantly faster source code analysis
- Prompts for SSH passphrases and HTTPS credentials when needed during VCS operations
- Faster detection of externally modified files, with reduced CPU load
- Saving and restoring of tool console scrollback across project close and reopen
- Clickable OSC 8 hyperlinks in the OS Commands and Debug I/O tools
- A preference to select the ssh or plink.exe SSH implementation
- A notice on the next startup when Wing's previous session ended in an unexpected crash
Wing 12 also makes a number of other bug fixes and usability improvements.
Product Line Changes
Wing 12 simplifies the product line. The Commercial / Non-Commercial use distinction has been replaced by two feature-based product tiers:
- Wing Pro -- the full-featured Python IDE including AI agent development tools
- Wing Classic -- the complete traditional Python IDE for hands-on development, with no AI agent features
Anyone may purchase either tier for any purpose. Existing Commercial and Non-Commercial Use licenses both become Wing Pro. Customers who don't need the AI agent features may move to Wing Classic at renewal time, or any time sooner by contacting support@wingware.com.
Wing Personal has been discontinued. Existing Wing Personal users may continue to use Personal 11.x indefinitely, switch to free Wing 101, or purchase a Wing Classic license. See Pricing for details.
Changes and Incompatibilities
The single-LLM-query AI features originally introduced in Wing 11 (the AI Coder and AI Chat tools) are considered legacy in Wing 12 and hidden from the user interface by default. They remain available in projects that already use them and can be re-enabled with Project Properties > AI in Project Properties or in the Projects > AI preferences.
See Wing's Claude Code Agent Integration for Wing 12's AI agent approach.
If you have questions, please don't hesitate to contact us at support@wingware.com.
13 Aug 2026 1:00am GMT
Trey Hunner: Reorganizing Python's sys module
The sys module is the primary junk drawer of the Python standard library.
A good junk drawer holds miscellaneous items that don't have another sensible home.
I often think of utils modules as "junk drawer" modules. I believe that both utils modules and junk drawers have their purpose, but junk drawers can get out of hand.
As I recently noted in my talk about pathlib, I see both the sys module and the os module as junk drawer modules. They serve a similar purpose to utils modules, but they have a different name.
In this post, I wonder: what would Python's sys be like if it was designed today, from scratch?
The overview: 9 new sys submodules
As of Python 3.15, the sys module has 115-121 attributes (depending on whether you're in the REPL and whether an exception has occurred), and 63 of those are functions.
All of those names need permanent homes.
How can we reorganize a utils-style module that's grown quite large?
Give it submodules!
No, really… this isn't the worst solution. Django's utils package isn't so bad.
So we could split sys into these 9 submodules:
sys.cli: for command-line argument handling and program controlsys.imports: related to imports and modulessys.io: handles standard I/O streamssys.repl: handles REPL display controlsys.interpreter: system information and installation detailssys.memory: memory management tools used for profiling, optimization, and debuggingsys.exceptions: exception handlingsys.profile: profiling and introspectionsys.runtime: interpreter runtime behavior
You may notice some similarities to other modules in the Python standard library. That's a hint that it might be worth moving some of these utilities into other parts of the standard library. But moving functionality between top-level modules is a much bigger change, so let's set that idea aside.
For now, let's take a closer look at our tentatively re-organized sys package.
The sys package and its submodules
A couple of these 9 submodules have only a handful of attributes, a couple have over 20, and the rest fall somewhere in the middle.
sys.cli
This submodule would handle command-line arguments and program control:
argv: Command-line arguments listorig_argv: Original unmodified argumentsexit(): Function to terminate Pythonflags: Named tuple of interpreter flags_xoptions: Dictionary of-Xcommand options
sys.imports
Everything related to imports and modules:
path: Module search path listmodules: Dictionary of loaded modulesbuiltin_module_names: Tuple of built-in modulesstdlib_module_names: Frozen set of standard library modulespath_hooks: List of path-to-finder callablespath_importer_cache: Finder object cachemeta_path: Meta path finder objectspycache_prefix: Bytecode cache directoryset_lazy_imports(),get_lazy_imports(),set_lazy_imports_filter(),get_lazy_imports_filter(),lazy_modules: Lazy import controls (Python 3.15+)
sys.io
The standard I/O streams:
stdin: Standard input streamstdout: Standard output streamstderr: Standard error stream__stdin__,__stdout__,__stderr__: The original values of those three streams (useful for restoring them after replacing them)
sys.repl
Hooks and settings for Python's interactive prompt:
displayhook(): Called to show the result of each REPL expression__displayhook__: The original value ofdisplayhookps1: The primary prompt string (>>>)ps2: The continuation prompt string (...)__interactivehook__: Called when an interactive session starts up_baserepl(): Starts the basic fallback REPL
sys.interpreter
Information about the Python build, the Python installation, and the operating system:
platform: Platform identifier string (linux,darwin,win32, etc.)version: Python version stringversion_info: Python version as a named tupleimplementation: Python implementation details (CPython, PyPy, etc.)executable: Path to the Python interpreterprefix,exec_prefix: Installation prefixesbase_prefix,base_exec_prefix: Installation prefixes, ignoring virtual environmentsplatlibdir: Platform-specific library directory namemaxunicode: Maximum Unicode code point (1114111)maxsize: Maximum size of containersbyteorder: Native byte order ('little'or'big')hexversion: Version encoded as single integerapi_version: C API versioncopyright: Python copyright noticeabiflags: ABI flags from PEP 3149abi_info: ABI details namespace (Python 3.15+)float_info: Floating point implementation detailsint_info: Integer implementation detailshash_info: Hash algorithm parametersfloat_repr_style: floatreprstyle ('short'or'legacy')winver,dllhandle,getwindowsversion(): Windows-specific detailsgetandroidapilevel(): Android-specific detail_base_executable,_framework,_git,_home,_stdlib_dir: Assorted build and installation details
sys.memory
Memory management tools used for profiling, optimization, and debugging:
getsizeof(): Size of an object in bytesgetrefcount(): Number of references to an objectgetallocatedblocks(): Number of allocated memory blocksgetunicodeinternedsize(): Number of interned stringsintern(): Intern a string_is_interned(): Check whether a string is interned_is_immortal(): Check whether an object is immortal_debugmallocstats(): Print memory allocator statistics_clear_type_cache(),_clear_internal_caches(): Clear interpreter caches
sys.exceptions
Tools for accessing and handling exceptions:
exc_info(): Currently handled exception, as a 3-tupleexception(): Currently handled exception (Python 3.11+)last_exc,last_type,last_value,last_traceback: The most recent unhandled exception, mostly for REPL useexcepthook(): Called to display unhandled exceptions__excepthook__: The original value ofexcepthookunraisablehook(): Called for exceptions that can't be raised__unraisablehook__: The original value ofunraisablehooktracebacklimit: Maximum number of traceback levels to display
sys.profile
Profiling, tracing, auditing, and other runtime introspection:
setprofile(),getprofile(): Profiling hooks_setprofileallthreads(): Set profile function for all threads (Python 3.12+)settrace(),gettrace(): Tracing hooks_settraceallthreads(): Set trace function for all threads (Python 3.12+)call_tracing(): Call a function with tracing enabledmonitoring: Low-overhead monitoring events namespace (Python 3.12+)_getframe(),_getframemodulename(): Frame inspection_current_frames(),_current_exceptions(): Frames and exceptions across all threadsactivate_stack_trampoline(),deactivate_stack_trampoline(),is_stack_trampoline_active(): Support for the perf profiler (Python 3.12+)audit(): Raise an auditing eventaddaudithook(): Register an audit hookremote_exec(),is_remote_debug_enabled(): Remote debugging support (Python 3.14+)
sys.runtime
Settings that control interpreter runtime behavior:
setrecursionlimit(),getrecursionlimit(): Recursion depth controlsetswitchinterval(),getswitchinterval(): Thread switching controlis_finalizing(): Whether the interpreter is shutting downbreakpointhook(): Called by the built-inbreakpointfunction__breakpointhook__: The original value ofbreakpointhookdont_write_bytecode: Suppress.pycfile generationwarnoptions: Warning filter settingsgetfilesystemencoding(),getfilesystemencodeerrors(): Filesystem encoding detailsgetdefaultencoding(): Default string encoding (alwaysutf-8)get_int_max_str_digits(),set_int_max_str_digits(): Limit on int-to-string conversion (Python 3.11+)setdlopenflags(),getdlopenflags(): Dynamic loading controlthread_info: Thread implementation details_is_gil_enabled(): Whether the GIL is enabled (Python 3.13+)_jit: JIT compiler introspection namespace_dump_tracelets(): Dump the JIT's internal tracelets_get_cpu_count_config(): Configured CPU count overrideget_asyncgen_hooks(),set_asyncgen_hooks(): Async generator lifecycle hooksget_coroutine_origin_tracking_depth(),set_coroutine_origin_tracking_depth(): Coroutine debugging depth_enablelegacywindowsfsencoding(): Windows mbcs encoding compatibility
Could this actually be done?
When I first pondered this experiment last year, this was a very hypothetical thought experiment that I assumed could never be done. I still mostly feel the same way.
There are a few big problems with such a refactoring:
- What would the transition period look like for the huge amount of code that currently uses existing
sysfeatures? - Would backwards compatibility be maintained forever? If so, would this cause more confusion than it's worth?
- How would code that monkey patches attributes like
sys.stdoutwork?
I thought the third question was the biggest roadblock, but I now think it's the first 2 questions.
Those first 2 questions are big questions and I haven't thoroughly thought through the upsides and downsides of such a refactoring.
That third question is a technical one, but I think I can answer it… but the answer is messy.
The magic of module-level __setattr__
When Python users want to capture all output from their program to a file, they reassign sys.stdout to an in-memory file-like object. That's how the contextlib.redirect_stdout helper works, and many testing tools use the same technique.
This monkey patching of sys.stdout is somewhat common, which poses a bit of a problem for us.
Imagine that stdout actually lived in a sys.io submodule. If sys.stdout and sys.io.stdout were two separate attributes, code that assigned to one would be invisible to code that read from the other.
We need a way to synchronize reads and writes of the old flat sys namespace to forward them to the newly nested namespace within the right submodule.
Python has supported customizing module-level attribute reads since Python 3.7, thanks to module-level __getattr__ functions (PEP 562). But Python doesn't support module-level __setattr__ functions (that idea was proposed in PEP 726 and rejected).
Although… every Python module is an instance of ModuleType, and Python allows changing the class of a module object. If we swap in a ModuleType subclass, we can define whatever __getattr__ and __setattr__ behavior we'd like.
This trick is demonstrated in a proof-of-concept newsys package.
The newsys package reimplements sys as a package with 9 submodules. As a proof of concept, this module simply proxies to the sys module. All reads and writes of newsys.io.stdout or newsys.stdout proxy to the original sys.stdout (since that's what everything else still uses under the hood in the existing Python interpreter).
What would the transition look like?
If this transition was ever actually done, I imagine it might look something like this:
- Add the submodules, with every old flat name still working via forwarding
- Update the documentation to nudge folks toward the new names
- Soft deprecate the flat names someday (or maybe never)
- (Likely never) hard deprecate the flat names
There's a tiny bit of precedent for sys submodules: sys.monitoring (added in Python 3.12) is an actual module that lives under sys. But since sys isn't a package, import sys.monitoring doesn't work, as noted at the top of the sys.monitoring documentation page.
But, I doubt this will ever be done. Python isn't known for reorganizing modules just to clean things up (outside of the big Python 2/3 split).
Removing names like sys.path and sys.argv would break a huge amount of code… and I can imagine Python tutorials and long-time Python users dragging their feet on re-learning "the new way". After all… why re-learn something when the old version already works and isn't going anywhere?
If this was ever done, the flat names might need to keep working forever, and permanent aliases might cause more confusion than such a reorganization is worth.
A thought experiment, not a proposal
I'm not seriously proposing that we actually reorganize sys… at least not seriously enough to draft a PEP.
But I do think there's a practical takeaway here for our own code. When a utils module grows out of hand, submodules can help. And if other code relies on the old flat names, a module-level __getattr__ function (or that hacky __class__ trick) can keep the old names working while you reorganize.
I doubt sys will ever change, but I had fun imagining a version of Python where it did.
13 Aug 2026 12:30am GMT
12 Aug 2026
Planet Python
Django Weblog: DSF Office Hours
The DSF Board hosts open office hours every Wednesday at 6:00 PM UTC (check your local time). Anyone in the Django community is welcome to drop in. You do not need an agenda or an invitation. Video call details are on the DSF Office Hours page.
We have been running these since October 2024, and right now we have two things we would especially like to talk with you about.
Who shows up
On any given Wednesday, you might find DSF Board members, Steering Council members, Django Fellows, working group members, and community members who are curious about joining a working group. There is no membership requirement. Anybody from the community can join, and often does.
The Executive Director search
We recently published a call for applicants for a Django Executive Director. If you are considering applying, or you are still deciding whether it is the right fit, come to office hours and ask us anything: what the job actually looks like, what we expect in the first year, how the search works. We would rather answer your questions directly than have you guess from a job posting.
If this is the first you are hearing about the search, please help us spread the word. The best candidate may be someone who has not thought to look.
Fundraising to support it
Hiring an Executive Director is why we raised our 2026 fundraising goal from $300,000 to $500,000, which needs about $16,000 per month in additional recurring support. We have made real progress and are working to close the rest.
If your company uses Django, you can help through corporate sponsorship, a direct donation, or GitHub Sponsors. Most of these are a small lift for a company that already depends on Django. If you want fundraising materials to bring to your leadership team, or help picking the option that fits, come to office hours, and we will get you what you need.
Everything else
Office hours cover plenty beyond that: what our working groups are up to and how to join one, projects the Foundation is working on, and whatever you have been wondering about how the DSF operates. In the weeks before a board meeting, we use the time to gather feedback on what we are about to discuss. If you want the board to hear something, this is a direct line.
One thing office hours are not: a general Django support channel. It is not the place to debug your code or market a product. For coding help, the Django Forum will get you faster answers.
Office hours are the most direct way to keep up with the Foundation, but they are not the only one. We wrote up all the other places we post and where the conversation happens if Wednesdays do not work for you.
Otherwise, put a Wednesday on your calendar and say hello.
12 Aug 2026 5:25pm GMT
Django community aggregator: Community blog posts
Weeknotes (2026 week 33)
Weeknotes (2026 week 33)
Holidays and the heat wave
I had four weeks of holidays this summer. The timing couldn't have been much better with the heat wave - doing much thinking seems to be impossible anyway. I organized a multi-day feast with a few friends and with much help from others. We built up the site and installations over the course of multiple days and spent some days tearing most of it down afterwards. I started back to the office job physically tired but mentally rested. That's good. I'm really looking forward to seeing the pictures people took.
What's less good is that we're living through the projections which climate scientists warned us about decades ago. Or worse, even, since Switzerland is one of the regions where the temperature increased more than the global average. The member of Switzerland's Federal Council heading the Federal Department of the Environment, Transport, Energy and Communications reportedly said that he didn't expect such intense heat. Of course, it was reported earlier in the same week that the same member was responsible for removing funding for a more resilient forest from the budget for the next fiscal year. This is unfortunately to be expected: he has long been connected to the fossil energy industry. After all, he was also the president of Swissoil and Auto Schweiz. It's really frustrating. None of this is news to climate scientists, and it hasn't been news here either - these posts start in 2005, back when I was studying environmental sciences at ETH with a focus on atmospheric physics.
Scripts for auto-merging dependabot and pre-commit pull requests
I let Claude write some scripts for automatically merging pull requests created by various bots, see here. The script finds pull requests created by a predefined list of bots in a defined list of accounts (organizations or users) and squash-merges them if the CI run is green and there are no conflicts. It's a dry run by default; --apply is required to actually merge anything. It doesn't look at reviews and doesn't care whether a bump is major or minor - I'm relying on the test suites for that.
The ruff 0.16 update was a bit painful because ruff now enables 413 rules by default, up from 59. Recurring themes were warnings about mutable class variables (which are common when using Django), blind except clauses and underspecified dates without time zones, but none of them in scenarios where they actually hurt.
So, instead of just running the merge script, I had to fix up dozens of pyproject.toml files and projects. Oh well, next time will be smooth again.
Releases
Since I've been away from the computer for so long, the list of releases from the start of July onwards is quite short.
django-authlib
django-authlib 0.18 now also supports Microsoft Entra ID logins. The admin integration also has support for Microsoft accounts, not just for Google.
django-content-editor
The django-content-editor 9.0.1 just contains a small fix which avoids submitting the form that allows cloning content between regions when cancelling the dialog.
12 Aug 2026 5:00pm GMT
Storing Django Static and Media Files on Cloudflare R2
This tutorial shows how to configure Django to load and serve up static and media files, public and private, via Cloudflare R2.
12 Aug 2026 3:28am GMT
11 Aug 2026
Django community aggregator: Community blog posts
Duff's device in JavaScript
In 1983, Tom Duff needed to copy memory into an output register faster than his compiler could manage, and wrote the most famous abuse of switch in the history of C. I ported his device to JavaScript and raced it against the plainest possible loop - and the verdict changed with the engine, the engine's version, and the CPU underneath.

11 Aug 2026 10:00am GMT
06 Aug 2026
Planet Twisted
Hynek Schlawack: Production-ready Python Docker Containers with uv
Starting with 0.3.0, Astral's uv brought many great features, including support for cross-platform lock files uv.lock. Together with subsequent fixes, it has become Python's finest workflow tool for my (non-scientific) use cases. Here's how I build production-ready containers, as fast as possible.
06 Aug 2026 12:00am GMT
23 Jun 2026
Planet Twisted
Glyph Lefkowitz: Adversarial Communication
As I have discussed in previous posts, "AIs" can make mistakes. In fact, they do make mistakes, and their mistake-making patterns are such that where and how they will make mistakes is both uncertain and constantly changing.
Thus, in any scenario where you want to attempt to make "productive" use of "AI", you must have a system in place for checking every result. Not checking some results; checking every result. If each result might have a consequence for you (and if it didn't have a consequence, why bother automating it?) and you cannot predict in advance which kinds of results will need verification, then verification is always required.
The verification often ends up being just as expensive as doing the work in the first place, which means that if you want your usage of "AI" to be personally profitable, you have to find someone else to externalize the cost of verification onto. This person becomes your adversary, and, if you are successful, your "AI's" victim.
The Ladder-Climber And Their Reverse-Centaur Rungs
One way that this constellation of facts can straightforwardly assemble themselves into a dystopian nightmare is the phenomenon, described by Cory Doctorow, of the reverse centaur. This is when your employer non-consensually turns you into the verification system. The "AI" does the fun part of initially performing the work, and then you do the boring part where you check if the robot is right and clean up its messes, even if everyone already knows that it would, in aggregate, be cheaper for you to do the work in the first place.
Reverse centaurs can be made from any automation, not only "AI" automation. I think that there is a reason that this term happens to have emerged in the "age of AI", though, and not with earlier automation technologies (even those which were considerably more viscerally horrific). That reason is: the wrongness of "AI" output is not merely a technical feature that must be compensated for, it is a generalized externality.
As I mentioned above, if you are responsible for the entirety of the work, both extruding the "AI" output and checking it, it's usually cheaper to have humans do the entirety of the work to begin with. When humans do the writing directly, we can check as we go, and thus verification doesn't need to be as comprehensive.
When "AI" coding advocates say "code review is the bottleneck", what they are observing is that the LLM is still rolling the dice for each PR, and a human is still necessary to verify that each of those rolls is a winner. But calling this process "code review" is a bit of a misnomer; it's not really "code review" in the traditional sense, it's human understanding.
Before the advent of "AI", the human understanding was implicit in the process of writing the code in the first place1, and the code review was a way of diffusing and extending that understanding. Now that the code can be authored with no initial understanding taking place, that cost has not gone away, it has moved.
Human understanding was always the bottleneck.
However, this is taking a collaborative view of a software project, where satisfying the needs and solving the problems of your customers are the goals. We can see that "AI" is a bad tool to satisfy those goals, because all it's doing is converting the first half of the work, that of understanding the code as you write it, to understanding the agent's output as you read it.
What if, instead, we were to take the view that every software company is a Hobbesian nightmare, red in tooth and claw? In this view, the only goal of a software project is for the individual developers to make their promo cycles and get their bonuses. Given that there is only a certain amount of money to go around, this is a zero-sum game where each programmer wants to look more productive than their colleagues.
Pretty much every organization finds it easy to reward "productivity" as expressed by lines of code emitted, but the benefits of doing thorough and thoughtful design, analysis, and code review very difficult to reward. In this world, an LLM is an invaluable tool for the sociopathic ladder-climber, particularly if your legacy organization is still structuring their workflows as if the person prompting the bot is "writing" the code, and then they get to foist off the act of "reviewing" the code onto someone else.
Here, the prompter effectively externalizes the cost of the LLM's failures but internalizes any benefits. The prompter will vibe-code a big feature, so large that the assigned reviewer can't possibly comprehend it all effectively. When this happens, the reviewer will, eventually, be pressured to approve it, even if they can try to spot a few problems along the way. The reviewer has their own work to get back to, after all, the obligation to review the prompter's (read: the bot's) code is a drain on their time that they are not going to get rewarded for.
If this feature is a big success, the prompter gets a promotion. If it causes a big issue, well, the reviewer must not have been careful enough.
This is why LLMs are "good for coding", and also why their biggest promoters keep having outages.
The Generative Gish Galloper
Coding is the biggest "success story" of this type of adversarial communication, but it is by far not the only instance of such a thing. LLMs create a new form of leverage that can turn Brandolini's law from a linear advantage into an exponential one. If you are engaged in a political debate where you want to overwhelm the other side in nonsense, an LLM can generate bullshit faster than it is physically possible for a human being to type, let alone respond thoughtfully. There is an asymmetry to the utility of this weapon as well: only one side of the political spectrum wants to flood the zone and destroy trust in institutions and the concept of truth. There's a good reason that the fascists love it.
Straightforward Spam and Fraud
This is kind of obvious, but LLMs can generate lightly-customized, plausible-looking text much more quickly than any human being. This facilitates their use in fraud, spam, and scams. In a spamming or fraudulent interaction, once again, the costs are externalized onto the victim: the recipient of a spam message has to do all the work of "checking" the LLM's output. Spammers already expect very low hit rates from boilerplate, and if the LLM can increase those percentages from 1% to 5% the technology will pay for itself; they don't need anything like reliable accuracy.
Customer "Support"
If you have any kind of commercial relationship with a company, I probably don't even need to mention this: customer "support" bots are a misery. Everybody knows it at this point. But customer support is usually conceptualized by businesses as an adversarial interaction, because it is a cost center. They maintain internal metrics on time-to-resolution and try to optimize them. Implicitly, this creates a dynamic where the goal of the customer service agent's job is not to solve your problem, but to emit noise that will cause you to think your problem is resolved, or to give up, as fast as possible. Unsurprisingly, LLMs can emit this noise faster than humans can, getting those customers off the phone. But those customers will remember those interactions, and the story outside the TTR metrics is horrible.
Similarly to the situation in software development, LLMs can look very good on paper for customer support, but mostly what they are doing is illuminating the problems with the industry's existing metrics, by turning "winning the metrics battle against the customer" into a more obvious and immediate defeat for the company's long term reputation.
"Education"
In 2026 it is sadly a fact of life that students cheat all the time using "AI", and that this cheating is very successful, in that the teachers find it very hard to detect.
LLMs are great for cheating on schoolwork because the student is externalizing the work of the checking onto the teachers, who are often starting at a disadvantage to begin with, at least in the US.
My view is that this is happening because of a divergence in the way that students vs. teachers (or, more accurately, "the broader educational system") view grading.
When a student is asked to write an essay, the teachers see the effort as both intrinsically worthwhile for the student, as well as useful as a pedagogical tool to evaluate and react to the student's progress. The student, by contrast, sees a stumbling block designed to knock them off the path to success and into a permanent underclass. It is no wonder that the student sees "AI" as useful to their own goals and has no compunction about deploying it.
There is a bitter irony that the ability to understand the inherent value of actually writing the essay on their own is the sort of thing that students can really only learn by writing a bunch of essays. There's no way that I can think of which makes the benefit legible as long as a shortcut is available.
The net effect here is a downward spiral, where the already-wobbling educational system is sustaining an attack that it doesn't have the resources to recover from. The individual students' attacks against their teachers and their schools' grading systems might appear to momentarily succeed, but they will win the battle and lose the war.
Spamming "For Good"?
Usually when we talk about someone unilaterally choosing to enter into an adversarial relationship, that's an "attack" and for good reasons we have a negative impression of the attacker. However, I would be remiss if I did not point out that there are some cases where the relationship was already adversarial; just because you're the attacker doesn't mean that you are evil.
For example we might imagine use-cases like automatically filing appeals for prior authorizations against health insurance. It's relatively well-known at this point that the main way for-profit insurers maintain their margins is by denying claims right up to the line of the policies themselves being fraud, so using a spamming tool to fight them might be entirely justifiable2 in that case.
Similarly, using an LLM could be justified in a fight against a company refusing to honor a warranty. One could imagine using an LLM to immediately generate replies and escalations.
However, even in imagined cases like these, the underlying problem is that the insurers and the vendors already have a tremendous amount of structural power, so it is more likely that they will have the advantage in deploying a communications weapon like an LLM, as well as enacting policies to simply ignore any LLM-based communication that you might submit. Worse, if these strategies were to become widespread, they might provide an excuse to reject any communications by feeding them into an unreliable "LLM detector" and issuing an automated "computer says no" even to hand-written correspondence.
It is also worth stressing that these cases are imagined, as compared to the very real coworker-abuse, spam, scam, fraud, and disinformation campaigns being waged in real life today.
Therefore, while legitimate uses might exist, it's hard to imagine that there's anywhere they would be genuinely valuable and sustainable. In the best case "AI" will provide a temporary advantage for underdogs that will provoke an arms race which the resource-advantaged adversaries will win in the long run, in the worst case the arms race itself will cement permanent structural change that will make things worse.
"Search" By Stealing
Most of the adversarial utility of "AI" is on the "write" side, since write-amplification is more obviously aggressive than reading. But the "read" side of LLMs - summarization and question-answering - can be a form of attack as well.
To begin with, the act of reading itself is currently enormously destructive, but that's arguably not a fundamental aspect of this technology. They could set reasonable rate-limits and respect things like robots.txt, as search engines have for decades now. They could also refrain from committing criminal levels of copyright infringement. But, today, using "AI" tools does suborn this sort of out-of-control crawling.
More insidiously, consider the scenario described in this YouTube video. The LTT Bros decided to try Linux again, and in the course of so doing, they had problems. When trying to solve these problems, they were faced with a choice: they could consult Reddit, or they could ask an LLM. Asking an LLM would "gaslight the heck out of" them, but they still found it preferable, because they would at least get an answer without getting yelled at.
Initially this sounds great. But it also means that you want to extract knowledge from a community, while mechanically eliding any values or norms that the community may want to impart as part of offering that knowledge. As someone who spent many years in a community tech support role, this is worrying. Many requests for support are people asking how to do things that will momentarily solve a superficial problem but create a long-term reliability problem or even an immediate security risk, that the question-asker doesn't want to hear about. Consider the question "I'm tired of entering my password so much, how do I make it so my laptop unlocks automatically". An obsequious chatbot will helpfully tell you how to do this without pushback.
But, this is also a sort of ethically murky area. The Linux community is somewhat famously, for many years now, a toxic cesspool of general hostility, misogyny, etc. It is certainly a good thing that people can get access to this knowledge without subjecting themselves to abuse. But it also means that the people with the power and the privilege to change the community for the better can just quietly withdraw, rather than fixing the problems. It also means that the positive elements of culture cannot be transmitted, and people will have no opportunity to learn about unknown unknowns.
In this case, the "adversarial" communication is with society. The thing that using an LLM for search lets you do is withdraw from society and avoid forming any personal connections. There are some personal connections which are painful and annoying, and so that can feel like a momentary balm. But the need to make connections in general is, like, the concept of society itself.
Who Am I Hurting?
LLMs are good at adversarial communication. They are so good at it, relative to their other benefits, that they will tend to make communications adversarial if you are not remaining vigilant about the possibility that it might do so. My request to you, dear reader, if you are going to use such tools, is to always ask yourself, "who might I be hurting, if I use an LLM for this?"
If you're using an "AI", who is its adversary? If you haven't given it one yet, who might the "AI" turn into an adversary? Who might you overwhelm with an asymmetric amount of output, or, if you're receiving information and not sending it, who are you taking that information from without consulting?
Figure out the answers to these questions and conduct yourself accordingly; the answer might be "yourself".
Acknowledgments
Thank you to my patrons who are supporting my writing on this blog. If you like what you've read here and you'd like to read more of it, or you'd like to support my various open-source endeavors, you can support my work as a sponsor!
-
One of the reasons that software developers tend to prefer greenfield development is that when you are given a blank page, you can project your own specific understanding onto it. You can structure the codebase in a way that works for your brain, down to the variable naming conventions and the module layouts. LLM-assisted development makes everything into instant brownfield work, which makes developers instantly miserable; even those who are excited about the technology will frequently complain about how it feels like their agency has been stolen and their joy in the work has been diminished. But I digress. ↩
-
Modulo the massive amount of other externalities involved in using LLMs, of course, but I don't have the time or energy to get into those here. ↩
23 Jun 2026 8:06pm GMT
09 Jun 2026
Planet Twisted
Hynek Schlawack: How to Ditch Codecov for Python Projects
Codecov's unreliability breaking CI on my open source projects has been a constant source of frustration for me for years. I have found a way to enforce coverage over a whole GitHub Actions build matrix that doesn't rely on third-party services.
09 Jun 2026 12:00am GMT