# Your CLI home video recorder 📼


![](https://user-images.githubusercontent.com/42545625/198402542-a305f669-a05a-4d91-b18b-ca76e72b655a.png#gh-light-mode-only align="center")

Write terminal GIFs as code for integration testing and demoing your CLI tools.

[![Welcome to VHS](https://camo.githubusercontent.com/c0ba0da8da954c204252434c33155361a241c783c54499d011b75ce4fe39a4ea/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f6e656f66657463685f332e676966 align="left")](https://camo.githubusercontent.com/c0ba0da8da954c204252434c33155361a241c783c54499d011b75ce4fe39a4ea/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f6e656f66657463685f332e676966)

The above example was generated with VHS ([view source](https://github.com/charmbracelet/vhs/blob/main/examples/neofetch/neofetch.tape)).

## Tutorial

To get started, [install VHS](https://github.com/charmbracelet/vhs#installation) and create a new `.tape` file.

```basic
vhs new demo.tape
```

Open the `.tape` file with your favorite `$EDITOR`.

```basic
vim demo.tape
```

Tape files consist of a series of [commands](https://github.com/charmbracelet/vhs#vhs-command-reference). The commands are instructions for VHS to perform on its virtual terminal. For a list of all possible commands see [the command reference](https://github.com/charmbracelet/vhs#vhs-command-reference).

```basic
# Where should we write the GIF?
Output demo.gif

# Set up a 1200x600 terminal with 46px font.
Set FontSize 46
Set Width 1200
Set Height 600

# Type a command in the terminal.
Type "echo 'Welcome to VHS!'"

# Pause for dramatic effect...
Sleep 500ms

# Run the command by pressing enter.
Enter

# Admire the output for a bit.
Sleep 5s
```

Once you've finished, save the file and feed it into VHS.

```basic
vhs demo.tape
```

All done! You should see a new file called `demo.gif` (or whatever you named the `Output`) in the directory.

![A GIF produced by the VHS code above](https://camo.githubusercontent.com/0176dc24fb7ada28fc31a012e679f7edf52180a98bb224455ad804a68602dd9b/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f64656d6f2e676966 align="left")

For more examples see the [`examples/`](https://github.com/charmbracelet/vhs/tree/main/examples) directory.

## Installation

Note

VHS requires [`ttyd`](https://github.com/tsl0922/ttyd) and [`ffmpeg`](https://ffmpeg.org/) to be installed and available on your `PATH`.

Use a package manager:

```basic
# macOS or Linux
brew install vhs

# Arch Linux (btw)
pacman -S vhs

# Nix
nix-env -iA nixpkgs.vhs

# Windows using scoop
scoop install vhs
```

Or, use Docker to run VHS directly, dependencies included:

```basic
docker run --rm -v $PWD:/vhs ghcr.io/charmbracelet/vhs <cassette>.tape
```

Or, download it:

* [Packages](https://github.com/charmbracelet/vhs/releases) are available in Debian and RPM formats
    
* [Binaries](https://github.com/charmbracelet/vhs/releases) are available for Linux, macOS, and Windows
    

Or, just install it with `go`:

```basic
go install github.com/charmbracelet/vhs@latest
```

<details><summary>Windows, Debian, Ubuntu, Fedora, RHEL, Void Instructions</summary><ul><li></li></ul><div class="highlight highlight-source-shell notranslate position-relative overflow-auto"><pre><span class="pl-c"><span class="pl-c"></span></span><span class="pl-k"></span><span class="pl-c1"></span><span class="pl-s"><span class="pl-pds"></span><span class="pl-pds"></span></span><span class="pl-k"></span><span class="pl-c"><span class="pl-c"></span></span><span class="pl-k"></span></pre><div class="zeroclipboard-container"></div></div><ul><li></li></ul><div class="highlight highlight-source-shell notranslate position-relative overflow-auto"><pre><span class="pl-c1"></span><span class="pl-s"><span class="pl-pds"></span></span><span class="pl-s"></span><span class="pl-s"></span><span class="pl-s"></span><span class="pl-s"></span><span class="pl-s"><span class="pl-pds"></span></span><span class="pl-k"></span><span class="pl-c"><span class="pl-c"></span></span></pre><div class="zeroclipboard-container"></div></div><ul><li></li></ul><div class="highlight highlight-source-shell notranslate position-relative overflow-auto"><pre></pre><div class="zeroclipboard-container"></div></div><ul><li></li></ul><div class="highlight highlight-source-shell notranslate position-relative overflow-auto"><pre><span class="pl-c"><span class="pl-c"></span></span></pre><div class="zeroclipboard-container"></div></div></details>

## Record Tapes

VHS has the ability to generate tape files from your terminal actions!

To record to a tape file, run:

```basic
vhs record > cassette.tape
```

Perform any actions you want and then `exit` the terminal session to stop recording. You may want to manually edit the generated `.tape` file to add settings or modify actions. Then, you can generate the GIF:

```basic
vhs cassette.tape
```

## Publish Tapes

VHS allows you to publish your GIFs to our servers for easy sharing with your friends and colleagues. Specify which file you want to share, then use the `publish` sub-command to host it on `vhs.charm.sh`. The output will provide you with links to share your GIF via browser, HTML, and Markdown.

```basic
vhs publish demo.gif
```

## The VHS Server

VHS has an SSH server built in! When you self-host VHS you can access it as though it were installed locally. VHS will have access to commands and applications on the host, so you don't need to install them on your machine.

To start the server run:

```basic
vhs serve
```

<details><summary>Configuration Options</summary><ul><li><code></code><code></code></li><li><code></code><code></code></li><li><code></code></li><li><code></code></li><li><code></code><code></code></li><li><code></code></li></ul></details>

Then, simply access VHS from a different machine via `ssh`:

```basic
ssh vhs.example.com < demo.tape > demo.gif
```

## VHS Command Reference

Note

You can view all VHS documentation on the command line with `vhs manual`.

There are a few basic types of VHS commands:

* [`Output <path>`](https://github.com/charmbracelet/vhs#output): specify file output
    
* [`Require <program>`](https://github.com/charmbracelet/vhs#require): specify required programs for tape file
    
* [`Set <Setting> Value`](https://github.com/charmbracelet/vhs#settings): set recording settings
    
* [`Type "<characters>"`](https://github.com/charmbracelet/vhs#type): emulate typing
    
* [`Left`](https://github.com/charmbracelet/vhs#arrow-keys) [`Right`](https://github.com/charmbracelet/vhs#arrow-keys) [`Up`](https://github.com/charmbracelet/vhs#arrow-keys) [`Down`](https://github.com/charmbracelet/vhs#arrow-keys): arrow keys
    
* [`Backspace`](https://github.com/charmbracelet/vhs#backspace) [`Enter`](https://github.com/charmbracelet/vhs#enter) [`Tab`](https://github.com/charmbracelet/vhs#tab) [`Space`](https://github.com/charmbracelet/vhs#space): special keys
    
* [`Ctrl[+Alt][+Shift]+<char>`](https://github.com/charmbracelet/vhs#ctrl): press control + key and/or modifier
    
* [`Sleep <time>`](https://github.com/charmbracelet/vhs#sleep): wait for a certain amount of time
    
* [`Hide`](https://github.com/charmbracelet/vhs#hide): hide commands from output
    
* [`Show`](https://github.com/charmbracelet/vhs#show): stop hiding commands from output
    
* [`Screenshot`](https://github.com/charmbracelet/vhs#screenshot): screenshot the current frame
    
* [`Copy/Paste`](https://github.com/charmbracelet/vhs#copy--paste): copy and paste text from clipboard.
    
* [`Source`](https://github.com/charmbracelet/vhs#source): source commands from another tape
    
* [`Env <Key> Value`](https://github.com/charmbracelet/vhs#env): set environment variables
    

### Output

The `Output` command allows you to specify the location and file format of the render. You can specify more than one output in a tape file which will render them to the respective locations.

```basic
Output out.gif
Output out.mp4
Output out.webm
Output frames/ # a directory of frames as a PNG sequence
```

### Require

The `Require` command allows you to specify dependencies for your tape file. These are useful to fail early if a required program is missing from the `$PATH`, and it is certain that the VHS execution will not work as expected.

Require commands must be defined at the top of a tape file, before any non- setting or non-output command.

```basic
# A tape file that requires gum and glow to be in the $PATH
Require gum
Require glow
```

### Settings

The `Set` command allows you to change global aspects of the terminal, such as the font settings, window dimensions, and GIF output location.

Setting must be administered at the top of the tape file. Any setting (except `TypingSpeed`) applied after a non-setting or non-output command will be ignored.

#### Set Shell

Set the shell with the `Set Shell <shell>` command

```basic
Set Shell fish
```

#### Set Font Size

Set the font size with the `Set FontSize <number>` command.

```basic
Set FontSize 10
Set FontSize 20
Set FontSize 40
```

![Example of setting the font size to 10 pixels](https://camo.githubusercontent.com/eea7efd9f5a3595a911748f88afbe97806f8bfd968f3275d644e0ecc6ae049f3/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f666f6e742d73697a652d31302e676966 align="left")

![Example of setting the font size to 20 pixels](https://camo.githubusercontent.com/9ebc0ef9df909bd982fe67810ef6052e0404ffcf099ff1cd315aa2d233d8e6a4/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f666f6e742d73697a652d32302e676966 align="left")

![Example of setting the font size to 40 pixels](https://camo.githubusercontent.com/9aa62d501d53b53d0914a5d19c6b44e362c02229efca9d198b4fff100614aae5/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f666f6e742d73697a652d34302e676966 align="left")

#### Set Font Family

Set the font family with the `Set FontFamily "<font>"` command

```basic
Set FontFamily "Monoflow"
```

![Example of changing the font family to Monoflow](https://camo.githubusercontent.com/66a7504467751013efe0c2a0939c6727c0046ba3f3a3c73c2941048916cce07d/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f666f6e742d66616d696c792e676966 align="left")

#### Set Width

Set the width of the terminal with the `Set Width` command.

```basic
Set Width 300
```

![Example of changing the width of the terminal](https://camo.githubusercontent.com/84882e236684e381e6e91f767e0b326ec2e1678b60f7314f14269ed708e6ae0c/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f77696474682e676966 align="left")

#### Set Height

Set the height of the terminal with the `Set Height` command.

```basic
Set Height 1000
```

![Example of changing the height of the terminal](https://camo.githubusercontent.com/5a463a866a9f31f263ca52fa59afa206da772291f1b8bdb6fb92448144a1e876/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f6865696768742e676966 align="left")

#### Set Letter Spacing

Set the spacing between letters (tracking) with the `Set LetterSpacing` Command.

```basic
Set LetterSpacing 20
```

![Example of changing the letter spacing to 20 pixels between characters](https://camo.githubusercontent.com/b4fec2e86d9d6b75b92c7f768c233a206a6a15d105c831eb988228390c607291/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f6c65747465722d73706163696e672e676966 align="left")

#### Set Line Height

Set the spacing between lines with the `Set LineHeight` Command.

```basic
Set LineHeight 1.8
```

![Example of changing the line height to 1.8](https://camo.githubusercontent.com/a17d32d3d1b21a995da38493eefddab4f270a2c477d17d3674d7fc251e97ee0e/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f6c696e652d6865696768742e676966 align="left")

#### Set Typing Speed

```basic
Set TypingSpeed 500ms # 500ms
Set TypingSpeed 1s    # 1s
```

Set the typing speed of seconds per key press. For example, a typing speed of `0.1` would result in a `0.1s` (`100ms`) delay between each character being typed.

This setting can also be overwritten per command with the `@<time>` syntax.

```basic
Set TypingSpeed 0.1
Type "100ms delay per character"
Type@500ms "500ms delay per character"
```

![Example of using the Type command in VHS](https://camo.githubusercontent.com/a3e40c723cca7327cb0410417c9eb76dbc590c58bba3d515a7360b7017f54560/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f747970696e672d73706565642e676966 align="left")

#### Set Theme

Set the theme of the terminal with the `Set Theme` command. The theme value should be a JSON string with the base 16 colors and foreground + background.

```basic
Set Theme { "name": "Whimsy", "black": "#535178", "red": "#ef6487", "green": "#5eca89", "yellow": "#fdd877", "blue": "#65aef7", "magenta": "#aa7ff0", "cyan": "#43c1be", "white": "#ffffff", "brightBlack": "#535178", "brightRed": "#ef6487", "brightGreen": "#5eca89", "brightYellow": "#fdd877", "brightBlue": "#65aef7", "brightMagenta": "#aa7ff0", "brightCyan": "#43c1be", "brightWhite": "#ffffff", "background": "#29283b", "foreground": "#b3b0d6", "selection": "#3d3c58", "cursor": "#b3b0d6" }
```

[![Example of changing the theme to Whimsy](https://camo.githubusercontent.com/99c87e02e3853987b1668df595ac886bd612bb8359e59587360d6626678386bb/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f7468656d652e676966 align="left")](https://camo.githubusercontent.com/99c87e02e3853987b1668df595ac886bd612bb8359e59587360d6626678386bb/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f7468656d652e676966)

You can also set themes by name:

```basic
Set Theme "Catppuccin Frappe"
```

See the full list by running `vhs themes`, or in [THEMES.md](https://github.com/charmbracelet/vhs/blob/main/THEMES.md).

#### Set Padding

Set the padding (in pixels) of the terminal frame with the `Set Padding` command.

```basic
Set Padding 0
```

![Example of setting the padding](https://camo.githubusercontent.com/4cde2c3cf3c99386e9695047a766753792a4cd95354e83133a041d31475c6c85/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f70616464696e672e676966 align="left")

#### Set Margin

Set the margin (in pixels) of the video with the `Set Margin` command.

```basic
Set Margin 60
Set MarginFill "#6B50FF"
```

![Example of setting the margin](https://camo.githubusercontent.com/cb2b086d6bf35d2dcd7d1a350bab44a23276ad41c4b1bedd3219075e306ecca4/68747470733a2f2f7668732e636861726d2e73682f7668732d316d694b4d744e48656e68374f3473763736544d77472e676966 align="left")

#### Set Window Bar

Set the type of window bar (Colorful, ColorfulRight, Rings, RingsRight) on the terminal window with the `Set WindowBar` command.

```basic
Set WindowBar Colorful
```

![Example of setting the margin](https://camo.githubusercontent.com/21a33e79b6c8e49cd6342ba7070da43a34cca314a2a8d516dec3a531e0884887/68747470733a2f2f7668732e636861726d2e73682f7668732d345667766943753338446261477462527a68744f55492e676966 align="left")

#### Set Border Radius

Set the border radius (in pixels) of the terminal window with the `Set BorderRadius` command.

```basic
# You'll likely want to add a Margin + MarginFill if you use BorderRadius.
Set Margin 20
Set MarginFill "#674EFF"
Set BorderRadius 10
```

![Example of setting the margin](https://camo.githubusercontent.com/fb0408b427e54fe4668082cd14be041bf030547645a9e79f1b5cabd7524c8fe5/68747470733a2f2f7668732e636861726d2e73682f7668732d346e596f79364973554b6d6c654a414e47374e3142482e676966 align="left")

#### Set Framerate

Set the rate at which VHS captures frames with the `Set Framerate` command.

```basic
Set Framerate 60
```

#### Set Playback Speed

Set the playback speed of the final render.

```basic
Set PlaybackSpeed 0.5 # Make output 2 times slower
Set PlaybackSpeed 1.0 # Keep output at normal speed (default)
Set PlaybackSpeed 2.0 # Make output 2 times faster
```

#### Set Loop Offset

Set the offset for when the GIF loop should begin. This allows you to make the first frame of the GIF (generally used for previews) more interesting.

```basic
Set LoopOffset 5 # Start the GIF at the 5th frame
Set LoopOffset 50% # Start the GIF halfway through
```

#### Set Cursor Blink

Set whether the cursor should blink. Enabled by default.

```basic
Set CursorBlink false
```

![Example of setting the cursor blink.](https://camo.githubusercontent.com/987797a517262591b7a31301d77cdc1b0c2e4178972d23cac969fcbb87e4374e/68747470733a2f2f7668732e636861726d2e73682f7668732d33724d4362383056456b614464544f4a4d4372784b792e676966 align="left")

### Type

Use `Type` to emulate key presses. That is, you can use `Type` to script typing in a terminal. Type is handy for both entering commands and interacting with prompts and TUIs in the terminal. The command takes a string argument of the characters to type.

You can set the standard typing speed with [`Set TypingSpeed`](https://github.com/charmbracelet/vhs#set-typing-speed) and override it in places with a `@time` argument.

```basic
# Type something
Type "Whatever you want"

# Type something really slowly!
Type@500ms "Slow down there, partner."
```

Escape single and double quotes with backticks.

```basic
Type `VAR="Escaped"`
```

![Example of using the Type command in VHS](https://camo.githubusercontent.com/9c9e752227160152607645e9795f61f35606a53154ed52990bb7fb8e3c28d2f4/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f747970652e676966 align="left")

### Keys

Key commands take an optional `@time` and optional repeat `count` for repeating the key press every interval of `<time>`.

```basic
Key[@<time>] [count]
```

#### Backspace

Press the backspace key with the `Backspace` command.

```basic
Backspace 18
```

![Example of pressing the Backspace key 18 times](https://camo.githubusercontent.com/ae8bb529ef4229bec44751aa30a9ef9f03e18a62e16468ba03f4a34e7328986a/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f6261636b73706163652e676966 align="left")

#### Ctrl

You can access the control modifier and send control sequences with the `Ctrl` command.

```basic
Ctrl+R
```

![Example of pressing the Ctrl+R key to reverse search](https://camo.githubusercontent.com/70e8be8dcacd54f72f058a3bc3ec837d4503b0fcdb736661d662a4f2de70040c/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f6374726c2e676966 align="left")

#### Enter

Press the enter key with the `Enter` command.

```basic
Enter 2
```

![Example of pressing the Enter key twice](https://camo.githubusercontent.com/af9ceec3e2f1f2ec4815afca35c7338880c4022eed62f2144a1d7a3092a00703/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f656e7465722e676966 align="left")

#### Arrow Keys

Press any of the arrow keys with the `Up`, `Down`, `Left`, `Right` commands.

```basic
Up 2
Down 2
Left
Right
Left
Right
Type "B"
Type "A"
```

![Example of pressing the arrow keys to navigate text](https://camo.githubusercontent.com/336e368185597a6e766cdbab60580774d21c165dab4d27bd361f36740db6df40/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f6172726f772e676966 align="left")

#### Tab

Enter a tab with the `Tab` command.

```basic
Tab@500ms 2
```

![Example of pressing the tab key twice for autocomplete](https://camo.githubusercontent.com/aadea0736e82c997729888c596b9a7f6104ce1490f1c2c2181aa18e6fbe4b82e/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f7461622e676966 align="left")

#### Space

Press the space bar with the `Space` command.

```basic
Space 10
```

![Example of pressing the space key](https://camo.githubusercontent.com/1787376e75a91e31345ba7d9e62d0ca5a22a9427834df788cc7bb75fc91d3867/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f73706163652e676966 align="left")

#### Page Up / Down

Press the Page Up / Down keys with the `PageUp` or `PageDown` commands.

```basic
PageUp 3
PageDown 5
```

### Sleep

The `Sleep` command allows you to continue capturing frames without interacting with the terminal. This is useful when you need to wait on something to complete while including it in the recording like a spinner or loading state. The command takes a number argument in seconds.

```basic
Sleep 0.5   # 500ms
Sleep 2     # 2s
Sleep 100ms # 100ms
Sleep 1s    # 1s
```

### Hide

The `Hide` command instructs VHS to stop capturing frames. It's useful to pause a recording to perform hidden commands.

```basic
Hide
```

This command is helpful for performing any setup and cleanup required to record a GIF, such as building the latest version of a binary and removing the binary once the demo is recorded.

```basic
Output example.gif

# Setup
Hide
Type "go build -o example . && clear"
Enter
Show

# Recording...
Type 'Running ./example'
...
Enter

# Cleanup
Hide
Type 'rm example'
```

### Show

The `Show` command instructs VHS to begin capturing frames, again. It's useful after a `Hide` command to resume frame recording for the output.

```basic
Hide
Type "You won't see this being typed."
Show
Type "You will see this being typed."
```

![Example of typing something while hidden](https://camo.githubusercontent.com/6a7bafe751aa9bfa9db3d8326659bc9885c035fec36105a653af5d4782e9cf4b/68747470733a2f2f73747566662e636861726d2e73682f7668732f6578616d706c65732f686964652e676966 align="left")

### Screenshot

The `Screenshot` command captures the current frame (png format).

```basic
# At any point...
Screenshot examples/screenshot.png
```

### Copy / Paste

The `Copy` and `Paste` copy and paste the string from clipboard.

```basic
Copy "https://github.com/charmbracelet"
Type "open "
Sleep 500ms
Paste
```

### Env

`Env` command sets the environment variable via key-value pair.

```basic
Env HELLO "WORLD"

Type "echo $HELLO"
Enter
Sleep 1s
```

### Source

The `source` command allows you to execute commands from another tape.

```basic
Source config.tape
```

---

## Continuous Integration

You can hook up VHS to your CI pipeline to keep your GIFs up-to-date with the official VHS GitHub Action:

> [⚙️ charmbracelet/vhs-action](https://github.com/charmbracelet/vhs-action)

VHS can also be used for integration testing. Use the `.txt` or `.ascii` output to generate golden files. Store these files in a git repository to ensure there are no diffs between runs of the tape file.

```basic
Output golden.ascii
```

## Syntax Highlighting

There’s a tree-sitter grammar for `.tape` files available for editors that support syntax highlighting with tree-sitter:

> [🌳 charmbracelet/tree-sitter-vhs](https://github.com/charmbracelet/tree-sitter-vhs)

It works great with Neovim, Emacs, and so on!

## Feedback

We’d love to hear your thoughts on this project. Feel free to drop us a note!

* [Twitter](https://twitter.com/charmcli)
    
* [The Fediverse](https://mastodon.social/@charmcli)
    
* [Discord](https://charm.sh/chat)
