SwiftPM gives the REPL a package's build context
The new swift run --repl option builds a package and prepares imports and runtime symbols for interactive use. Its implementation combines module search paths with a temporary dynamic-library product.
Importing a package in a Swift REPL needs more than knowing the module's name. The compiler must locate its interface, and the running session must load the symbols that implement it. Swift Package Manager already knows the package graph and build outputs, so it can prepare both parts of that environment.
Ankit Aggarwal's October 8 introduction adds swift run --repl for that purpose. The command builds the package and launches a REPL capable of importing its library targets. At the announcement, the feature is available in the latest trunk snapshot. It should not be read as an option already present in every installed Swift release.
The implementation change shows the connection between the package graph and the interactive process. SwiftPM synthesizes a dynamic-library product, constructs search and linkage arguments, and launches the interpreter from the selected toolchain. The interactive evaluator itself is the existing Swift REPL.
I like being able to examine a library through small expressions. Swift's build overhead makes it particularly useful when experimentation can start from the actual package without another project. This change removes setup work that the package manager already has enough information to perform.
Imports need compile-time and runtime information
A plain swift invocation starts the REPL without a package context. The announcement notes that core libraries such as Foundation and Dispatch are already available, along with platform system modules. Other Swift modules can also be imported when the REPL receives the right compiler arguments.
For Swift targets, SwiftPM supplies the directory containing the module's .swiftmodule file. For C targets, it supplies the directory containing the module map. Those paths allow the interactive compiler to understand the modules the package uses.
That only solves the declaration side. The session also needs implementations when an expression calls a function from an imported module. SwiftPM builds a shared library containing the root package's library targets, giving the runtime a loadable artifact with the needed symbols.
These responsibilities explain a common source of confusion in interactive tools. An import that can find declarations and a call that can execute linked code require related but different preparation. A package-aware launcher can derive both from one build plan instead of requiring the user to assemble them separately.
The package graph supplies an interactive product
The patch adds an optional mode for creating the special REPL product while loading the graph. In that mode, the package builder gathers library targets into a dynamic-library product. The product name uses the package name with a __REPL suffix.
This product exists to support the interactive session. The announcement says it is built only for the REPL option and does not affect other package-manager operations. A package author does not have to add a permanent distribution product just to experiment with the package's libraries.
The distinction between a target and a product is visible in that implementation. A package can contain several library targets, while the REPL needs a shared artifact that makes their implementations available together. SwiftPM creates that artifact from its knowledge of the targets instead of asking the manifest to predict the interactive use case.
Dependencies also contribute information. The implementation includes module-map search paths for Clang targets and compiler flags obtained through package configuration for reachable system-library targets. A package's interactive environment needs to account for these dependencies as well as its own Swift source.
This is the part of the change that makes it more useful than a short alias for launching the interpreter. The command derives a usable environment from the graph. A hand-maintained list of paths can become inaccurate when the graph or build layout changes.
The command builds before opening the session
The supported invocation is short when run from the package directory.
swift run --repl
The implementation loads the package graph with REPL-product creation enabled, creates a build plan and builds it before starting the interpreter. Its build subset excludes tests. This is preparation for an interactive library session, not a request to execute the package's test suite.
After the build, SwiftPM prints the arguments used to launch the REPL. That makes the derived environment visible. The displayed arguments can help explain why a module is available and which generated library the session is loading.
In the patch's build-plan test, the expected arguments include the build directory for module and library search, a generated module-map directory and a dependency's include directory. The test also checks the special product's name. Those assertions target the integration that makes package imports possible.
The test does not establish that every library operation works correctly in an interactive session. It verifies the argument-construction behavior for the package graph represented by its fixture. That is the right evidence for this particular implementation mechanism.
Interactive use starts at a library boundary
The announcement demonstrates Yams, a package for YAML, by importing it and calling its dump and load operations. A compact version of the demonstrated interaction is shown below.
import Yams
let text = try Yams.dump(object: ["count": 3])
let decoded = try Yams.load(yaml: text)
print(decoded)
This example assumes the session was launched from the appropriate package environment with the new option. It exercises a library API directly. It does not need an executable target whose only purpose is to call that API once.
Aggarwal also demonstrates Vapor's HTTP package and parses a response with Foundation. That example uses a package built on SwiftNIO, showing a more involved dependency graph than the YAML interaction. The launcher prepares the package context while the user writes the expressions to exercise it.
My preference is to keep this kind of exploration close to the package that defines the behavior. Once an expression becomes a lasting requirement, it can inform ordinary test code. The immediate benefit here is earlier in that process, when a developer needs to inspect returned values and understand an API without constructing another build definition.
The new command therefore joins two pieces of existing infrastructure. SwiftPM understands the graph and can build a loadable library, while the REPL can evaluate Swift with supplied module and linkage arguments. Their integration makes a package's libraries available to an interactive session through one documented snapshot command.