How to teach Gemini CLI to write Python scripts with inline dependencies
I learned how to write Python scripts you can run instantly, without ever worrying about
pip install or virtual environments. I then taught Gemini CLI how to do it.
Simon Willison wrote a blog post on one-shot Python tools. Let's review how this works and how you, too, can teach Gemini to write scripts in the same convenient way.
The anatomy of an executable Python script with inline dependencies
I first explored this pattern when visualizing Garmin FIT files, where Gemini CLI wrote a script that I could execute immediately.
First, here's the script that Gemini generated:
#!/usr/bin/env -S uv run
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "fitparse==1.2.0",
# "matplotlib==3.8.2",
# "numpy==1.26.4"
# ]
# ///
import fitparse
import os
import sys
import matplotlib.pyplot as plt
import numpy as np
# ... rest of the script ...
The script starts with a special shebang line to execute the script with
uv run, and includes an inline script metadata block with the Python
dependencies.
The uv run shebang
The first line of the script is a shebang (#!):
#!/usr/bin/env -S uv run
Let's break down each part of this shebang line. First, the shebang sequence (#!) at the very beginning tells the operating system which interpreter to use to run the
script. Second, (/usr/bin/env) is a standard tool that executes commands by respecting the
$PATH environment variable, making the script highly portable across
systems. Third, the split-string option (-S) instructs the env command to run uv with the argument
run rather than looking for a program literally called uv run.
Finally, (uv run) is the subcommand that launches our script using uv, a fast Python
package and project manager. You can learn more at the
uv documentation site.
The inline script metadata block
The second key part is the /// script block, which is a standardized way to
embed a script's dependencies and Python version requirements directly within the
.py file itself. This makes the script portable and lets you run it without
needing a separate requirements.txt or pyproject.toml file.
You can read more about it in the
Python Packaging User Guide.
-
The header
# /// scriptindicates the start of the embedded metadata block. -
The
requires-python = ">=3.12"line specifies that the script needs Python version 3.12 or newer to run correctly. -
The
dependencies = [...]list specifies the external libraries the script depends on, along with their specific versions.
When you run this script using a compatible tool (such as uv), the tool
first reads this block, automatically creates a temporary virtual environment, installs
the specified dependencies, and then executes the script within that environment.
How to teach Gemini this convention
The key to making Gemini CLI produce scripts like this in every session is to give it a
clear, explicit instruction and save it to its global instructional memory in
~/.gemini/GEMINI.md in your home directory. You only need to do this once.
While you can can edit GEMINI.md manually, you can also add instructions to
the using the Save Memory tool. I used the /memory add slash
command, like here:
/memory add When writing single-file Python scripts,
I should use a `uv` shebang (`#!/usr/bin/env -S uv run`) and
include a `# /// script` block to define the Python version
and in-line dependencies (for example, `requires-python = ">=3.12"`,
`dependencies = []`), and make the file
executable.
You can copy this snippet and run it in any gemini session. Gemini CLI then
adds the memory to ~/.gemini/GEMINI.md, and from that point on, whenever
you ask it to write a one-off Python script, it follows this convention.
After adding the instruction, you can run /memory show to view the entire
instructional memory, loaded from the various GEMINI.md files.
How GEMINI.md files work
Instructional memory is stored in files named GEMINI.md, which Gemini CLI
loads from two distinct locations.
Global instructions live in ~/.gemini/GEMINI.md in your home directory,
applying to all sessions across your system.
Project-specific instructions reside in any GEMINI.md file found within
your project's directory hierarchy. Gemini CLI starts from your current directory and
searches up to the .git root and down through all subfolders. If no
.git root is present, the upward search stops at your home directory.
Summary
I've covered:
-
Writing executable, single-file Python scripts by using a
uv runshebang line and adding an inline script metadata block with its dependencies. -
Using the
/memory addcommand to add a clear instruction to the instructional memory of Gemini CLI. This allows you to customize Gemini CLI's behavior to fit your workflow.