Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 0 additions & 61 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,4 @@ exclude = [".github", "npm", "scripts"]
clap = { version = "4", features = ["derive"] }
directories = "6"
dotenvy = "0.15.7"
serde_json = "1"
tempfile = "3"
200 changes: 101 additions & 99 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,68 +2,95 @@

[简体中文](README_zh.md)

Run Python, TypeScript, JavaScript, Rust, Go, or C# snippets from stdin or a source file with a selected runtime/toolchain version and temporary dependencies in an isolated environment.
Run a disposable Python, TypeScript/JavaScript, Rust, Go, or C# snippet with a selected runtime version and temporary dependencies—without modifying your global environment or current project.

## Installation
```bash
echo 'print("hello")' | run-code python@3.14
```

## Why run-code exists

A small experiment should not require creating a project, choosing a package manager layout, switching the active runtime, installing dependencies, and deleting everything afterward. Installing a package globally or into the current project is faster initially, but leaves unrelated state behind.

`run-code` turns the disposable case into one command:

Homebrew is recommended on macOS:
1. select a runtime or toolchain version;
2. prepare dependencies in an isolated temporary environment;
3. run code from stdin or a source file.

Use it to try a package from its README, verify behavior on a specific runtime, reproduce a small example, or let an agent run a focused check. Use a normal project for multi-file programs, durable dependencies, or build configuration. `run-code` is isolation for convenience, not a security sandbox.

## For agents

After installing the binary, an agent can read its matching `run-code-snippet` skill and exact version-specific instructions by running:

```bash
brew install timzhong1024/tap/run-code
run-code skill
```

You can also install the prebuilt binary through npm:
Install the skill into a project when its use should be repository-specific:

```bash
npm install --global @timzhong2000/run-code
mkdir -p .agents/skills/run-code-snippet
run-code skill > .agents/skills/run-code-snippet/SKILL.md
```

Or install from source:
Or install it globally for reuse across projects:

```bash
cargo install --locked --git https://github.com/timzhong1024/run-code
mkdir -p ~/.agents/skills/run-code-snippet
run-code skill > ~/.agents/skills/run-code-snippet/SKILL.md
```

GitHub Releases also provide standalone binaries for macOS, Linux, and Windows.
For a one-off check, the essential pattern is:

`run-code` delegates to external tools for each language. Install only the backends you use:
```bash
run-code TOOLCHAIN[@VERSION] [--package SPEC ...] [--clean] [--quiet] <<'LANG'
CODE
LANG
```

| Language | Required tool |
| --- | --- |
| Python | [uv](https://docs.astral.sh/uv/getting-started/installation/) |
| TypeScript / JavaScript | [Vite+ (`vp`)](https://viteplus.dev/guide/) |
| Rust | [rustup](https://rustup.rs/) |
| Go | [mise](https://mise.jdx.dev/getting-started.html) |
| C# / .NET | [mise](https://mise.jdx.dev/getting-started.html) |
This gives the agent an explicit runtime, disposable dependencies, isolated project state, and normal stdout/stderr without asking it to scaffold a project manually.

## Examples
## Install

### Source file
On macOS:

```bash
run-code node@20 snippet.ts -- first --verbose
brew install timzhong1024/tap/run-code
```

The source file is read and its contents are copied into a newly created isolated template project before execution. `run-code` does not execute inside the source file's existing project, discover that project's dependencies, or copy sibling files. Add everything the snippet needs with `--package`; arguments after `--` are passed to the snippet.

### Working directory and environment
Other options:

```bash
run-code node@20 --cwd ./fixtures --env-file ./snippet.env snippet.ts
npm install --global @timzhong2000/run-code
cargo install --locked --git https://github.com/timzhong1024/run-code
```

`--cwd` changes the working directory seen by the final snippet process. Template initialization and dependency installation still happen inside the isolated temporary project. `--env-file` loads dotenv-compatible variables for the final launch and snippet process; it does not modify the current shell or earlier setup and dependency-installation steps, and loaded values are omitted from displayed commands. Both paths are resolved from the directory where `run-code` was invoked.
Standalone macOS, Linux, and Windows binaries are available from [GitHub Releases](https://github.com/timzhong1024/run-code/releases).

`run-code` delegates runtime installation to existing tools. Install only the backends you use:

### TypeScript
| Code | Toolchain argument | Required backend |
| --- | --- | --- |
| Python | `python[@VERSION]` | [uv](https://docs.astral.sh/uv/getting-started/installation/) |
| TypeScript / JavaScript | `node[@VERSION]` | [Vite+ (`vp`)](https://viteplus.dev/guide/) |
| Rust | `rust[@VERSION]` | [rustup](https://rustup.rs/) |
| Go | `go[@VERSION]` | [mise](https://mise.jdx.dev/getting-started.html) |
| C# | `dotnet[@VERSION]` | [mise](https://mise.jdx.dev/getting-started.html) |

## Quick examples

### TypeScript with an npm package

```bash
run-code node@20 --package zod@4 --clean <<'TS'
import { z } from "zod";
console.log(await Promise.resolve(z.string().parse("hello")));
console.log(await Promise.resolve(z.object({ id: z.number() }).parse({ id: 1 })));
TS
```

### Python
### Python with a PyPI package

```bash
run-code python@3.14 --package requests==2.32.5 --clean <<'PY'
Expand All @@ -72,7 +99,7 @@ print(requests.__version__)
PY
```

### Rust
### Rust with a crate

```bash
run-code rust@stable --package serde_json@1 --clean <<'RS'
Expand All @@ -82,35 +109,53 @@ fn main() {
RS
```

### C#
### Source files, arguments, working directory, and environment

```bash
run-code dotnet@10 --package Spectre.Console@0.50.0 --clean <<'CS'
using Spectre.Console;
AnsiConsole.MarkupLine("[green]Hello from C#[/]");
CS
run-code node@20 \
--package zod@4 \
--cwd ./fixtures \
--env-file ./snippet.env \
snippet.ts -- first --verbose
```

For asynchronous Rust, specify Cargo features in the dependency spec:
The file is copied into a fresh isolated template; its existing project, dependencies, and sibling files are not used. Arguments after `--` go to the snippet. `--cwd` affects only the final code process, while `--env-file` supplies dotenv-compatible variables without changing the current shell or exposing their values in the displayed command.

```bash
run-code rust@stable --package 'tokio@1[full]' --clean <<'RS'
#[tokio::main]
async fn main() {
println!("async");
}
RS
```
## Execution behavior

In Windows PowerShell 7, use a single-quoted here-string:
- Omitting a version selects the built-in stable policy: Python 3.14, Node latest, Rust stable, Go latest, and .NET 10.
- Python and Node stdin snippets without `--package` run directly; dependencies or file input use an isolated template project.
- Temporary projects are retained by default so their generated command paths remain inspectable. Add `--clean` for a one-off run.
- Package-manager download caches remain enabled, so isolation does not mean downloading every package again.
- By default, dependency installation and the final command are displayed and their output is streamed. `--quiet` leaves only the final process stdout/stderr.
- Node defaults to ESM with TypeScript and top-level `await` support. Use `--commonjs` only for CommonJS-specific code.

```powershell
@'
print("hello\nworld")
'@ | run-code python@3.14 --clean
## CLI reference

```text
run-code [OPTIONS] TOOLCHAIN[@VERSION]
run-code [OPTIONS] TOOLCHAIN[@VERSION] FILE [-- ARG ...]
run-code skill
```

Fish does not support heredocs, so use `printf`:
| Argument | Meaning |
| --- | --- |
| `TOOLCHAIN[@VERSION]` | `python`, `node`, `rust`, `go`, or `dotnet`; `javascript`/`typescript` alias `node`, and `csharp`/`cs` alias `dotnet` |
| `FILE` | Copy and run one source file instead of reading stdin |
| `-- ARG ...` | Pass trailing arguments to the snippet |
| `-p, --package SPEC` | Add a dependency; repeat for multiple packages |
| `--cwd DIR` | Set the final snippet process working directory |
| `--env-file FILE` | Load dotenv variables for the final process |
| `--commonjs` | Run Node code as CommonJS instead of ESM |
| `--clean` | Remove the temporary project after execution |
| `--quiet` | Show only final-process stdout/stderr |
| `skill` | Print the bundled agent skill |

Package specs follow their ecosystems. Python accepts `NAME==VERSION`; Node, Rust, Go, and .NET accept `NAME@VERSION`. Rust features use `NAME[@VERSION][FEATURE,...]`, for example `'tokio@1[full]'`.

### Shell input

Bash and Zsh use the quoted heredocs shown above. Fish can pipe `printf`:

```fish
printf '%s\n' \
Expand All @@ -119,59 +164,16 @@ printf '%s\n' \
run-code node@20
```

## Agent Skill

`run-code skill` prints the complete bundled `SKILL.md` from the installed binary. An agent can discover the skill by its name and description, then read the full instructions when the task matches.

Install it in the current project:

```bash
mkdir -p .agents/skills/run-code-snippet
run-code skill > .agents/skills/run-code-snippet/SKILL.md
```

Or install it in your user directory to make it available across projects:
PowerShell 7 can pipe a single-quoted here-string:

```bash
mkdir -p ~/.agents/skills/run-code-snippet
run-code skill > ~/.agents/skills/run-code-snippet/SKILL.md
```powershell
@'
print("hello\nworld")
'@ | run-code python@3.14 --clean
```

Codex automatically discovers skills in these directories. See the [Codex Skills documentation](https://learn.chatgpt.com/docs/build-skills) for details.

## Why this project exists

Running a temporary snippet often means paying the setup cost of creating a project, installing dependencies, and preparing an environment. Switching to a different runtime or toolchain version for one task is also cumbersome, while installing packages globally or into an existing project creates unwanted state.

Several related tools solve parts of this problem, but none matched the combination of temporary dependencies, version switching, and isolated execution needed here. Inspired by snippet runners, version managers, and temporary package executors, `run-code` combines those steps into one command.

## Security

`run-code` provides environment and dependency isolation; it is not a security sandbox. Snippets and third-party dependencies run with the current user's permissions and may access local files, the network, environment variables, and credentials. Variables loaded with `--env-file` are deliberately available to the snippet, so do not pass secrets to untrusted code.

Dependency installation may execute npm lifecycle scripts, Python build backends, Cargo `build.rs` scripts, or other ecosystem-specific build code. Run only trusted code and dependencies. Inspect unfamiliar packages before use, pin versions in sensitive environments, and avoid exposing unnecessary secrets. `--clean` removes only the temporary project; it cannot undo system or network side effects, and package-manager download caches remain in place.

Report vulnerabilities privately through GitHub private vulnerability reporting. See [SECURITY.md](SECURITY.md) for scope and reporting instructions.

## CLI reference

```text
run-code [OPTIONS] TOOLCHAIN[@VERSION]
run-code [OPTIONS] TOOLCHAIN[@VERSION] FILE [-- ARG ...]
run-code skill
```
Snippets, dependencies, package lifecycle hooks, Python build backends, and Cargo build scripts run with the current user's permissions. They may access files, the network, environment variables, credentials, and other processes. Run only trusted code and packages; pin versions when reproducibility matters and do not pass secrets to untrusted snippets.

- `TOOLCHAIN[@VERSION]`: Select a language and optional version. Supported toolchains are `python`, `node`, `rust`, `go`, and `dotnet`; `javascript` and `typescript` are aliases for `node`, while `csharp` and `cs` are aliases for `dotnet`.
- `FILE`: Read a source file and copy its contents into a new isolated template project. The file's existing project and sibling files are not used. When omitted, source code is read from stdin.
- `ARG`: Pass arguments after `--` to the snippet process. This also works with stdin input.
- `-p, --package SPEC`: Add a temporary dependency. Repeat the option to install multiple packages. Specs follow each ecosystem: Python uses `NAME==VERSION`; Node, Rust, Go, and .NET use `NAME@VERSION`. Rust also supports `NAME[@VERSION][FEATURE,...]`, such as `'tokio@1[full]'`.
- `--cwd DIR`: Set the final snippet process's working directory. Template setup and dependency installation remain isolated from this directory.
- `--env-file FILE`: Load dotenv-compatible variables for the final launch and snippet process. Values override inherited variables with the same name and are not printed in displayed commands; runner-owned isolation variables take precedence.
- `--commonjs`: Run Node code as CommonJS. The default is ESM with top-level `await` support.
- `--clean`: Delete the generated project after execution. Without this option, the project is retained and its path appears in the displayed command.
- `--quiet`: Hide project setup, dependency installation, and command display; print only stdout/stderr from the final code process.
- `skill`: Print the bundled `run-code-snippet` skill.
- `-h, --help`: Show help.
- `-V, --version`: Show the version.

When the version is omitted, built-in defaults are used: Python 3.14, Node latest, Rust stable, Go latest, and .NET 10. C# runs as a .NET 10+ file-based app. For stdin input, Python and Node execute directly when no `--package` option is provided. File input always creates an isolated template project, even without dependencies. Package-manager download caches remain enabled. By default, `run-code` displays only dependency installation and final execution commands while streaming their stdout/stderr; project initialization output is shown only when initialization fails.
`--clean` removes the temporary project, but cannot undo filesystem or network side effects. See [SECURITY.md](SECURITY.md) for the reporting policy and complete security boundary.
Loading