├── .gitattributes ├── .gitignore ├── start.sh ├── freeze.json ├── LICENSE ├── flake.lock ├── flake.nix ├── README-ja.md ├── README.md └── gallery ├── npm-install.svg ├── npm-run-dev.svg └── tree.svg /.gitattributes: -------------------------------------------------------------------------------- 1 | *.svg -diff 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /*.svg 2 | result* 3 | -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | exec tmux new-session 'fish --init-command="function fish_prompt; echo '"'"'\$'" '"'; end"' -------------------------------------------------------------------------------- /freeze.json: -------------------------------------------------------------------------------- 1 | { 2 | "theme": "catppuccin-mocha", 3 | "window": false, 4 | "border": { 5 | "radius": 0, 6 | "width": 0, 7 | "color": "#515151" 8 | }, 9 | "shadow": false, 10 | "padding": [20, 40, 20, 20], 11 | "margin": "0", 12 | "font": { 13 | "family": "JetBrainsMono Nerd Font Mono", 14 | "size": 12 15 | }, 16 | "line_height": 1.2 17 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 suin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "inputs": { 5 | "systems": "systems" 6 | }, 7 | "locked": { 8 | "lastModified": 1731533236, 9 | "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", 10 | "owner": "numtide", 11 | "repo": "flake-utils", 12 | "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "numtide", 17 | "repo": "flake-utils", 18 | "type": "github" 19 | } 20 | }, 21 | "nixpkgs": { 22 | "locked": { 23 | "lastModified": 1750365781, 24 | "narHash": "sha256-XE/lFNhz5lsriMm/yjXkvSZz5DfvKJLUjsS6pP8EC50=", 25 | "owner": "NixOS", 26 | "repo": "nixpkgs", 27 | "rev": "08f22084e6085d19bcfb4be30d1ca76ecb96fe54", 28 | "type": "github" 29 | }, 30 | "original": { 31 | "owner": "NixOS", 32 | "ref": "nixos-unstable", 33 | "repo": "nixpkgs", 34 | "type": "github" 35 | } 36 | }, 37 | "root": { 38 | "inputs": { 39 | "flake-utils": "flake-utils", 40 | "nixpkgs": "nixpkgs" 41 | } 42 | }, 43 | "systems": { 44 | "locked": { 45 | "lastModified": 1681028828, 46 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 47 | "owner": "nix-systems", 48 | "repo": "default", 49 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 50 | "type": "github" 51 | }, 52 | "original": { 53 | "owner": "nix-systems", 54 | "repo": "default", 55 | "type": "github" 56 | } 57 | } 58 | }, 59 | "root": "root", 60 | "version": 7 61 | } 62 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 4 | flake-utils.url = "github:numtide/flake-utils"; 5 | }; 6 | 7 | outputs = 8 | { 9 | self, 10 | nixpkgs, 11 | flake-utils, 12 | }: 13 | flake-utils.lib.eachDefaultSystem ( 14 | system: 15 | let 16 | pkgs = import nixpkgs { 17 | inherit system; 18 | }; 19 | 20 | tools = with pkgs; [ 21 | tmux 22 | charm-freeze 23 | fishMinimal 24 | fontconfig 25 | nerd-fonts.jetbrains-mono 26 | ]; 27 | in 28 | { 29 | devShells = { 30 | default = pkgs.mkShell { 31 | packages = tools ++ [ pkgs.inkscape ]; 32 | FONTCONFIG_PATH = "${pkgs.fontconfig.out}/etc/fonts"; 33 | }; 34 | start = pkgs.mkShell { 35 | packages = tools; 36 | shellHook = '' 37 | ./start.sh 38 | ''; 39 | }; 40 | }; 41 | packages = { 42 | terminal = pkgs.writeShellApplication { 43 | name = "terminal"; 44 | runtimeInputs = with pkgs; [ 45 | fishMinimal 46 | tmux 47 | ]; 48 | text = '' 49 | tmux new-session 'fish --init-command="function fish_prompt; echo '"'"'\$'" '"'; end"' 50 | ''; 51 | }; 52 | # Takes screenshots of the terminal instance 53 | # usage: capture -o output.svg 54 | # TODO: make excluded prompt lines configurable here 55 | capture = pkgs.writeShellApplication { 56 | name = "capture"; 57 | runtimeInputs = tools; 58 | runtimeEnv.FONTCONFIG_PATH = "${pkgs.fontconfig}/etc/fonts"; 59 | text = '' 60 | tmux capture-pane -pet 0 | freeze -c ${self}/freeze.json "$@" 61 | ''; 62 | }; 63 | }; 64 | } 65 | ); 66 | } 67 | -------------------------------------------------------------------------------- /README-ja.md: -------------------------------------------------------------------------------- 1 | # terminal-svg-screenshot 2 | 3 | きれいなSVGスクリーンショットを作成するためのツールです。ターミナルの出力をSVG形式で保存することで、高品質かつ編集可能なスクリーンショットを簡単に作成できます。ドキュメントやブログ記事の作成に最適です。 4 | 5 | ## 必要なもの 6 | 7 | - nix(flakeが使える環境) 8 | - ウィンドウサイズを調整できるターミナルアプリ 9 | - バイザー設定などで幅が固定されていないものを使用してください 10 | - 推奨:Ghostty、Hyper 11 | - `brew install --cask ghostty` 12 | - `brew install --cask hyper` 13 | 14 | ## 使い方 15 | 16 | ### 1. リポジトリのセットアップ 17 | 18 | 以下のコマンドでリポジトリをクローンします: 19 | 20 | ```zsh 21 | git clone https://github.com/suin/terminal-svg-screenshot.git 22 | cd terminal-svg-screenshot 23 | ``` 24 | 25 | ### 2. スクリーンショットの作成 26 | 27 | 2つのターミナルを使用します: 28 | 29 | 1. モデルターミナル:撮影したいコマンドを実行するターミナル 30 | 2. カメラマンターミナル:SVGファイルを出力するターミナル 31 | 32 | #### モデルターミナルの準備 33 | 34 | 1. ターミナルアプリを開きます(iTerm2ではなく、ウインドウサイズが調整できるアプリを使用してください) 35 | 2. 以下のコマンドを実行します: 36 | ```zsh 37 | nix develop .#start 38 | ``` 39 | 3. 撮影したいコマンドを実行します 40 | 4. ターミナルウィンドウにちょうど収まるようにウインドウサイズと文字サイズを調整します 41 | 5. 画面構成が決まったら、そのままの状態にしておきます 42 | 43 | #### スクリーンショットの撮影 44 | 45 | カメラマンターミナルで以下の手順を実行します: 46 | 47 | 1. 新しいターミナルを開き、以下のコマンドを実行します: 48 | ```zsh 49 | nix develop 50 | ``` 51 | 52 | 2. SVGファイルを生成します: 53 | ```zsh 54 | tmux capture-pane -pet 0 | freeze -c ./freeze.json -o output.svg 55 | ``` 56 | 57 | プロンプト行の調整が必要な場合は、以下のコマンドを使用します: 58 | 59 | - 最後の行のプロンプトを除外: 60 | ```zsh 61 | tmux capture-pane -pet 0 | head -n -1 | freeze -c ./freeze.json -o output.svg 62 | ``` 63 | 64 | - 末尾行数の微調整(出力を確認しながら行数を調整): 65 | ```zsh 66 | tmux capture-pane -pet 0 | head -n -10 67 | ``` 68 | 69 | #### SVGの後処理 70 | 71 | 環境によってフォントの問題が発生することを防ぐため、テキストをアウトライン化することをお勧めします: 72 | 73 | ```zsh 74 | inkscape --export-text-to-path output.svg -o output-outlined.svg 75 | ``` 76 | 77 | 必要に応じて、FigmaやIllustratorで追加の編集を行うことができます。 78 | 79 | ## カスタマイズ 80 | 81 | ### テーマの設定 82 | 83 | `freeze.json`でターミナルの見た目を設定できます: 84 | 85 | - 背景色 86 | - 文字色 87 | - 文字サイズ 88 | - その他の設定 89 | 90 | 詳細は[freezeのドキュメント](https://github.com/charmbracelet/freeze)を参照してください。 91 | 利用可能なテーマは[こちら](https://xyproto.github.io/splash/docs/all.html)で確認できます。 92 | 93 | ### フォントの変更 94 | 95 | デフォルトではJetBrainsMono Nerd Font Monoを使用しています。フォントを変更する場合は: 96 | 97 | 1. `freeze.json`の`font`設定を変更します 98 | 2. `flake.nix`に使用したいフォントを追加します: 99 | 100 | ```nix 101 | tools = with pkgs; [ 102 | tmux 103 | charm-freeze 104 | fish 105 | inkscape 106 | fontconfig 107 | nerd-fonts.jetbrains-mono 108 | # ここに新しいフォントを追加 109 | ]; 110 | ``` 111 | 112 | ## ギャラリー 113 | 114 | 以下のスクリーンショットは、このリポジトリのサンプルコマンドを使用して作成されました: 115 | 116 | ![](gallery/npx-create-next-app.svg) 117 | 118 | ![](gallery/tree.svg) 119 | 120 | ![](gallery/nvim.svg) 121 | 122 | ![](gallery/npm-install.svg) 123 | 124 | ![](gallery/npm-run-dev.svg) 125 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # terminal-svg-screenshot 2 | 3 | A tool for creating beautiful SVG screenshots. Easily capture terminal output in SVG format to create high-quality, editable screenshots perfect for documentation and blog posts. 4 | 5 | [日本語版のREADME](README-ja.md) 6 | 7 | ## Requirements 8 | 9 | - nix (with flakes enabled) 10 | - Terminal app with adjustable window size 11 | - Use a terminal that doesn't have fixed width settings (like visor mode) 12 | - Recommended: Ghostty, Hyper 13 | - `brew install --cask ghostty` 14 | - `brew install --cask hyper` 15 | 16 | ## Usage 17 | 18 | ### 1. Repository Setup 19 | 20 | Clone the repository with the following commands: 21 | 22 | ```zsh 23 | git clone https://github.com/suin/terminal-svg-screenshot.git 24 | cd terminal-svg-screenshot 25 | ``` 26 | 27 | ### 2. Creating Screenshots 28 | 29 | You'll need two terminal windows: 30 | 31 | 1. Model Terminal: The terminal where you'll execute the commands you want to capture 32 | 2. Photographer Terminal: The terminal that will output the SVG file 33 | 34 | #### Preparing the Model Terminal 35 | 36 | 1. Open your terminal app (avoid iTerm2; use an app that allows window size adjustment) 37 | 2. Run the following command: 38 | ```zsh 39 | nix develop .#start 40 | ``` 41 | 3. Execute the commands you want to capture 42 | 4. Adjust the window size and font size to fit your content perfectly 43 | 5. Keep the window configuration as is once you're satisfied 44 | 45 | #### Taking the Screenshot 46 | 47 | In the Photographer Terminal, follow these steps: 48 | 49 | 1. Open a new terminal and run: 50 | ```zsh 51 | nix develop 52 | ``` 53 | 54 | 2. Generate the SVG file: 55 | ```zsh 56 | tmux capture-pane -pet 0 | freeze -c ./freeze.json -o output.svg 57 | ``` 58 | 59 | For prompt line adjustments, use these commands: 60 | 61 | - To exclude the last prompt line: 62 | ```zsh 63 | tmux capture-pane -pet 0 | head -n -1 | freeze -c ./freeze.json -o output.svg 64 | ``` 65 | 66 | - To fine-tune the number of trailing lines (adjust while checking output): 67 | ```zsh 68 | tmux capture-pane -pet 0 | head -n -10 69 | ``` 70 | 71 | #### SVG Post-processing 72 | 73 | To prevent font issues across different environments, it's recommended to convert text to outlines: 74 | 75 | ```zsh 76 | inkscape --export-text-to-path output.svg -o output-outlined.svg 77 | ``` 78 | 79 | You can perform additional editing in Figma or Illustrator if needed. 80 | 81 | ## Customization 82 | 83 | ### Theme Configuration 84 | 85 | Customize the terminal appearance in `freeze.json`: 86 | 87 | - Background color 88 | - Text color 89 | - Font size 90 | - Other settings 91 | 92 | For more details, refer to the [freeze documentation](https://github.com/charmbracelet/freeze). 93 | Available themes can be found [here](https://xyproto.github.io/splash/docs/all.html). 94 | 95 | ### Changing Fonts 96 | 97 | The default font is JetBrainsMono Nerd Font Mono. To change the font: 98 | 99 | 1. Modify the `font` setting in `freeze.json` 100 | 2. Add your desired font to `flake.nix`: 101 | 102 | ```nix 103 | tools = with pkgs; [ 104 | tmux 105 | charm-freeze 106 | fish 107 | inkscape 108 | fontconfig 109 | nerd-fonts.jetbrains-mono 110 | # Add your new font here 111 | ]; 112 | ``` 113 | 114 | ## Gallery 115 | 116 | The following screenshots were created using sample commands from this repository: 117 | 118 | ![](gallery/npx-create-next-app.svg) 119 | 120 | ![](gallery/tree.svg) 121 | 122 | ![](gallery/nvim.svg) 123 | 124 | ![](gallery/npm-install.svg) 125 | 126 | ![](gallery/npm-run-dev.svg) 127 | -------------------------------------------------------------------------------- /gallery/npm-install.svg: -------------------------------------------------------------------------------- 1 | 2 | 12 | 14 | 23 | 30 | 36 | 39 | 42 | 46 | 50 | 51 | 56 | 60 | 65 | 69 | 73 | 78 | 81 | 84 | 88 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /gallery/npm-run-dev.svg: -------------------------------------------------------------------------------- 1 | 2 | 12 | 14 | 23 | 30 | 36 | 39 | 42 | 46 | 50 | 54 | 55 | 60 | 64 | 68 | 73 | 76 | 80 | 83 | 84 | 88 | 92 | 97 | 100 | 104 | 107 | 108 | 111 | 115 | 118 | 119 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /gallery/tree.svg: -------------------------------------------------------------------------------- 1 | 2 | 12 | 14 | 23 | 30 | 36 | 39 | 42 | 46 | 50 | 54 | 55 | 58 | 62 | 65 | 66 | 69 | 73 | 77 | 80 | 81 | 84 | 88 | 92 | 93 | 96 | 100 | 104 | 107 | 108 | 111 | 115 | 118 | 119 | 122 | 126 | 129 | 130 | 133 | 137 | 140 | 141 | 144 | 148 | 152 | 155 | 156 | 159 | 163 | 167 | 170 | 171 | 174 | 178 | 182 | 185 | 186 | 189 | 193 | 196 | 197 | 200 | 204 | 208 | 212 | 213 | 216 | 220 | 223 | 224 | 227 | 231 | 235 | 238 | 239 | 242 | 246 | 250 | 251 | 254 | 258 | 262 | 263 | 266 | 270 | 274 | 275 | 278 | 282 | 286 | 287 | 290 | 294 | 298 | 299 | 302 | 306 | 310 | 314 | 315 | 318 | 322 | 326 | 329 | 330 | 333 | 337 | 341 | 345 | 346 | 347 | 348 | --------------------------------------------------------------------------------