How to Teach Gemini CLI to Write Python Scripts with Inline Dependencies

July 11, 2025 Wietse Venema

In a previous post, I shared how Gemini CLI wrote a portable, single-file Python script that I could immediately run. I didn't have to run pip install or create a virtual environment, even though it used various Python dependencies.

This was not a coincidence; I learned how to write single-file executable Python scripts with inline dependencies through a blog post by Simon Willison on one-shot Python tools, and I taught Gemini CLI to always write scripts in that way.

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

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:

  • #!: This is the shebang (or hashbang). It's a special character sequence at the very beginning of a script that tells the operating system which program to use to run the script's contents.

  • /usr/bin/env: This is a standard utility that executes a command, respecting the $PATH shell variable. Using env instead of a direct path (for example, #!/usr/bin/uv) makes the script more portable. It doesn't matter if uv is installed in /usr/bin/uv or /home/user/.local/bin/uv; env finds it.

  • -S: It's the split-string option and it makes the env command execute uv with the argument run, instead of trying to find a non-existent program named "uv run".

  • uv run: A subcommand of uv that executes a Python script. In case you're not familiar with uv, it's a super fast Python package and project manager. Read more about it 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 easy to run without needing a separate requirements.txt or pyproject.toml file. You can read more about it in the Python Packaging User Guide.

  • # /// script: This header indicates the start of the embedded metadata block.

  • # requires-python = ">=3.12": This line specifies that the script needs Python version 3.12 or newer to run correctly.

  • # dependencies = [...]: This is a list of 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 is to give it a clear, explicit instruction and save it to its instructional memory. You only need to do this once.

You can provide the instruction by using the /memory add command in the Gemini CLI prompt:

/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 (e.g., `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 uses the Save Memory tool to add the instruction to your global GEMINI.md file (located at ~/.gemini/GEMINI.md), and refreshes the instructional memory in the current session. From that point on, whenever you ask it to write a one-off Python script, it will follow this convention.

After adding the instruction you can run /memory show to view the entire instructional memory, loaded from the various GEMINI.md files.

Summary

Here's what this post covered:

  • Writing executable, single-file Python scripts by using a uv run shebang line and adding an inline script metadata block with its dependencies.
  • Using the /memory add command 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.

* * *