❌

Normal view

How to use virtual environments in Python

10 June 2026 at 10:00

Of all the reasons Python is a hit with developers, one of the biggest is its broad and ever-expanding selection of third-party packages. Convenient toolkits for everything from ingesting and formatting data to high-speed math and machine learning are just an import or pip install away.

But what happens when those packages don’t play nice with each other? What do you do when different Python projects need competing or incompatible versions of the same add-ons? That’s where Python virtual environments come into play.

What are Python virtual environments?

A virtual environment is a way to have multiple, parallel instances of the Python interpreter, each with different sets of packages and different configurations. Each virtual environment contains a discrete copy of the Python interpreter, including copies of its support utilities (such as the package manager pip).

The packages installed in each virtual environment are seen only in that virtual environment and no other. Even large, complex packages with platform-dependent binaries can be corralled off from each other in virtual environments.

Why use Python virtual environments?

There are a few common use cases for a virtual environment:

  1. You’re developing multiple projects that depend on different versions of the same packages, or you have a project that must be isolated from certain packages because of a namespace collision. This is the most standard use case.
  2. You’re working in a Python environment where you can’t modify the site-packages directory. This may be because you’re working in a highly controlled environment, such as managed hosting, or on a server where the choice of interpreter (or packages used in it) can’t be changed because of production requirements.
  3. You want to experiment with a specific combination of packages under highly controlled circumstances, for instance to test cross-compatibility or backward compatibility.
  4. You want to run a “baseline” version of the Python interpreter on a system with no third-party packages, and only install third-party packages for each individual project as needed.

Nothing says you can’t simply unpack a Python library into a subfolder of a project and use it that way. Likewise, you could download a standalone copy of the Python interpreter, unpack it into a folder, and use it to run scripts and packages devoted to it.

But managing such cobbled-together projects soon becomes difficult. It only seems easier to do that at first. Working with packages that have binary components, or that rely on elaborate third-party dependencies, can be a nightmare. Worse, reproducing such a setup on someone else’s machine, or on a new machine you manage, is tricky.

The best long-term solution is to use Python’s native mechanisms for creating, reproducing, and working with virtual environments.

How to use virtual environments in Python 3

Python has native tooling for virtual environments that makes the whole process quite simple. This wasn’t always the case, but now all supported versions of Python use the native virtual environment tool, venv.

Create the Python virtual environment

To create a virtual environment in a given directory, type:

python3 -m venv /path/to/venv

For instance, to create the virtual environment in the current directory, using the subdirectory .venv type:

python3 -m venv .venv

On Microsoft Windows, you can use py instead of python3 to reliably access an installed Python version. (See this article for more about using the py launcher in Windows.)

The exact name for the virtual environment directory is arbitrary, but it’s typically .venv.

The whole process of setting up the virtual environment may take a minute or two. When it’s finished, you should see that directory with a few subdirectories in it. The most important subdirectory is bin on Unix or Scripts on Windows, which is where you’ll find the copy of the Python interpreter for the virtual environment along with its utilities.

Note that because each virtual environment contains its own copy of the Python interpreter, it can be fairly large. A Python 3.13 virtual environment will consume anywhere from 14MB to 26MB of disk space, depending on the operating system.

Venvs and version control

If you are setting up a virtual environment in a project directory managed with some kind of version control system (e.g., Git), exclude the environment directory from tracking before you make any commits after creating the venv.

Venvs should not be tracked along with their associated code, as they are meant to be destroyed and recreated as needed. You should, however, track the requirements.txt or pyproject.toml files associated with the project, as those are used to describe what gets installed in the venv for that project.

Activate the Python virtual environment

Before you can use this virtual environment, you need to explicitly activate it. Activation makes the virtual environment the default Python interpreter for the duration of a shell session.

You’ll need to use different syntax for activating the virtual environment depending on which operating system and command shell you’re using.

  • On Unix or MacOS, using the bash shell: source /path/to/venv/bin/activate
  • On Unix or MacOS, using the csh shell: source /path/to/venv/bin/activate.csh
  • On Unix or MacOS, using the fish shell: source /path/to/venv/bin/activate.fish
  • On Windows using the Command Prompt: path/to/venv/Scripts/Activate.bat
  • On Windows using PowerShell: path/to/venv/Scripts/Activate.ps1

Note that the activated environment only works for the context it was activated in. For instance, if you launch two instances of PowerShell, A and B, and you activate the virtual environment in instance A, that environment will apply only to A, not B.

Many Python IDEs will automatically detect and activate a virtual environment if one is found in the current project directory. Visual Studio Code, for instance, can do this when the Python extension is enabled. Opening a terminal inside Visual Studio Code will automatically activate the selected virtual environment. PyCharm automatically creates a virtual environment for each new project and enables it automatically.

Configure and use the Python virtual environment

Once you’ve activated the new virtual environment, you can use the pip package manager to add and change packages for it. You’ll find pip in the Scripts subdirectory of the virtual environment on Windows, and in the bin subdirectory on Unix OSes.

If you’re already familiar with the way pip works, you’re set. It should be just the same in a virtual environment. Just make sure you’re using the instance of pip that manages packages for the virtual environment in the context where it was activated—e.g., the bash session or Windows CLI/PowerShell session. If you want to verify that you’re using the right pip and the right virtual environment, type pip -V and check that the path it displays points to a subdirectory of your virtual environment.

Note that when you want to upgrade pip in a virtual environment, it’s best to use the command python3 -m pip install -U pip. This ensures the upgrade process is run in such a way that Python doesn’t lock crucial files. The command pip install -U pip may not be able to complete the upgrade properly.

To use the virtual environment you created to run Python scripts, simply invoke Python from the command line in the context where you activated it. For instance, to run a script, just run python3 myscript.py.

With PyCharm, you can use the IDE’s own package management interface to manage the packages installed in your project.

Managing packages in Python virtual environments

When you create a new virtual environment, pip will be installed, but that’s all. You’ll need to install any other packages you want to use in the environment. For projects with complex requirements, it is customary to keep in the root of the project a requirements.txt file that lists the requirements for the project. This way, if you need to recreate the virtual environment, you can reinstall all of the needed packages with the command pip install -r requirements.txt.

More recently, a new project metadata format has emerged for Python projects, called pyproject.toml. A pyproject.toml file contains the package requirements of the project, but also a great deal of other information about it. To install those requirements, you’d run pip install . in the same directory as the pyproject.toml file.

Note that the copy of pip that lives in a virtual environment is local to that virtual environment. Each virtual environment has its own copy, which will need to be updated and maintained independently. This is why you may get warnings about pip being out of date in some virtual environments but not others; pip has to be updated in each virtual environment separately.

Deactivating the Python virtual environment

When you’re done using the virtual environment, you can just terminate the session where you were using it. If you want to continue to work in the same session but with the default Python interpreter instead, type deactivate at the prompt. Windows users on the Command Prompt need to run deactivate.bat from the Scripts subdirectory, but Unix users and Windows users running PowerShell can simply type deactivate in any directory.

Removing the Python virtual environment

Virtual environments are self-contained. When you no longer need the virtual environment, you can simply delete its directory. Just make sure you first close any running copies of Python that use the virtual environment.

Whenever you want to refresh or recreate a virtual environment, you can simply delete the current environment directory and recreate the venv as described above (see “Managing packages in Python virtual environments”). This is typically the easiest way to upgrade a project to a newer version of Python: delete or temporarily re-name the venv directory (in case the new version doesn’t work), then create a new one and install the project requirements into it.

If you have many older projects that aren’t being actively used, you can remove their environments to save space. They can be recreated easily whenever needed, although you will want to note which version of Python was used to create them along with the needed packages (typically recorded in requirements.txt or pyproject.toml).

Relocating the Python virtual environment

It’s tempting to assume a virtual environment can be copied and moved around along with its project. Don’t do this. Virtual environments are tied to the location of the Python installation on the system where they’re created. If you want to move the project to another system, leave out the venv directory, and recreate the venv on the target machine. Do copy and move the requirements.txt or pyproject.toml file with the project, because those files are needed to recreate the venv on the other system.

How to use virtual environments in Python 2

With Python 2, virtual environments aren’t a native feature of the language. Instead, you need to install third-party libraries to create and manage virtual environments.

The most popular and widely used of these projects is virtualenv, which handles creating the directory structure and copying the needed files into a virtual environment. To install virtualenv, just use pip install virtualenv. To create a virtual environment directory with it, type virtualenv /path/to/directory. Activating and deactivating the virtual environment works the same way as it does for virtual environments in Python 3 (see above).

Note that Python 2 should not be used for any new development. Virtual environments in Python 2, like Python 2 itself, should be used only for the maintenance of legacy projects that should eventually be migrated to Python 3.

Virtual environments and the main Python package directory

Normally, when you create a venv, it cannot work with the packages already present in the Python installation that created it. This is by design, as it ensures that packages installed globally don’t interfere with local ones.

You can override this behavior, but only when you first create a virtual environment. If you pass the flag --system-site-packages to venv when you run it, the created venv will have access to the parent Python’s package directory.

Using Python virtual environments with Jupyter notebooks

If you’re using Jupyter notebooks (aka IPython notebooks), and you already have Jupyter installed systemwide, create your virtual environment and activate it. Then, from your virtual environment directory, run pip install ipykernel to add the needed components for IPython. Finally, run ipython kernel install —user —name=, where project_name is a name you want to associate with that particular project. From there you should be able to launch Jupyter and switch to the IPython kernel you installed inside the virtual environment.

Upgrading Python virtual environments

When you upgrade a Python runtime on your system, virtual environments that use that version of Python aren’t automatically upgraded. That’s your responsibility. And that’s by design, because unwitting upgrades to Python versions can break their attendant packages.

If you’ve upgraded an existing Python interpreter with a minor point upgrade—e.g., from Python 3.13.1 to Python 3.13.3—you can upgrade any corresponding virtual environments easily enough. From a command prompt in the project directory, enter:

python -m venv /path/to/venv --upgrade

Don’t activate the virtual environment beforehand, or the upgrade may not work.

Alternatively, as noted above (see “Removing the Python virtual environment”), you could elect to remove the venv completely and recreate it using your requirements.txt or pyproject.toml file.

If you’ve installed a major new version of Python—e.g., you already have Python 3.10 and you now install Python 3.11 alongside it—you’ll need to create a new virtual environment that specifically uses the new major point version. Do not attempt to upgrade an existing virtual environment to a higher major point version of Python.

EU rules on securing IT products could affect open source software users beginning this week

10 June 2026 at 11:09

Too many enterprises remain ignorant of the European Union’s 2024 Cyber Resilience Act, the first elements of which enter force on June 11, according to a new survey.

Two-thirds of respondents to the survey by Open Source Security Foundation said they were unfamiliar with the CRA, which aims to make hardware and software sold in the EU more secure.

As well as the CRA’s demands on vendors, it also has implications for users of open-source software, hence the Foundation’s interest in the topic. Among other measures, the CRA creates the role of open-source steward within the enterprise, with responsibility for ensuring that a security policy is in place for any software being used within the organization.

The first part of the CRA to enter force, on June 11, concerns the designation of conformity assessment bodies by member states. Then, from September 11, manufacturers will be required to begin reporting vulnerabilities in their products to the relevant authorities. The remaining obligations under the Act, which include substantial financial penalties, will apply from December 11, 2027.

The impending sanctions seem not to have concerned businesses: 56 percent of respondents to the OpenSSF survey were unaware that non-compliance fines could reach €15 million or 2.5 percent of global annual turnover.

The lack of knowledge about the implications of the Act surprised OpenSSF CTO Christopher Robinson. “We’ve been speaking on this topic for some time and we’re scratching our heads on why more companies are not aware of the implications of the Act,” he said.

Global concern

He surmised that some companies don’t think EU regulations on hardware and software security apply to them — but such concerns will soon be a global matter. “Other countries, like Japan, are considering similar laws,” he said.

One area of misunderstanding could be that the CRA applies to vendors, and their customers may think that the requirements under the Act didn’t apply to them. He said that this was a misguided approach, particularly when the CRA’s application to open-source software is taken into account.

“There are about 700 million projects in Git Hub. If you work for an organization like a bank, you have little idea which of those projects are being used,” he said.

Under the Act, software companies will have to supply a software bill of materials (SBOM) that has been passed as secure, he said.

Companies that supply US federal government organizations already face this requirement, he said: “If you’re selling to the US government — which is the largest customer on the planet – you should be providing an SBOM.”

Cybersecurity consultant Hans Study said that by addressing the supply chain issue, the CRA is a step in the right direction. “Almost every application has dependencies, whether that is free and open-source software, commercial packages, or some mix of both. The problem has always been responsibility, and the blame game that comes with it. What the CRA does is make it harder for companies to dodge that responsibility when they are building, selling, or placing products with digital elements on the market,” he said.

AI ignorance

According to Michael Callahan, VP of Cyber Strategy at Salt Security, one of the issues that could cause problems in the future is the growing use of AI in the software development process. “The Cyber Resilience Act assumes enterprises know what is in their software. That assumption breaks down when AI coding assistants are generating a significant share of code. An AI assistant has never read your organization’s security policies, your licensing obligations, or your open-source governance standards. The code it produces may contain dependencies, patterns, or vulnerabilities that your security team cannot easily trace back to a specific decision or a specific developer.”

Enterprises are quickly running out time to fix issues and many are pessimistic about their chances. According to the OpenSSF survey, only 41percent of manufacturers expect to be fully compliant by December 2027, while 39 percent do not know when they will be.

It may be that the proposed fines could concentrate minds. Robinson said that it could be like GDPR where a few heavy fines drew companies’ attention to the regulation. The upper limit on fines is per infraction, not per company, he said: “Something like that could wipe out an SME and seriously hit large corporations.” The legislation should be something that all businesses need to be aware of, but there is still a long way to go.

This article first appeared on CIO.

The tokenmaxxing backlash is coming

10 June 2026 at 10:00

I’ve been around long enough to remember when deploying an application meant copying a *.exe file from the developer’s machine right into production. I am not making this up. It was that simple, and that fraught with peril. Applications weren’t complex — they were often not anything more than that simple *.exe file — and the process around deployment didn’t need to be anything complex, but it probably should have been.

Proper deployment of an application is something we’ve learned to do over the years. The process of properly building, testing, and deploying an application has grown more complex for two reasons. First, the process must ensure that every deployment succeeds. Deploying complex applications can be convoluted and challenging, and a strict deployment process ensures everything happens properly and runs correctly. Second, the process must thoroughly test the application to make sure that all the moving parts work together to create a properly functioning application. 

Today’s continuous deployment processes were hard-won from many lessons learned. Eventually, these practices became formalized, even to the point where the Sarbanes-Oxley Act was understood to require that IT departments formally document their deployment processes. 

This kind of governance is what separates professional software development organizations from those that, well, don’t know what they are doing. 

Agentic growing pains

Agentic development is headed in this same direction, but it’s all happening a bit more quickly. It was just a few months ago that people began to use AI to write code seriously. At first, most of us were doing it furtively, having Claude Code find and fix bugs, and then quietly checking in the solutions. Maybe we were a bit hesitant to mention that we had done this, but then we felt guilty about doing it and taking credit, and eventually we mentioned it. But it soon became apparent — like “within a week” soon — that Claude Code was up to the task, and we became pretty open about it. 

Very quickly, it not only became accepted but actually encouraged, and we were off to the races. In a month, everyone was tokenmaxxing.

It almost seems a bit out of control. Sure, there is a lot of code being generated and non-trivial amounts of money being spent, but it isn’t quite clear if the results are worth the effort. I’m not at all sure if anyone can say that the money spent is returning the value needed.

At some point, as an industry, we are going to have to get control of all of this. I fear that there will be a rush to impose governance over the whole thing. This, like deploying an .exe directly, is also fraught with peril. Right now, there appears to be little control over what tools are being used where, how much is being spent for what purpose, and what that spending is actually getting us. 

The governance over our deployment processes was successful and useful because it arose organically. The accepted, codified procedures arose from the lessons that practitioners learned by actually building and deploying applications. We all should work to ensure that a similar process happens with agentic coding.

Developers know best

Because agentic coding is happening so quickly and so furiously, the danger is that a governance process will be imposed over the top just as quickly and furiously. I want to encourage us all to take a deep breath, slow down a bit, and take a close look at what we are doing, and more importantly, how we are doing it. 

Agentic coding will be governed in some manner. It’s critical that we practitioners take the lead in providing that governance, or we’ll have governance forced upon us. We are the ones that know what matters and how the tools should be used. We are the ones with skin in the game and the ones keeping pace with the technology. 

Top-down governance of a technology moving this fast will never be able to keep up. Or as Uri Haramati, co-founder and CEO of Torii says, “The person closest to the tool usually understands why it’s being used, and governance works better when it includes those people instead of trying to control them.”

Copying that *.exe file into production is comically reckless. We don’t do that anymore because we know better. It took time, but we learned the right way to deploy software. Right now, we are in the “copying the *.exe” phase of agentic coding, and we need to figure out the right way to do it before someone comes along and does it for us.

Enterprises know AI-generated code is vulnerable; they’re shipping it anyway

10 June 2026 at 04:01

AI-generated code is riddled with security flaws, yet enterprises are shipping more of it than ever before. Why? Perhaps they’re over-confident, lack true visibility into security risks, or are simply choosing to ignore the problem and hope it goes away.

It’s a dangerous game to play at the dawn of the agentic AI era, as underscored in a new report from app security company Checkmarx.

The survey of thousands of security leaders exposes an underlying naivete about AI-built code and its vulnerabilities, even as tools like Anthropic’s Mythos are uncovering security flaws orders of magnitude faster than any human security team could ever hope to.

“Mythos-class models collapse the window between a vulnerability existing and a working exploit being available from months to minutes,” the report notes. Enterprises relying on traditional security tools and methods, it says, “cannot survive this reality.”

Security as an afterthought

Checkmarx’s survey of 2,350 CISOs, AppSec managers, and developers across 14 countries focused on how much AI-developed code enterprises are deploying, the vulnerabilities it introduces, how it impacts developer workflows, and overall sentiment about AI code and security posture.

Today, nearly half of production code is AI-generated, and the majority of enterprises also report that at least half their codebase is made up of open-source components, according to the report.

But the more AI-generated code that is pushed out, the more vulnerabilities are exposed. Enterprises who said 81% – 100% of their code is built by AI ship vulnerable code 3.4 times more often than businesses using AI more conservatively, relying on 20% or less AI code.

Additionally, 70% of developers said that AI code generation created vulnerabilities in 2025, and almost all enterprises surveyed (93%) had at least one security breach as a direct result of in-house developed apps.

Still, risk is becoming “normalized,” the report notes, with three-quarters of enterprises knowingly deploying vulnerable code as they face increased pressure for ROI. Startlingly, about 30% of respondents admitted they ship compromised code and hope the vulnerability won’t be found. Similarly, more than a third of organizations leave half of their known vulnerabilities unfixed for 90 days or more.

The report points out that the organizational bottleneck isn’t detection, “it’s the human decision to ship anyway, suppress the finding, or defer to the next sprint.”

Along with this, AppSec teams are often limited to reactive incident response as they deal with tool sprawl. And developers only continuously secure code a small percentage of the time (18%), even though nearly all are equipped with security tooling.

Ultimately, developers are “set up to fail,” the report contends. They face significant pressure to deliver, and are forced to choose quantity and speed over security. Yet, even as they face significant consequences when it comes to post-mortems, performance reviews, escalation, and blocked releases, the tools that contribute to security issues, delivering low-value findings, unclear guidance, or late feedback, continue to go unfixed.

“Developers remain accountable for outcomes, even when systems and workflows are not aligned to support them,” the report notes.

Overconfidence, outdated practices

Alarmingly, many enterprises seem to be deluded when it comes to their security posture. Of those that rate themselves as “highly mature” AI organizations, 42% often ship the most vulnerable code, and have breach rates “barely distinguishable” from other enterprises.

“Confidence isn’t protecting them,” the report notes. “It’s blinding them.”

Underscoring this, only 22% of organizations have formal AI governance, and developers still rely on manual code reviews to ensure their code meets compliance standards.

The result is a mismatch between the speed of software creation and the speed of governance, the report notes. “Compliance frameworks are evolving, but many organizations are still attempting to govern AI-scale development with processes designed for a slower era of software delivery.”

Strategic imperatives for enterprises

Enterprises do seem to have wised up (a bit) after Anthropic’s Mythos proved capable of not only discovering vulnerabilities across major operating systems and browsers, but exploiting them 100 times faster than previous Claude models. And the subsequent Project Glasswing almost immediately surfaced thousands of previously-unidentified security flaws.

Checkmarx’s survey, which, it should be noted, was conducted a month prior to Mythos’ arrival, found that enterprises are finally taking proactive measures, focusing more heavily on AI security threats overall, and investing more in DevSecOps practices, automation, and developer training.

The report emphasizes the importance of prioritizing risk over code volume; vulnerabilities should not be considered isolated incidents. Also, it’s critical to embed security into developer workflows rather than treating it as a checkpoint. Enterprises must have systems that reduce noise, provide clear guidance, and allow them to take action when an issue arises.

Security “must be integrated directly into how developers write, test, and ship code within the IDE, pipelines, and AI-assisted workflows where development now happens,” the report notes.

Similarly, enterprises would benefit by reducing fragmentation and tool sprawl and defining ownership of the AI tools. By simplifying security stacks, they can align responsibilities and ensure consistent tool use, according to the report.

Further, AI needs strong governance, and teams must move beyond outdated manual triage and “human-gated remediation.” AI can fight AI in a strong system built to prioritize, remediate, and resolve risk “without waiting for a human to approve each step,” the report notes.

Ultimately, it says: “Progress depends on embedding intelligence directly into workflows, enabling risks to be prioritized, remediated, and resolved, all within the systems that they operate in.”

This article originally appeared on CIO.com.

How to use virtual environments in Python

9 June 2026 at 17:05

Of all the reasons Python is a hit with developers, one of the biggest is its broad and ever-expanding selection of third-party packages. Convenient toolkits for everything from ingesting and formatting data to high-speed math and machine learning are just an import or pip install away.

But what happens when those packages don’t play nice with each other? What do you do when different Python projects need competing or incompatible versions of the same add-ons? That’s where Python virtual environments come into play.

What are Python virtual environments?

A virtual environment is a way to have multiple, parallel instances of the Python interpreter, each with different sets of packages and different configurations. Each virtual environment contains a discrete copy of the Python interpreter, including copies of its support utilities (such as the package manager pip).

The packages installed in each virtual environment are seen only in that virtual environment and no other. Even large, complex packages with platform-dependent binaries can be corralled off from each other in virtual environments.

Why use Python virtual environments?

There are a few common use cases for a virtual environment:

  1. You’re developing multiple projects that depend on different versions of the same packages, or you have a project that must be isolated from certain packages because of a namespace collision. This is the most standard use case.
  2. You’re working in a Python environment where you can’t modify the site-packages directory. This may be because you’re working in a highly controlled environment, such as managed hosting, or on a server where the choice of interpreter (or packages used in it) can’t be changed because of production requirements.
  3. You want to experiment with a specific combination of packages under highly controlled circumstances, for instance to test cross-compatibility or backward compatibility.
  4. You want to run a “baseline” version of the Python interpreter on a system with no third-party packages, and only install third-party packages for each individual project as needed.

Nothing says you can’t simply unpack a Python library into a subfolder of a project and use it that way. Likewise, you could download a standalone copy of the Python interpreter, unpack it into a folder, and use it to run scripts and packages devoted to it.

But managing such cobbled-together projects soon becomes difficult. It only seems easier to do that at first. Working with packages that have binary components, or that rely on elaborate third-party dependencies, can be a nightmare. Worse, reproducing such a setup on someone else’s machine, or on a new machine you manage, is tricky.

The best long-term solution is to use Python’s native mechanisms for creating, reproducing, and working with virtual environments.

How to use virtual environments in Python 3

Python has native tooling for virtual environments that makes the whole process quite simple. This wasn’t always the case, but now all supported versions of Python use the native virtual environment tool, venv.

Create the Python virtual environment

To create a virtual environment in a given directory, type:

python3 -m venv /path/to/venv

For instance, to create the virtual environment in the current directory, using the subdirectory .venv type:

python3 -m venv .venv

On Microsoft Windows, you can use py instead of python3 to reliably access an installed Python version. (See this article for more about using the py launcher in Windows.)

The exact name for the virtual environment directory is arbitrary, but it’s typically .venv.

The whole process of setting up the virtual environment may take a minute or two. When it’s finished, you should see that directory with a few subdirectories in it. The most important subdirectory is bin on Unix or Scripts on Windows, which is where you’ll find the copy of the Python interpreter for the virtual environment along with its utilities.

Note that because each virtual environment contains its own copy of the Python interpreter, it can be fairly large. A Python 3.13 virtual environment will consume anywhere from 14MB to 26MB of disk space, depending on the operating system.

Venvs and version control

If you are setting up a virtual environment in a project directory managed with some kind of version control system (e.g., Git), exclude the environment directory from tracking before you make any commits after creating the venv.

Venvs should not be tracked along with their associated code, as they are meant to be destroyed and recreated as needed. You should, however, track the requirements.txt or pyproject.toml files associated with the project, as those are used to describe what gets installed in the venv for that project.

Activate the Python virtual environment

Before you can use this virtual environment, you need to explicitly activate it. Activation makes the virtual environment the default Python interpreter for the duration of a shell session.

You’ll need to use different syntax for activating the virtual environment depending on which operating system and command shell you’re using.

  • On Unix or MacOS, using the bash shell: source /path/to/venv/bin/activate
  • On Unix or MacOS, using the csh shell: source /path/to/venv/bin/activate.csh
  • On Unix or MacOS, using the fish shell: source /path/to/venv/bin/activate.fish
  • On Windows using the Command Prompt: path/to/venv/Scripts/Activate.bat
  • On Windows using PowerShell: path/to/venv/Scripts/Activate.ps1

Note that the activated environment only works for the context it was activated in. For instance, if you launch two instances of PowerShell, A and B, and you activate the virtual environment in instance A, that environment will apply only to A, not B.

Many Python IDEs will automatically detect and activate a virtual environment if one is found in the current project directory. Visual Studio Code, for instance, can do this when the Python extension is enabled. Opening a terminal inside Visual Studio Code will automatically activate the selected virtual environment. PyCharm automatically creates a virtual environment for each new project and enables it automatically.

Configure and use the Python virtual environment

Once you’ve activated the new virtual environment, you can use the pip package manager to add and change packages for it. You’ll find pip in the Scripts subdirectory of the virtual environment on Windows, and in the bin subdirectory on Unix OSes.

If you’re already familiar with the way pip works, you’re set. It should be just the same in a virtual environment. Just make sure you’re using the instance of pip that manages packages for the virtual environment in the context where it was activated—e.g., the bash session or Windows CLI/PowerShell session. If you want to verify that you’re using the right pip and the right virtual environment, type pip -V and check that the path it displays points to a subdirectory of your virtual environment.

Note that when you want to upgrade pip in a virtual environment, it’s best to use the command python3 -m pip install -U pip. This ensures the upgrade process is run in such a way that Python doesn’t lock crucial files. The command pip install -U pip may not be able to complete the upgrade properly.

To use the virtual environment you created to run Python scripts, simply invoke Python from the command line in the context where you activated it. For instance, to run a script, just run python3 myscript.py.

With PyCharm, you can use the IDE’s own package management interface to manage the packages installed in your project.

Managing packages in Python virtual environments

When you create a new virtual environment, pip will be installed, but that’s all. You’ll need to install any other packages you want to use in the environment. For projects with complex requirements, it is customary to keep in the root of the project a requirements.txt file that lists the requirements for the project. This way, if you need to recreate the virtual environment, you can reinstall all of the needed packages with the command pip install -r requirements.txt.

More recently, a new project metadata format has emerged for Python projects, called pyproject.toml. A pyproject.toml file contains the package requirements of the project, but also a great deal of other information about it. To install those requirements, you’d run pip install . in the same directory as the pyproject.toml file.

Note that the copy of pip that lives in a virtual environment is local to that virtual environment. Each virtual environment has its own copy, which will need to be updated and maintained independently. This is why you may get warnings about pip being out of date in some virtual environments but not others; pip has to be updated in each virtual environment separately.

Deactivating the Python virtual environment

When you’re done using the virtual environment, you can just terminate the session where you were using it. If you want to continue to work in the same session but with the default Python interpreter instead, type deactivate at the prompt. Windows users on the Command Prompt need to run deactivate.bat from the Scripts subdirectory, but Unix users and Windows users running PowerShell can simply type deactivate in any directory.

Removing the Python virtual environment

Virtual environments are self-contained. When you no longer need the virtual environment, you can simply delete its directory. Just make sure you first close any running copies of Python that use the virtual environment.

Whenever you want to refresh or recreate a virtual environment, you can simply delete the current environment directory and recreate the venv as described above (see “Managing packages in Python virtual environments”). This is typically the easiest way to upgrade a project to a newer version of Python: delete or temporarily re-name the venv directory (in case the new version doesn’t work), then create a new one and install the project requirements into it.

If you have many older projects that aren’t being actively used, you can remove their environments to save space. They can be recreated easily whenever needed, although you will want to note which version of Python was used to create them along with the needed packages (typically recorded in requirements.txt or pyproject.toml).

Relocating the Python virtual environment

It’s tempting to assume a virtual environment can be copied and moved around along with its project. Don’t do this. Virtual environments are tied to the location of the Python installation on the system where they’re created. If you want to move the project to another system, leave out the venv directory, and recreate the venv on the target machine. Do copy and move the requirements.txt or pyproject.toml file with the project, because those files are needed to recreate the venv on the other system.

How to use virtual environments in Python 2

With Python 2, virtual environments aren’t a native feature of the language. Instead, you need to install third-party libraries to create and manage virtual environments.

The most popular and widely used of these projects is virtualenv, which handles creating the directory structure and copying the needed files into a virtual environment. To install virtualenv, just use pip install virtualenv. To create a virtual environment directory with it, type virtualenv /path/to/directory. Activating and deactivating the virtual environment works the same way as it does for virtual environments in Python 3 (see above).

Note that Python 2 should not be used for any new development. Virtual environments in Python 2, like Python 2 itself, should be used only for the maintenance of legacy projects that should eventually be migrated to Python 3.

Virtual environments and the main Python package directory

Normally, when you create a venv, it cannot work with the packages already present in the Python installation that created it. This is by design, as it ensures that packages installed globally don’t interfere with local ones.

You can override this behavior, but only when you first create a virtual environment. If you pass the flag --system-site-packages to venv when you run it, the created venv will have access to the parent Python’s package directory.

Using Python virtual environments with Jupyter notebooks

If you’re using Jupyter notebooks (aka IPython notebooks), and you already have Jupyter installed systemwide, create your virtual environment and activate it. Then, from your virtual environment directory, run pip install ipykernel to add the needed components for IPython. Finally, run ipython kernel install —user —name=, where project_name is a name you want to associate with that particular project. From there you should be able to launch Jupyter and switch to the IPython kernel you installed inside the virtual environment.

Upgrading Python virtual environments

When you upgrade a Python runtime on your system, virtual environments that use that version of Python aren’t automatically upgraded. That’s your responsibility. And that’s by design, because unwitting upgrades to Python versions can break their attendant packages.

If you’ve upgraded an existing Python interpreter with a minor point upgrade—e.g., from Python 3.13.1 to Python 3.13.3—you can upgrade any corresponding virtual environments easily enough. From a command prompt in the project directory, enter:

python -m venv /path/to/venv --upgrade

Don’t activate the virtual environment beforehand, or the upgrade may not work.

Alternatively, as noted above (see “Removing the Python virtual environment”), you could elect to remove the venv completely and recreate it using your requirements.txt or pyproject.toml file.

If you’ve installed a major new version of Python—e.g., you already have Python 3.10 and you now install Python 3.11 alongside it—you’ll need to create a new virtual environment that specifically uses the new major point version. Do not attempt to upgrade an existing virtual environment to a higher major point version of Python.

8 cutting-edge web development tools you don’t want to miss

9 June 2026 at 10:00

There is no ordained path. The hope that we were converging on some kind of consensus in web development has been eradicated by recent, ingenious developments that point in almost every direction. Yet, if there is a central theme uniting these efforts, it is the desire to mitigate the layers of liturgical embellishment that have grown up around the reactive canon. How can we look at things differently to attain the power that we need, without the heavy intricacy?

Here are eight cutting-edge web development tools that point the way.

Front-end maestro

If you put a bunch of classical musicians in a room together with sheet music and let them run, you might get to a cohesive piece—but you probably want a conductor, a maestro who coordinates all of the parts. That is Astro for your front-end frameworks.

Astro addresses the “hydration” of the front end, that is to say, the process of making the shell reactive. In conventional server-side rendering (SSR), like Next.js or Nuxt, the server not only sends the HTML, but also sends the massive framework runtime down the wire, just to attach event listeners to the page. Astro allows you to write components in React, Svelte, Vue, or Solid, and its compiler strips away all of the JavaScript before it reaches the browser. Astro ships zero JS by default, relying on its islands architecture to hydrate only the specific components that demand interactivity. 

Because Astro isolates interactivity into distinct islands, sharing complex state between those islands (e.g., a complex filtering sidebar communicating with a separate dynamic data grid) is fundamentally harder than it is in a monolithic single-page application. If you are building a highly interactive, dashboard-heavy app where every component affects every other component, Astro’s isolated islands might begin to feel more like a straitjacket than a liberation.

See also: Qwik. If Astro unbloats by stripping away the JavaScript entirely, Qwik unbloats by delaying it. Qwik delivers instant HTML and serializes the application state, downloading and executing only the JavaScript code required for a specific interaction at the exact millisecond the user clicks a button.

Biome: Lint like it’s 2026

Rust is gradually replacing the underlying infrastructure in the JavaScript ecosystem. But while Rust gives Biome its close-to-the-metal speed, Biome’s true calling card is its unification of the sprawling toolchain under a cohesive umbrella.

The .eslintrc and .prettierrc files and the dozen associated plugins can become a dark and unhappy bog in a project. Biome is the way out of the mire. It is a single, blazingly fast binary that replaces your entire tangled formatting and linting ecosystem, providing a path to code quality that doesn’t require a sprawling web of dependencies.

Probably the biggest drawback to Biome is that you lose the wide-open extensibility—which is exactly the same feature that makes Biome lean.

See also: Rspack. Biome cleans up the linting. Rspack unbloats the build step. Also built on Rust for speed, Rspack challenges the new “unbundled” esbuild-based dev mode championed by Vite and uses bundled dev mode.

Bun: Fast and integrated back-end JavaScript

Most cutting-edge JavaScript enthusiasts are already well-aware of Bun. For those who haven’t yet experienced Bun’s enthralling blend of one-stop shopping and blistering speed first-hand, it’s a virtually irrefutable must-try.

Fast is probably an understatement. If you are used to Node and you try out Bun, you will likely be immediately impressed with the speed at which commands execute. The Bun team has also made an extensive, multi-year effort to bring its engine into close compatibility with Node’s APIs. Overall, Bun is an extraordinary engineering effort that every JS developer should explore.

However, while Bun’s Zig-based engine is in most respects a drop-in for Node, it isn’t perfect, especially when considering the gargantuan landscape of Node packages out there. Node remains the conservative, happy-path engine for server-side JavaScript. 

See also: Deno. Although Bun has justifiably earned a reputation for bleeding-edge innovation, Deno has quietly pressed ahead with an appealing set of enterprise features like an integrated deployment platform and a front-end framework (Deno Fresh).

The Bun curious also may want to check out my interview with Bun creator Jared Sumner.

HTMX: Ajax KISS

If we are talking about clever ways to de-complexify the web, HTMX could reasonably be considered the poster-child. It takes the core mechanisms of the modern web client, like Ajax and partial updates, and turns them into simple HTML attributes. That means the state lives exclusively on the server, which is responsible for sending HTMX fragments.

Of course, there are trade-offs. Perhaps most unavoidable is the extreme dependence on the network. Because there is no client-side state machine, the browser will be orphaned and helpless without a connection to the server. That is, unless you get experimental with a local-first datastore.

Long story short: if your app falls into the realm of HTMX’s ability, HTMX is likely to be the most direct RESTful way to build it. And HTMX can in fact handle quite a lot.

See also: Hotwire. A collection of tools for building single-page-style applications using HTML over the wire, Hotwire has great features like page morphing, which can diff HTML instead of cold-loading it, with a simple import. True to classic “free as in speech” software culture, the HTMX and Hotwire projects freely exchange ideas. 

PowerSync: Data layer redo

Although the local-first data revolution that PowerSync represents implies a fairly serious engineering deep dive, its core proposal — to entirely reshape the way data moves in web architecture — is something a web developer needs to be aware of.

Usually, we create architectures that require a complex middleware to broker between a reactive client and the datastore. PowerSync proposes a radical alternative: bypass the middleman entirely by dropping a robust SQLite Wasm database directly into the browser.

The UI works on local data using familiar SQL, synchronously. Latency is zero. The dreaded loading spinner vanishes entirely. In the background, PowerSync automatically reconciles your local store with your central Postgres database. It handles the complex syncing algorithms and network drops, effectively making your application offline-first by default.

The catch, of course, is that local-first development forces a massive mental shift. You have to define data slices (similar to a view) that each client user holds. The PowerSync engine does most of the hard work, but things like schema migrations and conflict resolution (when two users edit the same record while offline) require a significantly steeper initial setup than a standard REST API.

See also: RxDB. RxDB is a slightly different flavor of local-first datastore. Whereas PowerSync relies heavily on Postgres, SQLite, and background daemons, RxDB provides a NoSQL, offline-first, reactive database that treats queries as observable streams, pushing UI updates the exact millisecond the local data changes.

RooCode: Use any AI you want

The beauty of RooCode lies in its ability to orchestrate whatever AI providers you have—for free. RooCode is an extension to Visual Studio Code that provides an AI manager layer. This layer bridges between the general abilities of the LLM and your code-specific, project-level structures.

RooCode is strong enough to be somewhat agentic in its capabilities. It doesn’t reach the powerhouse abilities of something like Cursor or Antigravity, but it is quite able to handle most small to medium-sized requests. And it does so with a minimum of unnecessary overhead. I find myself often using RooCode alongside my AI-assisted IDE to knock out lesser requirements, for less cost and without interrupting the flow of ongoing epics.

RooCode keeps you free of proprietary ecosystems. It allows you to plug in your own API keys—whether that is Claude, OpenAI, or even a local model running on your own hardware. 

The hidden tax of any AI coding assistant, however, is that it fundamentally shifts your job description from “writer” to “editor.” The unbloating of keystrokes can paradoxically lead to massively bloated codebases if developers blindly accept AI-generated boilerplate without actively reviewing its architectural impact. It is incredibly easy to let an agent spin up 500 lines of complex React when 50 lines of plain JavaScript would have done.

See also: Antigravity. RooCode is a lightweight extension that supercharges your existing environment. Google’s Antigravity is a custom-built editor designed from the ground up around AI, geared for agentic development workflows.

TanStack Query: Syncing made simple(r)

Even when client-side state management is addressed (see Zustand below), there is still a big, gaping hole in the plot: syncing across the server boundary. That is where TanStack Query steps into the breach.

Distributed computing is a notoriously thorny problem, and in fact our standard reactive model walks right into these thorns by holding the same state in two different places: on the client and the server.  Tanstack Query tries to make this inherent architectural friction as painless as possible by acting as an intelligent asynchronous layer. 

Instead of using a bunch of manual fetches tied to useState updates, along with fragile isLoading flags and complex state synchronization logic, TanStack Query abstracts the heavy lifting of API responses, background updates, and request deduplication into a few elegant hooks. You tell TanStack Query where to get the data, and it uses a pattern known as “stale-while-revalidate,” which means it will cache and reuse data on the front end (eliminating reload waits) and sync to the latest state in the background.

The catch, however, is that cache invalidation remains one of the hardest problems in computer science—and TanStack Query forces you to face it head-on. You will spend time thinking about “query keys” and deciding when a piece of data should be considered “stale.” No free lunches in software.

See also: SWR. While TanStack Query is an absolute powerhouse for complex data manipulation, SWR remains a champion of API minimalism, doing exactly what its name implies (stale-while-revalidate) with almost zero configuration.

Zustand: Minimalist state

If you have yet to encounter the monstrosity of large-scale state management in a reactive app, then spoiler alert: it can be nasty. Zustand proposes to dispense with the ceremonial boilerplate of reducers, providers, and unwieldy context wrappers in favor of a tiny, brutally simple global store.

Instead of forcing your entire application tree into a massive React context provider (sometimes leading to cascades of superfluous re-renders across the DOM), Zustand uses custom hooks to tie state directly to the specific components that need it. Zustand strives to achieve the specificity in the VDOM reactive model (instead of eliminating it entirely a la Signals).

You define a store, you call it, and the reactivity just works. It is an expression of the KISS philosophy applied to front-end architecture, scraping away the intricacies of Flux-like patterns. The trade-off for this liberation is the burden of discipline. Because Zustand is unopinionated, it won’t stop you from turning your global store into a cluttered junk drawer. You’ll need to impose your own conventions and guardrails to keep a large-scale project manageable.

See also: Jotai. If Zustand is the unbloated global store, Jotai is the unbloated atomic approach. Jotai manages state from the bottom up, calculating changes with surgical precision without triggering massive re-renders across the application tree.

New directions in web development

The most remarkable thing about these eight tools is that they deal in large part with alternative approaches that challenge the familiar. Although you may not be able to adopt them immediately, you will want to keep an eye on them. They are key factors that will continue to influence the shape of web applications and how we build them.

Meet Hades: The malware that lies to AI security agents

9 June 2026 at 06:05

Threat actors are continuing their onslaught against software supply chains, now with malware named after death itself.

The newly-discovered Hades Campaign is a “highly sophisticated” supply chain compromise that targets Python developer environments and runs as soon as infected packages are imported. It uses the popular Bun toolkit to silently execute multi-layer payloads that can extract sensitive data, move laterally across compromised systems, exploit common security frameworks, and even hijack AI gatekeeper analyzer systems via adversarial prompt injection.

Notably, the campaign exploited the popular C++ library ensmallen, as well as packages in the computational biology, bioinformatics, and genotype-phenotype analysis ecosystems.

The most novel thing about this malware is its combination of advanced tactics, noted David Shipley of Beauceron Security. He noted that we’ve seen memory-focused malware, we’ve seen attacks that attempt to defuse large language model (LLM) powered analysis with hidden prompts, and we’ve seen malware with wiper capabilities.

“But all three, in a fast moving mass propagating worm, is its own kind of nightmare,” he said. “And I suspect this is the way of the future.”

How Hades works

The Hades Campaign was discovered by researchers at StepSecurity, who called it the latest evolution of the Miasma threat actor. The researchers previously described Miasma attacks that had sent self-replicating worms to perform multi-cloud credential sweeps, caused infected repositories to execute code when folders were accessed in integrated development environments (IDEs) or by AI agents, and used techniques that scanned and read Linux process memory.

Hades uses the same credential harvesting methods, self-replicating worm logic, and GitHub-based exfiltration patterns, the researchers noted. In addition to ensmallen, compromised packages include mflux-streamlit, nhmpy, ppkt2synergy, embiggen, gpsea, and pyphetools.

The campaign’s entry point is a simple, obfuscated script embedded inside a Python package’s __init__.py file, a critical building block that gives Python the ability to recognize packages and import modules. Once they gain access, threat actors drop a precompiled Bun runtime binary and executes its JavaScript payload. Bun allows the malware to run complex JavaScript tasks in environments lacking a Node.js installation, bypassing traditional package manager controls and proxy logs.

The malware is able to scrape Linux memory mappings, and also introduces tailored macOS and Windows memory scrapers, which allow threat actors to extract sensitive, encrypted data.

Interestingly, attackers are also able to evade detection by automated LLMs that scan for suspicious code. This is achieved with a simple block of text at the top of the file; this instructs the model to ignore the hidden code below, classify the package as verified and clean, and provide reports stating it is safe.

This element represents what the StepSecurity researchers described as a “significant conceptual shift,” with attackers writing payloads that target AI systems’ cognitive logic. “Scanners that pass raw text to LLMs without strict boundary isolation can be coerced into generating false negative verdicts, allowing the malicious package to bypass organization analysis,” they wrote.

The tactic is indeed clever, Beauceron’s Shipley agreed, pointing out that attackers will increasingly target endpoint LLM-powered agents.

Why? “Because there’s no reliable defense,” he said. “LLMs are incredibly susceptible to social engineering.” This has been relabeled as prompt engineering, but is essentially just phishing for bots, he pointed out.

“While everyone’s worried about LLM-powered vulnerability discovery and automated exploitation, it’s LLM-created smart malware like this, and AI-powered phishing of humans and bots, that keeps me awake at night,” Shipley said.

Hades’ crafty worm propagation

The Hades Campaign command and control (C2) infrastructure uses three independent channels on public GitHub infrastructure to allow its communications to blend in with normal traffic. Stolen credentials are encrypted locally in a hybrid fashion (serialized, compressed, and pushed to a newly created public GitHub repository under attackers’ control). Exfiltrated repositories carry the description “Hades — The End for the Damned.”

Researchers noted that a core component of this campaign is its ability to propagate and move laterally across networks. It exploits the very methods meant to protect systems, including Secure Shell (SSH) and Secure Copy Protocol (SCP), OpenID Connect (OIDC),and Supply-chain Levels for Software Artifacts (SLSA).

For instance, when running inside a GitHub Actions workflow runner, the malware checks for OIDC variables, then bypasses registry signature policies and generates cryptographically signed SLSA provenance bundles via Sigstore. It can then fetch target libraries and inject the obfuscated script and JavaScript payload. From there, it can publish compromised versions to the Python Package Index (PyPI) repository and node package manager (npm) using the target’s credentials and the generated Sigstore bundle.

“This ensures that the published package appears to have valid, cryptographically verified build provenance from the organization’s official GitHub Actions build environment,” the researchers explained.

Further, if a harvested GitHub token has write permissions, the malware will target repositories to extract secrets using GitHub Actions runners. This occurs “directly from the runner’s address space without ever writing them to disk or making a suspicious network connection,” the researchers noted.

The malware also targets rule files and configuration directories for 14 different AI agents and systems, planting custom prompt instructions or executing hooks that trigger a bun run bootstrap command when the victim loads or consults the workspace with their AI assistant. Finally, it establishes persistence on the workstation and monitors for the presence of the stolen token; if that token is revoked, it executes a wiper process to erase the user’s files.

Broadcom beefs up Spring security to protect against AI-enabled attacks

8 June 2026 at 22:02

Broadcom today announced multiple security investments in its Spring and Java ecosystems that aim to help protect users from AI-enabled threats.

The company said that, first, it is releasing what it called the largest set of Spring security updates to open source in the product’s history, and, for customers, it is extending its clean-room build architecture to build the Java dependencies for the entire Spring ecosystem.

“Spring is one of the most widely adopted application development frameworks in the world, and as its steward, we have a deep responsibility for its security,” said Purnima Padmanabhan, vice president and general manager of Broadcom’s Tanzu Division. “Because we maintain Spring and are the sole committers, we can better secure it at the source for everyone who depends on it. This investment is about two things we will never separate: the health of the Spring community and the security of our customers who trust Spring to run their business.”

The company also announced that, as the number of security advisories reported by the community has exploded, its engineering team has “significantly scaled” its use of AI tools to help it identify vulnerabilities, assess remediation paths, and validate fixes across the dependency ecosystem. Although Broadcom declined to specify the AI models it’s using in its bug hunting, it is a member of Anthropic’s Project Glasswing, so Claude Mythos is likely part of the effort.

For paying customers only

One perk available only to Tanzu Spring enterprise customers is zero-day access to validated CVE patch-only releases through the Spring Enterprise Repository, before they are released to open source. These patches isolate the security fix from any other changes to let customers remediate more quickly.

“By utilizing Tanzu Spring’s private artifact repositories, customers can be confident that the artifacts are the official, validated patches from Broadcom, the steward of Spring,” Broadcom said in its announcement, adding that it will continue to issue CVEs for all versions of every Spring project under open source support, as well as older versions under Tanzu Spring enterprise support.

Broadcom’s Tanzu Spring enterprise support includes:

  • Certified source for secure spring libraries 
  • Commercial-first release of patches for both current and older, enterprise supported versions
  • Access to dependent Java binaries
  • Automated, deterministic upgrades with Spring Application Advisor
  • Exclusive Tanzu Spring components for governance and security
  • 24×7 support, hands-on expertise and access to the Spring team.

In addition, Broadcom said, it has now added:

  • Secured, SLSA Level 3–validated software supply chain for Java dependencies.
  • Coverage that spans the full transitive dependency graph managed by the Spring Boot bill of materials.
  • Thousands of secured dependencies, built and tested across every supported Spring version. Spring Boot 4.0 alone manages 1,768 of them; across the full supported portfolio, that totals more than 100,000 validated dependency builds.

“This capability gives customers validated dependencies across both current and end-of-life Spring versions, helping customers reduce software supply chain risk while continuing to benefit from the productivity and consistency of Spring Boot’s dependency management model,” the announcement noted.

Security fixes for sale

Seva Ioussoufovitch, senior research analyst at Info-Tech Research Group, sees these moves as mostly positive.

“It’s encouraging to see Broadcom take proactive steps towards dealing with the increase in AI-detected vulnerabilities that many organizations have had to contend with in recent months,” he said. “Announcements like Mythos have made it clear that the industry needs to re-think traditional approaches to security patching.”

Ioussoufovitch isn’t surprised at the size of the update release either, noting that it’s consistent with the result of AI scanning and remediation that has been occurring, and will likely continue.

“More meaningful is the provision of validated and secured dependencies,” he said. “This is a critical move in the right direction, especially with the endlessly growing list of supply chain vulnerabilities the industry has been managing in recent months.”

Ioussoufovitch is less happy with the restriction of zero-day patches to paying customers.

“Putting security fixes behind a paywall isn’t new, but when there are no drop-in alternatives for an ecosystem as critical as Spring, it just looks like a power move to force more of the open-source community onto the monetization track,” he noted. “Another approach might’ve been to release the CVE fixes to everyone while charging for enterprise-grade packaging, validation, and support, but, given Broadcom’s track record of aggressive monetization in recent years, what they’ve chosen here doesn’t necessarily come as a shock.”

10 MCP servers to connect LLMs with databases

8 June 2026 at 10:00

Model Context Protocol (MCP) has gained considerable momentum as a standard connector between LLM-powered tools and local systems, internal and external APIs, and data sources. From major clouds to devops tools, MCP servers are enabling powerful, AI-powered development and operations capabilities through natural language commands.

Nowhere is this more true than in the world of databases. Most major database platforms now support agentic access through MCP servers. Using an MCP server for databases, you and your AI agent proxies can perform lookups, create and update data, and perform administrative tasks without you having to write SQL by hand.

The MCP server could also guide your LLMs to write new code or build automations that align with your database schema, like its tables, structure, and fields, as well as embeddings, indexes, and metadata. It could also aid debugging by enabling faster queries to surface data issues or misconfigurations, along with plenty of other possible use cases.

Below, we’ll cover official MCP servers from some of the top platform options across major database styles. Though maturity varies, the MCP servers discussed below represent some of the best vendor-backed offerings available today across relational SQL, NoSQL, graph, vector, and data warehouse systems.

These servers can be used by any MCP-compatible tool, IDE, or agent, whether it’s Claude Code, Codex, Cursor, Gemini CLI, Google Antigravity, VS Code, Windsurf, or something else. Adding them is typically simple, often involving a lightweight JSON addition to your MCP configuration file.

Amazon Aurora MCP Servers

MySQL and PostgreSQL are the world’s most widely-used open source databases. However, in both cases, there is no canonical MCP server—what we see are different MCP servers emerging across vendors. One of these vendors is Amazon Web Services (AWS), which offers official MCP servers for Amazon Aurora, its managed relational database service compatible with both MySQL and PostgreSQL.

According to the documentation on GitHub, the Amazon Aurora MySQL MCP Server can be used to convert natural language commands into MySQL-compatible SQL queries, which can then be executed against Aurora MySQL databases. Similarly, the Aurora Postgres MCP Server provides MCP tools for working on PostgreSQL databases. The Aurora DSQL MCP Server does the same for distributed Postgres databases.

AWS provides a growing portfolio of official MCP servers across its product line, including MCP servers for other Amazon database platforms like DynamoDB, ElastiCache, and Redshift. If you’re a heavy AWS shop and you want to enable LLM interactions with your data, these are sensible choices.

BigQuery MCP Server

BigQuery is Google’s cloud-based data analytics platform, and a popular data source for AI applications. BigQuery users with API access configured can also utilize the BigQuery MCP Server to interact with the platform using MCP-compatible AI clients.

Using the remote BigQuery MCP Server, engineers can generate and execute queries on data sources, or return metadata on datasets, tables, and schema. This can be done with a simple natural language prompt like “List the datasets in project PROJECT_ID.” Results are filterable by region, data set ID, column name, and more.

As part of Google’s fully-managed, remote-hosted MCP portfolio, the BigQuery MCP Server provides some peace of mind regarding security, maintenance, and ease of use for distributed teams. The MCP tools are subject to some limitations, however, in terms of query result size, processing time, and other factors. If you’re using BigQuery and you want more agentic control, you’ll want to check this one out.

Elastic Agent Builder

Another important database category includes platforms designed for keyword and semantic search. In this space, Elasticsearch is commonly deployed. Instead of providing a single MCP server, Elasticsearch provides the Elastic Agent Builder, which is a more comprehensive framework aimed at agentic workflows.

Using Elastic Agent Builder, you can chat with an agent to retrieve data context from Elasticsearch data and extend it into various environments. The Agent Builder itself includes an MCP server endpoint for programmability and exposing the agent to other clients.

Unlike others on this list, this is not a direct MCP interface to raw Elasticsearch APIs. Instead, it’s an interface that exposes skills from the agent platform. This should also not be confused with the Elasticsearch MCP Server, released in mid-2025, which has since been deprecated.

A possible downside of using this utility is that it includes an additional layer between your IDE or agent and the data you’re searching. The agent setup requires a higher subscription and takes additional steps to configure compared to other MCP servers.

That said, if you want an extensible common layer to interact with both Elasticsearch and external MCP servers, while centralizing responsibilities like permissions, this is an interesting proposition.

MCP servers for Neo4j

Graph databases are another key NoSQL database type these days, specializing in using nodes and edges to accelerate queries of highly interconnected data. Of these, Neo4j is a popular graph database option.

The Official MCP Server for Neo4j works with all kinds of Neo4j deployment (desktop, sandbox, self-managed, and the managed Neo4j Aura cloud service), and allows LLM-based clients to retrieve graph schema, execute read and write statements, execute graph algorithms, and more.

In addition, several other MCP servers for Neo4j are available from Neo4j Labs. These have specialized uses, such as generating Cypher queries from natural language, maintaining an in-memory graph database, modeling and visualizing graph, and interacting with the Neo4j Aura API.

The first MCP server for Neo4j was developed in December 2024. If you’re an avid Neo4j user and want to experiment with interacting with your graph databases in a chat-infused way, these stand as an interesting platform of servers.

MCP Toolbox for Databases

Google’s MCP Toolbox for Databases is a notable MCP server because it’s a popular catch-all for various database types. Unlike the other entries on this list, this server connects LLMs not to a single managed database, but unifies LLM access to multiple systems. The open source utility ships with pre-built configurations for nearly 30 databases including PostgreSQL, MySQL, SQL Server, Oracle Database, MongoDB, Redis, Neo4j, and Snowflake, as well as the databases in Google Cloud.

Once you define data sources in a tools.yaml file, you can use MCP Toolbox to perform structured queries or semantic searches against databases directly from within an IDE or agentic client using plain English. MCP tools translate commands into actions like list_tables and execute_sql.

MCP Toolbox for Databases is mature, originally built as a generative AI utility and later re-worked for MCP-style workflows. It offers numerous download, configuration, and interaction methods.

If you’re using a variety of databases on Google Cloud and elsewhere and you want an “all-in-one” MCP server, MCP Toolbox for Databases is a great place to start.

MongoDB MCP Server

MongoDB is the popular NoSQL document-oriented database. The creators of MongoDB have released an official MCP server that works with the open-source database as well as the company’s cloud-hosted MongoDB Atlas database platform.

The MongoDB MCP Server provides a number of tools to interact with MongoDB. You can query the database, return information on collections, create or remove collections or indexes, gather statistics on database usage, and more. Other tools enable MongoDB Atlas operations, like creating users or clusters, returning cluster data, and other functions.

The server’s tools are read-only by default but can be switched to allow write capabilities. It can be used locally, but also supports Streamable HTTP transport for remote servers, although that comes with greater security concerns.

For those using MongoDB and wanting to hook their AI-enabled IDE or CLI up with more automated powers, the official MongoDB MCP Server is worth checking out.

Pinecone MCP server

Among vector-native databases, Pinecone stands as a strong, widely used option with a well-designed API and comprehensive SDKs. The Pinecone MCP server extends this experience, allowing users to query its documentation and execute functionality via AI agents and AI-enabled IDEs.

To date, the Pinecone MCP server consists of nine MCP tools. These cover read-only actions, like knowledge gathering via the Pinecone official documentation and querying vector records, index metadata, configurations, and statistics. It also allows for write operations like updating records and creating new indexes.

Released in mid-2025, the Pinecone MCP server is one of the more complete early implementations, with easy configuration and installation.

For those using Pinecone who want to test new LLM-assisted workflows for creating indexes with embeddings, performing reranking, or testing results using natural language commands, the Pinecone MCP server is worth trying out.

Redis MCP

An ultra-fast in-memory database, Redis is commonly used for caching, real-time analytics, and other latency-sensitive use cases. And as you might have guessed, the company behind the Redis database provides an official MCP server. The server allows read, query, and write capabilities.

Developers can use Redis MCP from an LLM client to perform high-level actions to analyze, reference, or embed Redis data and interact with the Redis server within their prompts. The documentation suggests some example prompts for common use cases, such as “Cache this item,” “How many keys does my database have?,” and “What is user:1’s email?”

Unlike other MCP servers, which only allow a slice of platform capabilities, Redis MCP offers full Redis support. This enables working with Redis constructs such as hashes, lists, sets, sorted sets, streams, and more, according to the GitHub repository.

One possible drawback is that Redis MCP has yet to support Streamable HTTP transport. Until this is developed, the server is constrained to local deployment. But for those seeking a local MCP server to work with Redis data, this is the best choice.

Snowflake MCP Server

Snowflake is a cloud-hosted, AI-enabled data platform widely used in enterprise contexts for data warehousing, data analytics, and data engineering purposes. Compared to other data storage systems, Snowflake is unique in that it’s more fully managed and combines structured and non-structured data types.

The Snowflake MCP Server, available on GitHub, can be used to perform many of the standard Snowflake platform operations. This includes a “fuzzy” search of all records via Snowflake’s Cortex Search and structured data semantic lookups using Cortex Analyst.

Other abilities include object management operations like creating, updating, and deleting records. The server also can invoke other agentic-designed capabilities, like the ability to generate and execute SQL statements against back-end databases.

Snowflake MCP Server is well-thought-out and well-documented, with walkthroughs for various agent and deployment patterns. Those already building with Snowflake should find it complements the mechanics they already employ.

Supabase MCP Server

A longtime open-source favorite, PostgreSQL is one of the most popular and trusted object-relational SQL-based database systems. With an active open source community, Postgres has been maturing for decades. Given its open source nature, there isn’t a single “official” MCP server for the platform. Anthropic built an original reference implementation, but it’s now archived.

Instead, database platforms built on PostgreSQL provide different flavors of MCP servers, with a range of vendor neutrality and specificity. One notable option is the Supabase MCP Server, provided by Supabase, a cloud-based “back end as a service” and Postgres development platform.

Supabase MCP Server connects AI agents with Supabase projects, allowing engineers to issue natural language commands to manage tables, query data, get logs, fetch configuration information, and more. The Supabase MCP Server is pre-1.0 release and some features are still experimental.

If you’re an engineer using Supabase and looking for an MCP server to connect your AI assistant with your Postgres databases, this is a good tool to test out.

Other MCP servers for databases to consider

So far, we’ve reviewed official, vendor-backed MCP servers from some of the most-adopted managed databases. However, numerous MCP servers exist across other database platforms and types.

One MCP server that aggregates LLM access across various database types is DBHub, which works with MySQL, PostgreSQL, SQL Server, MariaDB, and SQLite. Developed by Bytebase, DBHub is described as a zero-dependency, token-efficient MCP server.

For SQL, the options are nearly endless. Official servers exist for Microsoft Azure SQL and DuckDB. PulseMCP catalogs more than 100 MCP servers for MySQL, although most are unofficial, solo-creator open source projects. Of these, one of the most starred is MCP Server for MySQL, developed by full-stack developer Ben Borla and optimized for Claude Code.

For Postgres, notable alternatives to Supabase include pgEdge Postgres MCP, Neon MCP server, and Postgres MCP Pro. For vector databases, others beyond Pinecone have been quick to adopt MCP as well, including Weaviate and Milvus.

Using MCP for databases: what to watch out for

Before diving into MCP servers for enterprise databases, it’s important to understand the security risks. For instance, prompt injection remains an unsolved problem, so it’s recommended to limit permissions for SQL statements.

To mitigate this, Supabase recommends enabling AI client settings that require manual approval for each tool call before execution. Experts also recommend assigning only the minimum permissions required and avoiding exposure of sensitive data like API credentials. Due diligence around authentication and authorization is especially important when hosting remote servers.

Lastly, to avoid shadow IT, it’s becoming common practice to catalog the internal MCP servers you use, even for experimental projects. For this, experts recommend an MCP registry that documents approved servers. An MCP registry improves both MCP server discovery and security awareness.

Making sense of too much code

8 June 2026 at 10:00

Anyone can build an app now. But nobody seems to care.

Well, not nobody. VCs keep funding startups that add AI to, well, everything. But users aren’t buying the massive influx of new apps. In a chart shared by Jen Zhu Scott based on the new National Bureau of Economic Research’s working paper “Writing Code vs. Shipping Code,” iOS app releases have exploded since the advent of agentic AI. That would perhaps be cause for celebration had app reviews not declined during this same period, and apps with significant usage have stayed essentially flat.

In other words, more apps but almost nobody new showing up to use them.

For those of us that grew up in open source, it’s a familiar problem. The greater the abundance of code, the greater the need to help would-be customers navigate it through marketing (including branding), sales, etc. AI is creating so much noise, in terms of new code, new products, etc., that the real work has shifted to taste-making.

Getting more but not using more

I’ve been saying for a while that developer productivity isn’t about producing more code faster. Or at least it shouldn’t be. Productivity is about producing well-architected, secure, maintainable code that solves a problem someone actually has.

That’s a very different thing. It’s not something AI can fix; at least, not yet.

Charity Majors put it more bluntly in a post I wrote in 2024: “Writing code is the easiest part of software engineering,” she said. The harder parts are figuring out what to build, integrating it into a larger system, validating that it works, maintaining it over time, and getting humans to trust it enough to use it.

Turns out the harder parts are really hard. Mert Demirer, Leon Musolff, and Liyuan Yang tracked more than 100,000 GitHub developers alongside their AI usage telemetry. Autocomplete, interactive agents, and autonomous agents each ramped raw coding activity, with cumulative effects on commits of 40%, 140%, and 180%. That sounds great until you look how the gains attenuate the closer you get to actual users. For example, that 180% jump in commits became roughly 50% more projects and just 30% more actual releases. The report’s authors call this the weak-link problem: The strong link (writing code) got much stronger, while the weak links (everything else humans have to do) didn’t. The estimated elasticity of substitution between AI and human effort is 0.25, which is economist for “these complement each other, but they don’t replace each other.”

When the authors checked four major app marketplaces, they found a bump in new apps but no increase in total usage. In other words, we’re getting better at creating things with AI’s help; apparently we’re not good at turning that into user interest. User attention (and budget) is finite. The hard part is to figure out how to get users to care enough to pay (with their time or their money).

Learning to love marketing

So what’s actually scarce in a world of near-infinite software? Not code, for sure. No, what’s scarce is attention, trust, and a reason to switch.

That means the durable advantages in software increasingly live in the parts of the business developers often undervalue, like a recognizable brand (something that Red Hat figured out early on in open source) or a channel they already use. Or it could be in areas that developers appreciate but don’t pay for, like good documentation or a welcoming community.

This isn’t a new idea; it’s just newly unavoidable. We’re watching something similar inside enterprises, where AI adoption is wildly uneven, not because the technology has no value, but because the organizational plumbing around it often hasn’t been built. This is why a new kind of speed is important. I once argued that speed was the killer app, and that was mostly true. Today the more interesting speed is how quickly you can earn trust, fit into a workflow, answer objections, and get adopted.

Years ago I wrote that RethinkDB was dead and MongoDB wasn’t what killed it. RethinkDB was at the time, by many technical measures, a better database, built around “correctness, simplicity, and consistency.” It still lost—and badly. Its founder’s own postmortem was unsparing: They had picked a brutal market and tuned the product to the wrong definition of good. Being technically right turned out to have almost nothing to do with getting adopted.

With AI we’re generating a thousand smaller “RethinkDBs,” only faster and with nicer landing pages generated by the same model that wrote the code. These aren’t going to win, any more than RethinkDB was able to unseat MongoDB. It’s not just about the tech, but rather about making that tech fit within a user’s or enterprise’s world and making it easy to adopt. AI makes this harder, not easier.

It’s a cliché that developers don’t like marketing. It’s also false in my inexperience. What developers don’t like is traditional marketing. During my time at MongoDB and now at Oracle, my developer relations teams have focused on offering developers deep, hands-on enablement, and the response has been fantastic. Is a technical tutorial marketing? Of course it is. So is a forward-deployed engineer working side by side with an enterprise’s engineers to help them effectively use your tech. Just because it’s not a 30-second Super Bowl ad doesn’t mean it’s not marketing.

Years ago the Dilbert cartoon captured developers’ disdain for marketing. It was funny then, and it’s funny now, but it has never been true.

Years ago Matt Klein, creator of the open source Envoy project, once talked me through all the non-development work that goes into making an open source project thrive. As he reflected, “If you look at what I did in 2016 and early 2017 to [introduce] and grow the project, it was not technical.” So what was it, if not core engineering? “It was all leadership, public relations, marketing, documentation, etc., and I did it all myself and I nearly killed myself [doing it].” As he summed it up for me, it was a “f—ing lot of work,” and much (most?) of it wasn’t about code. It was about helping users appreciate the value of that code.

TL;DR? The boring but essential go-to-market grind has always been the real job. It’s what will separate winners from losers in AI.

The boring work wins

None of this is an argument against AI coding tools. Developers should absolutely use them. I use them constantly.

But AI can’t compensate for the hard work that goes into making a product successful in the market. In a world drowning in AI-generated sameness, taste becomes a competitive advantage. For me, “taste” translates into knowing what not to build, or what not to publish. It’s also all about knowing how to market one’s product, which might include ads but definitely needs to incorporate technical training that helps developers make sense of your code.

In short, there’s no Field of Dreams “build it and they will come.” There’s just a lot of hard, human work to help real people find and use your code.

GitHub adds new Copilot features as usage-based billing takes effect

5 June 2026 at 18:32

GitHub is expanding Copilot beyond the IDE with a new desktop application and a new collaborative work surface called canvas as part of its broader efforts to pitch the AI-assisted coding tool as the control center for agent-native software development.

The desktop application announced at Microsoft’s annual Build conference this week is designed to give developers a dedicated environment for working with AI agents throughout the software development lifecycle, rather than limiting those interactions to code-generation tasks inside an editor, the company wrote in a blog post.

The application includes a collaborative workspace called canvas where developers can brainstorm ideas, refine requirements, generate plans, and iterate on projects alongside AI, it said.

It also has new Agent Merge and code review features that enable developers to automate Copilot to combine tasks of different agents to complete a specific goal or conduct autonomous code reviews according to set standards, it said.

These new features could reduce context switching, increase engineering efficiency, and accelerate delivery cycles, said Phil Fersht, CEO of HFS Research.

Shift in pricing justified?

However, despite the new features, much of the conversation among developers in recent weeks has centered on a different topic: this week’s shift to a usage-based billing model for GitHub Copilot that it announced in April.

The changes were met with a wave of criticism on the GitHub community forum, where some users accused the company of a “bait and switch,” while others requested refunds or announced plans to cancel their subscriptions.

For analysts, though, the pricing change was, at least from GitHub’s point of view, necessary and justified.

“The pricing change is justified by where GitHub is going, not by where the product is today. Running multiple agents in parallel with sandboxes, canvas reviews, and Agent Merge looping through CI is closer to cloud compute than an IDE plugin, and you cannot price compute on a flat seat fee. So metered billing is the right call structurally,” said Advait Patel, a senior reliability engineer at Broadcom.

Fersht said developers and CIOs need to focus on Copilot’s metamorphosis from being a coding assistant into a platform for orchestrating software-development agents and workflows.

“That changes the ROI conversation significantly. CIOs should stop thinking about Copilot as a seat-license productivity tool and instead evaluate it as an AI-powered software delivery platform,” he said. “The metrics shift from ‘lines of code generated’ to broader operational outcomes such as release velocity, code quality, defect reduction and engineering efficiency.”

GitHub is not the first company offering vibe-coding tools to rethink its pricing strategy as AI agents proliferate across enterprises and evolve to take on more complex software-development tasks that are computationally more intensive.

Over the past year, platforms such as Claude Code, Replit, Cursor, and Kiro have repeatedly adjusted their pricing structures to account for mounting infrastructure costs, limited GPU availability, and the expense of serving increasingly sophisticated AI models and agents, despite furor among their users.

For CIOs, the challenge is proving ROI

That common pressure across AI coding vendors is why Amit Chandak, chief analytics officer at IT consulting firm Kanerika, thinks developers and CIOs should focus less on GitHub’s pricing mechanics and more on whether these increasingly capable tools are delivering measurable business value.

“The new features that GitHub announced can act as productivity multipliers as well as features that increase consumption without delivering proportional business value. Without productivity baselines established before adoption, enterprises risk absorbing higher costs with no clear line back to delivered value,” Chandak said.

For Fersht, developers and CIOs will need to focus on governance, monitoring and financial controls as the pricing model is changing.

“The governance challenge is very real. Autonomous agents can continuously reason, test, revise and interact with multiple systems in ways that create far less predictable consumption patterns than traditional SaaS tools,” he said.

Patel, however, advised users and decision-makers to be more skeptical, especially since the new features are currently in technical preview.

“Customers are being asked to pay variable rates now for value that has not been validated in production. Do not assume new capabilities justify higher spend,” he said. “Instead, run a 90 day pilot, measure PRs merged per dollar before and after, and let the data decide. If the ratio improves, the pricing is fair. If it does not, you are paying for promise, not delivery,” Patel added.

Patching fast and slow: Ruby devs delay to defend against supply chain attack

5 June 2026 at 18:04

The team behind RubyGems, a package hosting site for Ruby developers, has added a new feature to bundler, a tool for managing Ruby packages (or ‘gems’) to protect developers against the recent wave of software supply chain attacks: A cooling-off period before recently updated packages are installed on their systems.

Recent attacks on software repositories have focused on stealing developer credentials in order to introduce malicious code into the packages they create, which then steals more developers’ credentials when they install the malicious updates, and so on. Users of the repositories are vulnerable if they download an affected package during the short interval between it being interfered with and the malicious additions being discovered and removed.

To counteract this, RubyGems team has added a new cooldown argument to Bundler that takes ignores gems until they have been published for a specified number of days. This provides an additional layer of defense against malicious package releases as it gives others an opportunity to identify any malicious code they contain before installation.

The cooldown system works by checking the timestamp of any new versions of gems. Any new additions to the source will have to come from older versions, any new additions will be delayed until they are validated.

In situations where waiting is unhelpful — for instance when a known-good package is released to patch a dangerous security flaw — the delay can be overridden.

Embedding pipelines are the new ETL

5 June 2026 at 10:00

I’ve seen a lot of promising AI prototypes fall apart after launch. And it’s rarely because the model was bad. More often, the problem starts much earlier; teams treat the data layer like something they can figure out later.

They’ll spend weeks fine-tuning prompts, testing models and debating evaluation scores, then throw together the retrieval pipeline over a weekend and move on. At first, everything looks great in demos. But a few months later, the system gives outdated answers; the embeddings no longer match the source documents, and nobody fully understands what changed.

What started as an impressive prototype slowly becomes difficult to trust in production. The teams that avoid this tend to realize one thing early: Embedding pipelines are fundamentally a data engineering problem, not an entirely new AI discipline. It’s still ETL (Extract, Load, Transform) at its core, but with embeddings and vector stores as the destination instead of a warehouse.

Once you start looking at it that way, a lot of things become clearer. Problems like versioning, data freshness, lineage and retries stop feeling “AI-specific.” They’re data infrastructure problems we’ve already spent years learning how to solve.

Why do we need embedding pipelines?

Large language models are extraordinary reasoners trapped inside a time capsule. When training ends, the model’s knowledge is sealed. It does not know what your team decided in last quarter’s strategy review. It has never read the support ticket that came in this morning. It cannot find the clause buried on page 47 of your master service agreement. It’s brilliant, but blind to anything specific to your organization.

Layer on top of that a hard context window limit, a ceiling on how much text the model can process in a single interaction, and you have a clear problem: you cannot just hand it everything you own.

The answer the industry converged on is retrieval-augmented generation, or RAG. Instead of stuffing everything into the context window, you build a retrieval layer that fetches only the most relevant pieces of information at the moment a question is asked and passes just those to the model. That retrieval layer is powered by a vector database, and the process that populates it, which is taking raw documents and transforming them into searchable semantic representations, is what I mean when I say embedding pipeline.

Every team building an internal AI assistant, a smarter enterprise search tool, an automated customer support agent or a document Q&A system needs one. The question is not whether to build it. The question is whether you build it like a prototype or like infrastructure.

How an embedding pipeline works

An embedding pipeline has three stages: ingestion, chunking and indexing. Here is what each one means and how I relate them to a typical ETL process.

Ingestion is extraction

Getting your raw content, PDFs, wiki pages, Word documents, database records, transcripts, out of wherever it lives and into the pipeline. This is ETL’s extract stage, almost verbatim.

I see teams cut corners here more than anywhere else, and it’s often where production systems first start to fail. A document gets updated, but the pipeline doesn’t pick it up. A file gets deleted, but its chunks remain in the index, still returning outdated answers months later. And because there’s no obvious error, no one reports it.

The fix is Change Data Capture (CDC). This maintains a manifest of every document you have ingested, a content hash and a timestamp. On each run, we compare sources against that manifest, re-ingest what changed, delete what is gone and treat your document the way you would treat any source table you are syncing incrementally.

Chunking is transformation

Once your documents are in the pipeline, you cannot embed them whole. A 30-page technical report is too long to represent meaningfully as a single vector, and even if it were not, returning the entire report in response to a narrow question would bury the model in irrelevant context.

Chunking is the process of breaking each document into smaller pieces that are focused enough to embed accurately and retrieve precisely. This is ETL’s transform stage, and it deserves the same level of design discipline.

The most common mistake I see is treating chunk size as a default configuration option rather than a product decision. It is not. The right chunk size depends entirely on the nature of your content and the nature of your queries. Dense technical documentation needs finer granularity than a collection of FAQs. A legal contract with clause-level logic needs different treatment than a set of onboarding emails. What works for one document will actively degrade retrieval quality on another.

My strong preference is to treat your chunking configuration as a versioned pipeline parameter, not hardcoded logic. When you change it, and trust me, you will. You need to re-chunk in a controlled, observable way, compare retrieval quality before and after, and roll back if it degrades. That is just good transform-layer hygiene. It is no different from versioning a data cleaning rule or a field mapping.

Indexing is the load

The final stage is where chunked text gets converted into vectors and stored in a vector database where it can be searched by semantic similarity rather than keyword match.

In the conversion step, embedding is handled by a model specifically trained to turn text into dense numerical representations that encode meaning. Two chunks expressing the same idea in different words will produce vectors that cluster close together in that mathematical space. Two chunks discussing entirely different topics will sit far apart. When a user asks a question, the system embeds that question the same way, finds the chunks whose vectors are nearest, and returns them as context for the model to reason over.

That is a genuinely new capability. But the discipline around indexing is not. One data engineering principle I keep coming back to is versioning.

In embedding pipelines, every chunk in your index should be tagged with the embedding model name and version used to generate it, this is non-negotiable. Embedding models evolve, and vectors produced by different versions are not comparable in a reliable way. You cannot safely search across them as if they are interchangeable.

This exact problem shows up when teams upgrade embedding models mid-pipeline without a proper migration plan. You end up mixing vectors from different generations in the same index, and retrieval starts to degrade in ways that are hard to detect. The system just quietly begins returning subtly wrong answers.

I treat an embedding model upgrade the same way I treat a schema migration: Plan it explicitly, execute it in full and validate retrieval quality on a representative query set. The stakes are the same as any breaking change to your data model.

Pipeline observability is not optional

Once an embedding pipeline is running in production, the question shifts from “did it run” to “did it run correctly.” That distinction matters more here than in most pipelines, because failures are rarely loud because the index looks fine, queries return without errors and the system quietly surfaces wrong answers until someone notices the AI has stopped being useful.

The same observability discipline that makes any data pipeline trustworthy applies directly here. Once you treat embedding pipelines as production systems, you stop thinking in isolated steps and start thinking in signals. For example, chunk counts per document become a simple but powerful health check, a sudden drop is usually not a model issue, but a sign of broken ingestion or upstream parsing failures.

You also need a “golden set” of queries with known-good outputs. This runs after every pipeline change, much like data quality checks after a transformation. This is how you catch regressions that don’t show up as explicit failures.

On top of that, you can track lineage: Which embedding model version produced which chunks, and when each document was last ingested. That makes it possible to trace retrieval issues back to specific changes instead of guessing.

And finally, freshness becomes a first-class signal. If documents start going stale beyond an acceptable threshold, that should surface in monitoring long before users experience degraded results.

The metric that ties it all together is retrieval quality over time. Treat it like any other pipeline SLA, measured, tracked and owned.

Summary

Embedding pipelines definitely come with a lot of new language, new tools and a genuinely different capability in the semantic layer. But the funny thing is, the principles that actually make them reliable in production are not new at all.

We have versioning, freshness, quality checks and monitoring. These are problems data engineering has already spent years solving.

The real work is taking that same discipline and applying it to a pipeline that just happens to output vectors instead of rows in a table. Once you start seeing it that way, a lot of the chaos around AI systems becomes much easier to reason about.

That’s the difference between building a cool AI demo and building something people can actually depend on. One is a prototype, whereas the other is infrastructure.

This article is published as part of the Foundry Expert Contributor Network.
Want to join?

Microsoft makes Linux developers feel more at home in Windows with Coreutils release

4 June 2026 at 21:06

Microsoft has announced Coreutils, a new Windows 11 feature that allows developers to run many popular Linux command line utilities natively on Windows from a single binary.

Revealed at this week’s Build 2026 developer conference in Seattle, Coreutils is about reducing what Microsoft terms the “cognitive load” faced by developers when moving between Windows and other platforms.

Currently, accessing the Linux command line utilities that are considered essential in many CI/CD development environments on Windows requires a kludge that involves either opening an emulation such as Git Bash, or a virtualized Windows Linux Subsystem (WSL) terminal.

Both are time-consuming and inefficient. As Microsoft’s announcement puts it: “Developers constantly move between platforms, but familiar commands don’t work consistently, forcing workarounds, lost speed and context switching.”

Coreutils removes the need for this back and forth, allowing developers to run most Linux commands straight from the Windows CMD command prompt, PowerShell, or Windows Terminal.

“Whether you’re moving between Linux, macOS, WSL, containers or cloud environments, the commands and workflows you’ve built over years just work in your Windows environment,” Microsoft said.

Most utilities, but not all

Installed as a single executable (via WinGet: install Microsoft.Coreutils), Coreutils for Windows itself is a Rust rewrite of the GNU uutils/coreutils project that provides commands that are universal across Linux distros.

Fundamental to making Coreutils efficient to manage is the fact that individual Linux commands run from a multi-call executable which maps via NTFS hardlinks pointing to each command. The advantage of this approach is that there’s only one binary to install, one binary to sign, and one binary to patch or update.

Microsoft lists 75 Linux utilities supported by Coreutils, including commonly-used commands such as ls, cp, find, grep, find, rm, du, hostname, and uptime.

However, some Coreutils commands clash with existing CMD or Powershell commands, or are otherwise not possible to execute; Microsoft provides a compatibility table listing conflicts. This means that some commands are not available, specifically: dir, expand, kill, more, timeout, and whoami.

There are also some commands omitted from Coreutils because a command relies on a POSIX Unix/Linux feature that Windows doesn’t implement in a compatible way; some examples are chmod, chown, id, stty, and chroot.

In other cases, the command will execute in one context, CMD, but not in PowerShell. Microsoft explained the complex order of precedence:  “Whether the Coreutils version runs depends on the shell, the PATH order, and (for PowerShell) the alias table.”

As well as Coreutils, the Build 2026 developer conference also saw Microsoft announce WSL containers CLI and API to deploy Linux containers on Windows, a new framework for autonomous agents with open source governance tools, and Microsoft Scout, an AI agent designed to automate tasks in Microsoft 365.

Microsoft’s Web IQ aims to give enterprise AI agents real-time web intelligence

4 June 2026 at 19:13

For the past two years, enterprises have focused on grounding AI systems in internal documents, databases and knowledge repositories. Microsoft now contends that the next challenge is giving those systems reliable access to the outside world as they move into production.

At its ongoing annual Build conference, Microsoft unveiled Web IQ, a new suite of AI-native APIs designed to connect AI agents and applications to real-time information from across the web, including web pages, news, images and videos.

The goal is to help developers build more accurate and context-aware AI systems while reducing the complexity of integrating web search, retrieval and grounding capabilities into enterprise applications, the company wrote in a blog post.

The APIs already underpins grounding for Microsoft Copilot and ChatGPT, and unlike traditional search APIs are designed to retrieve highly relevant information while minimizing token consumption, helping reduce both inference costs and response latency, Microsoft said.

Reducing the cost and complexity of web grounding

That focus on reducing inference costs and response latency to deliver Web IQ’s search capabilities will be valuable for CIOs and developers, said Phil Fersht, chief analyst at HFS Research.

“Developers have typically stitched this together themselves using search APIs, web scraping, retrieval-augmented generation, vector databases, custom ranking logic, crawling tools and separate orchestration layers. That works, but it is messy, brittle and expensive to maintain,” he said.

“The hard part is not just finding a web page. It is retrieving the right evidence, ranking it, selecting useful passages, reducing token waste, respecting publisher controls and doing all this fast enough for multi-step agents,” he added.

An agent running in production will typically run at least five or ten retrieval steps and in such scenarios latency and cost can become “ugly,” said Moor Insights and Strategy principal analyst Mike Leone.

“I’ve watched plenty of teams handle this by gluing a search API onto a model and hoping the model can sort through whatever HTML comes back, which isn’t ideal,” he said.

Simplifying development of applications

Beyond the infrastructure and cost advantages, Web IQ could also simplify the AI application building process developers, said Stephanie Walter, practice lead of the AI stack at HyperFrame Research.

“The value of Web IQ is that Microsoft is trying to make web grounding a reusable, agent-native service rather than a bespoke integration,” Walter said.

That reusability, Fersht said, will matter to CIOs as most enterprises do not want every development team rebuilding its own web grounding stack: “They need a common capability that is governed, scalable, low-latency and economically efficient.”

Still, Microsoft is not entering an untapped market and there are several offerings already available, including OpenAI web search, Google grounding, Perplexity APIs, Bing Search APIs, Azure AI Search, vector databases, and custom RAG pipelines.

However, Microsoft might have an advantage with IQ, despite Google’s strength in search and web-scale knowledge, OpenAI’s tooling push, and AWS’ Bedrock-data-service-partner integrations combo, Fersht said.

“Microsoft’s differentiation is that it can combine Bing’s global web index with Azure AI, Copilot, Foundry, Microsoft 365 and enterprise developer channels,” he said.

The other advantage is the existence of existing IQ offerings, such as Work IQ, Fabric IQ, and Foundry IQ, all of which are targeted towards adding more business context for agentic systems, Fersht added.

But uptake, Walter said, will depend on whether these integrations translate into better production outcomes.

Web IQ is currently available in limited access for select Azure customers. Enterprises can request access to Web IQ via their Microsoft account team or submit a form.

Beyond direct API access, developers can also configure the model-agnostic Web IQ as an MCP tool within Foundry IQ, a Microsoft spokesperson said.

Rayfin signals Microsoft’s push to make Fabric an AI app runtime

4 June 2026 at 10:45

For enterprises embracing AI-assisted development, writing code is no longer the hardest part. Operationalizing it is. Microsoft is targeting that challenge with Rayfin, a new open-source SDK and CLI unveiled at Build 2026.

“Rayfin turns backend development into a code-first workflow. Developers and coding agents can define a full application backend in code, including databases, business logic, APIs, identity, and access policies, and deploy it to Microsoft Fabric for a fully managed, enterprise-grade backend,” Shireesh Thota, CVP of databases at Microsoft, wrote in a blog post.

In effect, Thota added, this approach cuts down the manual integration work and time typically required to connect backend systems once an application front-end is built.

Explaining further, how Rayfin works, the top executive said that developers or coding agents working on their behalf define the entire backend using the SDK, and then that definition is deployed directly to Fabric using the CLI.

Governance, not productivity, may be the bigger draw

According to independent consultant David Linthicum, Rayfin increases developer productivity, reduces integration overhead, and platform sprawl: “Instead of standing up separate app runtimes, data services, governance layers, and custom integration code, they can push more of that into one managed environment. It also keeps application data closer to the analytics estate.”

However, the rise in developer productivity is just the hook, according to Stewart Bond, research vice president at IDC.

“For CIOs, the more compelling value proposition is governance and operational control. It is governance by default — inherited security, compliance, and access policies from day one — that addresses the risks CIOs most frequently cite when AI-generated code and agent-authored applications enter production environments,” Bon said.

“IDC research indicates that AI data readiness is not owned by a single team but by a coordinated network of stakeholders across all four planes of the enterprise intelligence architecture, and Rayfin’s architecture reflects that by ensuring that application data lands directly in a governed data estate, making it immediately available for reporting, analytics, and AI workloads without additional pipeline work,” Bond added.

For Ashish Chaturvedi, leader of executive research at HFS Research, Rayfin should help CIOs tackle another facet of non-governance: shadow IT.

“Coding agents have democratized app creation. Today, anyone with a prompt and a browser can spin up a working application in minutes. Every one of those ungoverned apps is a potential data silo, a security gap, and a compliance liability waiting to land on someone’s desk. Rayfin is the governed on-ramp,” Chaturvedi said.

Platforms like Rayfin are set to gain traction

Analysts say platforms like Rayfin are becoming increasingly common as enterprises discover that AI applications are difficult to govern and operationalize when data, models, policies, and runtimes are spread across separate systems.

Enterprises moving beyond isolated AI experiments, according to Bond, increasingly need automated governance, real-time processing, and tighter feedback loops between AI systems and enterprise data — capabilities that are harder to deliver when application and data layers remain separate.

More so because the economics, too, becomes harder to argue, Chaturvedi said.

“When apps run inside the data platform, you eliminate data movement costs, reduce governance surface area, and shrink the attack surface. Within three to five years, converged platforms will be the default for new agentic applications,” the analyst added.

However, Stephanie Walter, practice lead of the AI stack at HyperFRAME Research, pointed out that enterprises will not move every application onto one platform.

“The likely future is a hybrid model: some agentic applications will run inside governed data platforms like Fabric, Snowflake, or Databricks, while others will continue to run on general-purpose cloud runtimes. The architectural question will be where the application’s most sensitive data, context, and control plane should live,” Walter said.

Making Fabric the runtime for AI applications

Beyond the immediate benefits around governance and operational control, Walter sees Rayfin as a strategic move in Microsoft’s broader effort to expand Fabric’s role within the enterprise technology stack.

Rayfin’s release, Walter said, is less about a new developer tool and more about Microsoft’s attempt to reposition Fabric as a platform for building and running AI-native applications.

“Rayfin positions Fabric as a runtime environment for a new class of AI-native applications. That is strategically important because the next phase of enterprise AI will not be won only at the model layer. It will be won by the platforms that can turn governed enterprise data into safe, operational applications,” Walter added.

However, she remained skeptical about whether developers will accept Fabric as an application runtime and not just a data platform: “Rayfin lowers the barrier, but Microsoft still has to prove the developer experience is lightweight enough, the deployment model is flexible enough, and the governance benefits are strong enough to justify building inside Fabric rather than around it.”

Microsoft is making Rayfin available in preview, and enterprises can try the service through a 60-day Microsoft Fabric trial. The SDK and CLI-combo can also be accessed via Replit, the company said.

The next AI breakthrough won’t come from bigger models, but from better data

4 June 2026 at 10:00

Artificial intelligence does not advance at the same pace across industries. It presses forward in some directions while lagging behind in others.

Spend time with today’s most advanced AI applications, and this contrast becomes obvious. In software development, AI is quickly becoming ubiquitous. It writes production-ready code, explains obscure libraries, and iterates at a pace human teams have difficulty matching.

But place that same AI model inside a complex customer support workflow or ask it to reason through a nuanced clinical scenario, and the cracks begin to show. Multi-step reasoning falters. Context gets lost. Performance drops in ways that can seem inconsistent with the model’s strengths elsewhere.

These AI models are often similar. They run on similar hardware and are often trained in similar ways. So why the mismatch in performance across tasks? The simplest explanation is also the most overlooked: data.

Software engineering benefits from an immense, structured, and highly visible digital record. Code is written in standardized languages, benefits from robust documentation, is reviewed in public forums, and is discussed at scale. That ecosystem has generated a robust and massively useful pool of training material.

Other fields often do not. For example, healthcare data is scattered across institutions, wrapped in privacy constraints, expressed in multiple modalities, and rarely ready out-of-the-box for AI training. Enterprise workflows are captured in internal systems that were never designed for training AI. Multilingual speech data varies widely in quality and representation.

This imbalance creates what I describe as “the data gap.” This is the distance between what models are capable of in theory and what they can achieve in practice, because the right data does not yet exist in usable form. Closing this data gap may be the most important—and least glamorous—challenge in AI today.

The missing pillar of AI progress

Three forces are driving the recent advances in AI: the models, the chips, and the data.

On the AI models, the field has invested heavily. Major research organizations employ thousands of researchers and scientists who are actively refining architectures, training techniques, and evaluation methods. Breakthroughs are measured in benchmark scores, conference papers, and model performance on human tasks. On the computing chips, the investment has been equally intense. Hardware manufacturers and infrastructure providers are pouring billions of dollars into building and supporting data centers that deliver faster results via large-scale training.

Yet data has not received the same institutional focus for AI development. Conversations with researchers at frontier AI labs share a similar frustration that today’s model capabilities in key use cases, such as healthcare, are limited less by architectural imagination and more by the availability of high-quality, domain-specific data. The bottleneck is not always a lack of ideas, but a lack of reliable inputs.

We are long past scraping the internet for useful data, and this path does not scale. Progress depends on building and curating datasets that reflect the complexity of true lived experience and organizational processes. That work requires both scientific rigor and research specialization in the field of data for AI.

The dataset behind every leap

The history of AI reinforces a consistent lesson: major leaps in model capability follow major leaps in the availability of quality data. From early vision systems that relied on clearly labeled images to today’s language models trained on massive text collections, each major leap has depended on access to more high-quality data.

Architectural innovation alone is rarely enough. The value of these new approaches only emerges when paired with large, structured, and representative datasets that reveal what the models can actually do in practice. Whether in vision or language, progress has depended on the painstaking work of collecting, organizing, and validating the underlying data.

Large language models illustrate this clearly. Their emergence was not just the result of better training techniques, but of access to an unprecedented volume of data. The models did not generate that data. They relied on it. That pattern raises a pressing question for the present: who is building the next generation of foundational datasets?

Across domains ranging from healthcare to audio to agentic task performance, there is no widely accepted blueprint. What constitutes a gold-standard dataset for training an AI agent to handle complex enterprise tasks? What does a clinically meaningful evaluation look like for a model that will assist in medical decision-making? How should multilingual speech data be curated to ensure broad representation and reliable performance?

These are not simple sourcing problems. They are fundamental research challenges that need to be solved.

When data is treated as a commodity

Too often, consequential data decisions are handled like procurement exercises. An organization requests “medical conversations” or “wildlife scenes,” and the request is routed to internal procurement or data sourcing teams, or to external data vendors, who assemble data that appears to match the description. The implicit assumption is that data is interchangeable, that one dataset is as good as another so long as it meets a basic specification.

Actual application suggests otherwise. Seemingly small choices about factors such as inclusion criteria, annotation standards, filtering rules, and validation protocols can dramatically alter downstream performance. Data design shapes model behavior as much as architecture does.

Three structural issues compound the problem:

  • Capacity: There are relatively few specialized teams dedicated to building domain-specific datasets at the highest level of rigor. Talent and funding have gravitated toward model development and hardware innovation. Data work often operates in the background, even though it underpins both.
  • Design: Constructing a dataset is a distinct discipline from designing a neural network. It requires expertise in experimental design, domain knowledge, and statistical validation. Expecting model researchers to simultaneously shoulder the full burden of data research, while also training and evaluating the models, overlooks the complexity of the upstream task.
  • Translation: The researchers who are requesting specific data sources to improve the models are often not the same people responsible for sourcing that data. As a result, nuances and research-backed expertise can often be missing or diluted as requests pass through layers of procurement and vendor relationships. The result can be data that meets the specification sheet, but in fact fails to advance model performance.

The rise of annotation providers and reinforcement learning services has addressed part of the need. Rating model outputs, labeling text, and evaluating structured information are essential for many optimization tasks. But these activities generate data that is carefully constructed for specific, bounded purposes.

The frontier challenges in AI require more. They demand datasets derived from real human activity and organic organizational processes. Such data is complex, multimodal, and sensitive. It is rarely AI-ready by default. And converting it into reliable training and evaluation material is a scientific undertaking.

The need for scientific rigor for the AI data layer

If high-quality data is a central bottleneck, then scientific rigor is part of the solution. Just as leading model-builders have dedicated research labs and hardware has dedicated development ecosystems, the data layer for AI requires focused, scientifically-grounded institutions.

This means engaging directly with core questions like dataset design, evaluation methodology, and quality control. The conversation cannot end at volume; it must address data structure, representativeness, and expert validation.

Dataset construction must be approached as experimental design. Protocols must be documented and validated. Evaluation frameworks must test whether the dataset truly reflects the intended applications.

The field also requires standards and benchmarks that reflect real-world complexity, not simplified proxies. In healthcare, for instance, evaluating a system intended for clinical assistance with generic question-and-answer tests is insufficient. Real-world clinical environments involve multimodal inputs and contextual judgment. Benchmarks must reflect that reality if they are to function as meaningful gates before deployment.

Quality measurement is another crucial frontier. Finance relies on standardized metrics such as credit scores to assess risk. AI lacks an equivalent for datasets and benchmarks. Developing clear methodology to quantify dataset quality and evaluation reliability brings clarity to model assessment.

The criteria for evaluating a multilingual audio library will differ from those of a multimodal oncology dataset. Yet the underlying principle remains constant. Better models require better-defined, better-measured data.

The risks of getting it wrong

As AI systems move closer to high-stakes deployment, weak data practices carry tangible risks.

Benchmarks cannot be created with the same data that is used for training—that’s giving the test answers to the model ahead of time. Scaling data volume without prioritizing data quality and selection diminishes model performance gains, and can even bias against or omit underrepresented populations. These are methodological challenges, and ones that must be solved.

The rigor required at the data layer may not attract headlines. It does not typically lend itself to dramatic product launches. Yet the data layer for AI is foundational to trust, safety, and sustained progress for all AI progress.

An ecosystem for the data era

No single organization can resolve the data gap alone. What is needed is an ecosystem of AI data labs and research groups, each focused on different domains and challenges but united by a commitment to scientific discipline. These institutions would collaborate with model researchers and domain experts who would tackle challenges such as dataset contamination, factuality, groundedness, de-identification, international representation, and bias. They would design benchmarks that mirror real-world complexity rather than simplified abstractions.

AI’s trajectory will not be determined solely by larger models or faster chips. It will be shaped by the datasets we construct, the standards we adopt, and the rigor we apply at the foundation. The uneven frontier we see today reflects an uneven data landscape. Bridging the gap requires deliberate, research-driven dataset design.

If we want AI systems capable of operating reliably in clinical contexts, navigating enterprise workflows, and functioning responsibly across languages and cultures, we must treat data for AI as a first-class scientific endeavor.

AI models have their research labs. AI chip-builders have their fabrication plants. AI data needs institutions of equal seriousness and ambition.

—

New Tech Forum provides a venue for technology leaders—including vendors and other outside contributors—to explore and discuss emerging enterprise technology in unprecedented depth and breadth. The selection is subjective, based on our pick of the technologies we believe to be important and of greatest interest to InfoWorld readers. InfoWorld does not accept marketing collateral for publication and reserves the right to edit all contributed content. Send all inquiries to doug_dineley@foundryco.com.

Angular Signals explained: How pull-based reactivity changes how we model state

4 June 2026 at 10:00

Angular’s introduction of Signals has generated both excitement and confusion. For many developers, Signals appear to be “simpler observables” or a more convenient way to trigger updates without subscriptions. Others attempt to map them directly onto familiar RxJS patterns, expecting emissions, operators, and event-style coordination.

Both interpretations miss the point.

Signals are not primarily an event system, and they are not designed to replace RxJS. They represent a different way of modeling application behavior, one that centers on current state and explicit dependencies rather than sequences of events. This distinction is subtle at first, but it has significant consequences for how applications are structured and reasoned about over time.

In a previous article, “Angular Signal Forms: From event pipelines to signal-driven state,” we reframed form behavior as a state-driven problem rather than an event-driven one. That shift raises an important follow-up question: what kind of reactive primitive is best suited for expressing state and derived behavior? To answer that, we need to understand Signals on their own terms, independent of any specific feature such as forms.

This article examines Angular Signals as a reactivity model rather than a convenience API. By clarifying what Signals are and, just as importantly, what they are not, we can better understand where they fit alongside RxJS and why they align so naturally with state-heavy problems such as form modeling.

Signals as a state primitive (not an event system)

To understand why Signals are a good fit for form modeling, it helps to be precise about what Signals are, and just as importantly, what they are not.

Signals are not an event system. They do not represent a sequence of things that happened over time. Instead, a signal represents a current value, along with a dependency graph that describes how other values derive from it. When a signal changes, Angular does not broadcast an event. It simply marks dependent computations as stale and reevaluates them the next time they are read. This is what we mean by fine-grained change detection control.

This distinction may seem subtle, but it has profound implications for how we reason about application logic.

Reactive streams encourage developers to think in terms of emissions. When something changes, subscribers are notified, operators transform the stream, and side effects occur in response. This model is extremely powerful for asynchronous workflows, but it introduces temporal reasoning even when time is not an essential concern. Developers must ask not only what the current state is, but how it arrived there and which emission triggered a particular piece of logic.

Signals, by contrast, encourage a declarative, pull-based model. A computed signal does not react to changes as they occur. Instead, it declares that its value depends on other signals. When those dependencies change, the computed value is simply recomputed the next time it is accessed. There is no notion of subscription order, missed emissions, or stale listeners.

This pull-based model aligns naturally with form state. At any moment, a form has a well-defined set of values. From those values, validity, error messages, and UI flags can be derived. These relationships do not depend on the sequence of changes that led to the current state. They depend only on the current state itself.

This is why Signals feel simpler when applied to state-heavy problems. They shift the developer’s focus away from orchestration and toward declaration. Instead of asking “What should happen when this changes?”, the question becomes “What does this value depend on?”

It is important to note that this does not make Signals a replacement for RxJS. Angular still relies on observables for asynchronous streams, external events, and integration with APIs that produce values over time. Signals and RxJS serve different purposes. In the context of forms, Signals are best used to represent state and derived state, while RxJS remains useful for asynchronous side effects and integration points.

By keeping this distinction clear, we avoid the trap of using Signals as a less expressive event system. Instead, we use them for what they do best: modeling state in a way that is explicit, deterministic, and easy to reason about.

Designing a signal-first form model with Angular Signal Forms

Before looking at any concrete implementation, it is worth clarifying what a “signal-first” form model actually implies. The goal is not to introduce a new abstraction that replaces Angular Forms, nor is it to hide form behavior behind another layer of indirection. Instead, the intent is to reorient how form state is represented and reasoned about.

In a signal-first approach, the form’s data model is treated as the single source of truth. Signals are used to represent that state directly, rather than mirroring it through control hierarchies or intermediary objects. The form itself becomes a projection over the state, attaching semantics such as validation, interaction metadata, and submission behavior without duplicating or owning the data.

This distinction is subtle but important. Traditional form models often encourage developers to think of the form as the container of state, with values flowing in and out through events. A signal-first model reverses that relationship. State exists independently of the form, and the form derives its behavior from that state. This makes it easier to inspect, reason about, and test form behavior, because the underlying data remains explicit and accessible.

The examples in this section are therefore intentionally minimal. They are not meant to demonstrate every feature of Angular Signal Forms, but to illustrate how a state-driven representation reshapes form architecture. The emphasis is on structure and intent rather than mechanics. More detailed implementation concerns, such as asynchronous validation, persistence, and UI composition, are explored in the following article.

Once we accept that form behavior is largely derived from state, the next question becomes how that idea is expressed in Angular itself. Angular’s Signal Forms API is a direct response to this shift in thinking. Rather than modeling forms as trees of controls emitting events, Signal Forms begin with a signal-backed model and layer form behavior validation, interaction state, and submission on top of it.

The starting point is still the same: a plain data model representing the values the form collects. In a signal-first approach, this model is wrapped in a writable signal and treated as the single source of truth. There is no duplication of state between the UI and the form model, and no need to synchronize multiple representations of the same data.

From this model signal, a form instance is created using Angular’s form() function. The role of this function is not to introduce a second state container, but to attach form semantics to an existing state object. The form instance provides structured access to fields, validation results, and interaction metadata, all of which are exposed as signals.

Validation is declared through a schema function passed to form(). This schema associates validation rules directly with specific fields in the model. Built-in validators such as required() and email() express constraints declaratively, and Angular automatically reevaluates them whenever the underlying values change. Validation results are not stored imperatively; they are derived and exposed through field-level signals such as invalid(), errors(), and pending().

This design is significant because it keeps validation aligned with the mental model established earlier. Validation rules do not “run” in response to events. They describe constraints on state. When state changes, derived validation state updates automatically, without subscriptions, listeners, or life-cycle hooks.

Angular Signals Form example

A minimal example illustrates the shape of this approach. The model remains a simple interface, and the signal holds the current form values.

interface RegistrationData {
  email: string;
  password: string;
  confirmPassword: string;
  acceptedTerms: boolean;
}

The form is then created by passing this model signal into form(), along with a schema that declares validation rules.

const registrationModel = signal({
  email: '',
  password: '',
  confirmPassword: '',
  acceptedTerms: false,
});

const registrationForm = form(registrationModel, (schema) => {
  required(schema.email, { message: 'Email is required' });
  email(schema.email, { message: 'Enter a valid email address' });

  required(schema.password, { message: 'Password is required' });
  required(schema.confirmPassword, { message: 'Please confirm your password' });

  required(schema.acceptedTerms, {
    message: 'You must accept the terms to continue',
  });
});

What matters here is not the syntax, but the structure. The model signal defines what the form is. The schema defines what constraints apply. Angular takes responsibility for deriving field state and exposing it through signals that the UI can consume directly.

Each field now has a clear, inspectable state. Whether a field is valid, invalid, touched, or pending is no longer inferred by tracing event streams or subscription chains. It is available as a signal, derived from the current model and the declared rules. This makes form behavior easier to reason about, test, and debug.

Just as importantly, this model scales naturally. Cross-field validation, such as checking that two password fields match, can be expressed declaratively using schema-level logic that reads from multiple fields. Form-level state, such as whether submission should be allowed, is derived rather than toggled imperatively. The form remains a projection of the state, not a controller of behavior.

I have avoided discussing templates or DOM integration here. The purpose of this section is to show that Angular’s Signal Forms align closely with the first-principles model introduced above. They do not replace that model; they formalize it.

In the next article in this series, we will connect this signal-first form to an actual Angular component. We will bind fields to inputs, render validation feedback using field state signals, and implement submission logic. This implementation will form the foundation of the GitHub example that accompanies this series and will be extended in later articles to cover asynchronous validation, persistence, and hybrid approaches.

The power of Signals

Angular Signals represent a deliberate shift in how reactivity is expressed within the framework. Rather than focusing on events, emissions, and coordination, Signals encourage developers to describe relationships between values. Computation becomes declarative, dependencies become explicit, and behavior becomes easier to reason about by inspection rather than reconstruction.

This does not diminish the role of RxJS. Event streams, asynchronous workflows, and integration with external systems remain essential parts of modern applications. Signals and RxJS solve different problems, and treating them as interchangeable inevitably leads to confusion. When each is used for what it does best — Signals for state and derivation, RxJS for coordination and side effects — the resulting architecture becomes clearer and more maintainable.

Viewed through this lens, the appeal of Signals is not novelty, but alignment. Signals map closely to how developers already think about state: as something that exists now, from which other values can be derived deterministically. This alignment reduces cognitive overhead, particularly in parts of an application where behavior is dominated by state rather than time.

With this understanding in place, we can now turn to practice. The next article applies these ideas to a concrete Angular example, showing how a signal-first approach reshapes form modeling, validation, and UI logic without reintroducing event-driven complexity.


Hole in GitHub’s browser-based VSCode editor could lead to stolen token

4 June 2026 at 02:35

A vulnerability in GitHub’s browser-based VSCode editor could lead to the theft of a developer’s token under certain circumstances, says a researcher.

The issue, revealed this week in a blog by Ammar Askar, has apparently been already addressed by GitHub owner Microsoft. But it raises a questions about both DevOps security, and about the researcher’s allegation that, because Microsoft doesn’t treat bug discoveries seriously, he can justify giving it short notice before openly publishing vulnerabilities he finds.

First, the bug: Users of github.com may not realize it, but when they are on any repository, they can shift to github.dev and its browser-based version of VSCode just by changing the URL.

Why do this? Because the browser instance of VSCode is pretty powerful, Askar says in his blog. “You can view all the files in the repo (even if it’s a private one), you can send out pull requests, and even make commits.”

Rob Enderle, a IT consultant who heads the Enderle Group, agrees that jumping into VSCode this way is “an incredibly useful tactical tool for quick tasks. By just hitting the ‘.’ key in any GitHub repo, you instantly get a browser-based VS Code interface without having to clone gigabytes of data locally. It’s perfect for rapid PR reviews, quick documentation edits, or navigating code on the fly without breaking your workflow. Just keep in mind that it runs entirely in the browser sandbox; there’s no compute backend, no terminal, and no code execution.”

For any heavy lifting or actual compiling, he added, the developer will still need the raw compute of a local workstation, or a full cloud environment like Codespaces.

The problem, Askar says, is that this functionality is achieved by github.com POSTing over an OAuth token to github.dev that allows it to interact with GitHub on your behalf. “The token is not scoped to the particular repo you interacted with, meaning it has full access to every other repo that you have access to,” he wrote in the blog.

“The presence of this token, and the fact that this web app is running almost the entire brunt of VSCode’s million line Typescript codebase, makes it a great target for anyone looking into VSCode bugs,” he wrote.

The exploit

Askar said that a threat actor could install an extension in a repository using a Jupyter notebook, a web application for creating and sharing computational documents that has the ability to install a malicious local workspace extension while skipping the publisher trust check. In his proof of concept, Askar said that once his payload runs, the newly installed extension will grab the GitHub API token, run a query to get the private repos the developer has access to, and then print out the replies and the token.

This vulnerability also exists in the desktop version of VSCode, Askar said, though it’s harder to exploit, since a threat actor would need to convince the victim to clone their repo and open the notebook containing the webview script payload. “Of course,” he added, “if you [the hacker] had some other XSS [cross-site scripting attack] in a webview that you can get a victim to open, you get effectively full RCE [remote code execution] on their computer.”

In an email, he said this vulnerability was “about as serious as it gets. Any website on the internet could have redirected you to a github.dev link that could have provided an attacker a token to read and modify your code repos. If one could convince the maintainer of a popular software project to click a link, they could have made whatever modifications they wanted to their project.”

This means, said Enderle, “we have to start treating developer endpoints with strict, isolated, zero-trust parameters, because we clearly cannot rely on vendor complacency to protect us.”

This issue reinforces the point that you should never follow any links unless you know exactly where they will take you, added Dwayne McDaniel, principal developer advocate at GitGuardian.

Short notice

Here’s where things get complicated. Because of an unhappy experience when disclosing a previous VSCode vulnerability to Microsoft — the bug was fixed, but Askar wasn’t given credit — this time he only gave GitHub one hour notice that this new discovery was going to be published. Microsoft applied what Askar calls a “stopgap” fix by adding a confirmation when a developer opens notebooks in web VSCode, and by not allowing the trusted publisher requirement to be skipped by commands.

[Related content: When responsible disclosure becomes unpaid labor]

An ethical question

Askar’s short notice raises an ethical question: How far in advance should a responsible researcher give notice to a vendor about a vulnerability before publicly revealing it?

These days, most infosec pros agree that notice must be given, or else a threat actor can quickly exploit a hole. Not only that, but the researcher risks damage to their reputation if reasonable notice isn’t given. Experienced researchers often give vendors at least 30 days to create and distribute a patch.

For their part, vendors often create bug bounty programs, or partner with bug bounty programs, to reward researchers for their work. Unfortunately, some vendors don’t always credit researchers, or downplay the damage a vulnerability can cause. In fact, last month Microsoft and a prominent cybersecurity researcher got into a public spat about one such alleged incident.

An imbalance of power

Asked for comment about Askar’s most recent discovery, a Microsoft spokesperson said, “we value the critical role that the security research community plays in strengthening the security of our products, services, and the broader technology ecosystem. While independent researchers determine when and how to publish their findings, we remain committed to rapidly assessing reported issues, mobilizing the appropriate engineering and security response resources, and delivering mitigations, guidance, and protections as quickly as possible to help safeguard our customers.”

The spokesperson added that the issue Askar reported “has been mitigated for our services and no customer action is required.”

[Related content: Is the vulnerability disclosure process glitched?]

There is a balance between coordinating disclosure with a software vendor (CVD) and full disclosure, Askar told us. But, he added, there’s an imbalance of power. “A security researcher can pour countless hours into an issue, ensuring they develop a good proof of concept and provide all the steps to recreate the issue. With this, they hope to at least get an acknowledgement for their efforts, which they can use to further their security track record or, in the best case, a monetary bounty reward.”

However, he added, “If security vendors don’t adhere to their side of the bargain, public disclosure is one of the few options security researchers have (if they don’t want to sit on their vulnerabilities or sell them on the black market). It forces the vendor to acknowledge the security issue publicly and usually leads to a much faster resolution than any private communication would.”

This, said Enderle, creates problems for enterprises: “When vendor bureaucracy penalizes responsible disclosure, it alienates the security community and forces public zero-day drops, ultimately leaving enterprise customers holding the bag.”

Pyrefly 1.0: A fast, forward-looking Python linter

3 June 2026 at 10:00

A veritable garden of linters and type checkers has blossomed in the Python ecosystem. Pyright and Mypy are two of the most popular, while Astral’s ty and Meta’s Pyrefly are two promising Rust-based newcomers. We compared early-stage ty and Pyrefly last June. One year later, Meta has released Pyrefly 1.0.

Pyrefly is intended to stand out from the pack by way of a few key features. It’s written in Rust for performance and memory efficiency, and it has a number of intriguing forward-looking features, some still experimental.

Setting up Pyrefly

Pyrefly installs into a Python environment like any other Python type checker (pip install pyrefly) and brings with it no additional dependencies. Visual Studio Code users can work with Pyrefly via an extension, but the extension doesn’t give you access to the command-line tools offered by Pyrefly when it’s installed in a project venv.

You can start using Pyrefly right away, with no actual setup. If Pyrefly detects no configuration for a given project, it defaults to flagging only the most high-profile errors: syntax issues, unrecognized names, and so on. To start using Pyrefly’s more advanced features, you can add a [tool.pyrefly] section in pyproject.toml, or create a pyrefly.toml file, and populate those with your desired settings.

You can also run pyrefly init on your codebase and set things up automatically, including migrating existing settings from previous Pyrefly installs or from Mypy or Pyright. By default Pyrefly will use **/*.py* as the project’s includes directory, and will automatically ignore site package paths from your configured environment, thus sparing you potentially thousands of spurious errors from your venv’s installed packages.

Using Pyrefly

Once you have Pyrefly set up on a project, you’ll likely see an immense number of new errors. To silence all of them at once via # pyrefly: ignore comment directives, run pyrefly suppress. This will not only reduce the amount of error noise, but allow you to see what each error actually is from its suppression comments.

Suppression comments have another nice readability feature: they can be placed on the line before the offending error, rather than at the end of it. You can also pre-emptively suppress errors for an entire module with one directive at the top of the file, but having each error suppressed individually makes more sense. And while there’s a pyrefly suppress --remove-unused command to remove suppressions that have no actual error, there’s no command for stripping a codebase of all suppressions. However, because suppressions are consistently formatted, you could remove those suppressions with a simple regex-powered search-and-replace.

A currently experimental feature called baseline files borrows an idea from the basedpyright tool. You generate a project-wide .json file with pyrefly check --baseline that tracks all existing errors in the project, then only new errors apart from those will be reported. It’s a handy way to refactor a codebase when new work is being done on it, so that existing problems can be handled separately.

If you have the Pyrefly extension installed in VS Code, objects without existing type hints will have suggested type hints displayed as inlays if the types can be inferred from the code. These can be added with a right click, or inserted automatically across the codebase with the command pyrefly infer.

Advanced Pyrefly features

Two major third-party Python packages have direct type annotation support in Pyrefly. One is Django and its ORM, via the django-stubs package. Models, fields, relationships, class-based generic views, and many other features have typing support. The other package, Pydantic, gets support from Pyrefly for features like fields, dataclasses, and Pydantic’s own runtime validation logic. Pydantic validation can be “lax” (automatic coercion of types via unions) or “strict” (exact types required).

Many advanced Pyrefly features are still considered experimental, but have a lot of promise. With type coverage, for instance, you can use pyrefly report to generate a JSON report of how thoroughly types are used in the codebase. (This is not to be confused with the coverage package in Python, which describes test coverage for a codebase.)

Another experimental feature lets you generate stub files for a codebase by using static code analysis (not runtime analysis). PyTorch users also benefit from a form of experimental Pyrefly support. Tensor shapes can be described with types and type-checked across transformations. Note that the typing used for this is exclusive to Pyrefly, as there is no agreed-on standard for how to do this.

Pyrefly vs. Pyright and Mypy

Pyright and Mypy have been the default choices for linting and type checking in the Python world for some time now. Pyright is an easy default for Visual Studio Code users, as it’s part of Microsoft’s Python extensions for that editor, and Mypy offers extensibility and broader compatibility with older codebases. Pyrefly, on the other hand, is forward-looking, with fewer legacy concerns. It also has a higher score for test conformance than Mypy, though not a higher score than Pyright.

Other key differences include the type checking philosophy used by each, and their licensing. Pyrefly and Pyright infer as aggressively as possible, while Mypy’s default is to skip anything unannotated. And while Pyrefly and Mypy are MIT-licensed, only Pyright’s core functionality is MIT-licensed. Pylance, the language server extension for VS Code that is powered by Pyright, is proprietary.

Finally, Pyrefly’s Rust codebase gives it a default performance edge over both Mypy and Pyright, which are written in Python and TypeScript, respectively. Astral’s ty, also written in Rust, is still more prototype than mature project. Pyrefly has enough of a feature set right now that it’s already worth experimenting with—although that’s best done on a branch of your code where adding type annotations, suppression comments, and init files won’t pose a problem.

❌