Self-Contained Scripts: From Python’s UV to Bun’s TypeScript Revolution

Self-Contained Scripts: From Python's UV to Bun's TypeScript Revolution

Remember the pain of sharing a Python script with someone? “First install Python, then pip install these packages, oh and make sure you have the right Python version…” The same story repeats with Node.js scripts. Modern tools are finally solving this ancient problem by enabling truly self-contained scripts.

The Self-Contained Script Revolution

Python recently introduced inline script dependencies with PEP 723, and tools like UV have made it reality:

Bun takes this concept even further for TypeScript. While Python scripts still need UV installed, Bun can compile your TypeScript into a true standalone binary that includes everything—runtime, dependencies, and your code.

From Python UV to Bun: A Natural Evolution

Let me show you the progression with a real example. Here’s a self-contained Python script using UV:

Now here’s the equivalent in Bun TypeScript:

Real-World Self-Contained Scripts: Claude Code Hooks

Let me show you real self-contained TypeScript scripts from my own setup. These are Claude Code hooks that demonstrate the power of Bun’s approach:

Example 1: Command Logger Hook

Example 2: Desktop Notification Hook

Here’s another self-contained script that sends desktop notifications:

The Magic: No Dependencies Required

What makes these scripts truly self-contained? Let’s compare approaches:

Traditional Node.js Approach

UV Python Approach

Bun Approach

Making Scripts Truly Portable

While the scripts above work great if Bun is installed, we can go one step further and create true binaries:

The compiled binary includes:

  • The Bun runtime
  • Your TypeScript code (transpiled)
  • All dependencies
  • Native modules like SQLite

Comparing Self-Contained Approaches

Let’s look at a practical example across different tools:

UV Python Script

Bun TypeScript Equivalent

When to Use Each Approach

Different self-contained script approaches serve different needs:

Use UV Python when:

  • You need the Python ecosystem (NumPy, Pandas, etc.)
  • Scripts will be run by Python developers
  • You’re prototyping data analysis scripts

Use Bun TypeScript when:

  • You want type safety
  • You need maximum performance
  • You’re building CLI tools or web services
  • You want to compile to standalone binaries

Use traditional package managers when:

  • Building large applications with many dependencies
  • Working in a team with established workflows
  • You need very specific version control

Advanced Pattern: External Dependencies in Bun

While Bun includes many APIs built-in, sometimes you need external packages. Here’s how to keep scripts self-contained while using dependencies:

Performance Comparison: Real Numbers

I benchmarked the Claude Code hooks on my M1 Mac:

Metric Node.js + ts-node Python + UV Bun (interpreted) Bun (compiled)
Startup time ~200ms ~250ms ~10ms ~3ms
Memory usage 35MB 28MB 25MB 22MB
Binary size N/A N/A N/A 92MB

Here’s a template for building self-contained TypeScript tools:

The Future of Self-Contained Scripts

We’re seeing a clear trend across languages:

  • Python: PEP 723 and UV
  • JavaScript/TypeScript: Bun
  • Go: Already compiles to binaries
  • Rust: Cargo scripts in development

The days of “install these 15 dependencies first” are ending. Modern developers expect scripts that just work.

Conclusion

Self-contained scripts represent a fundamental shift in how we think about code distribution. Whether you’re using UV for Python or Bun for TypeScript, the goal is the same: eliminate the setup friction between writing code and running it.

Bun takes this concept to its logical conclusion by not just embedding dependencies but compiling everything into a single binary. My Claude Code hooks demonstrate this perfectly—complex TypeScript applications that run instantly with zero setup.

The next time you’re writing a utility script, consider making it self-contained. Your future self (and your users) will thank you.


Source link