$git clone https://github.com/rasros/lxlx turns a pile of files into one prompt you can paste into an LLM.
| 1 | # lx |
| 2 | |
| 3 | [](https://pkg.go.dev/github.com/rasros/lx) |
| 4 | [](LICENSE) |
| 5 | |
| 6 | lx turns a pile of files into one prompt you can paste into an LLM. |
| 7 | |
| 8 | Point it at a directory and it walks the tree, honours your ignore files, leaves binaries alone, and prints the result as Markdown, XML, HTML, or plain text. It adds a token estimate so you know what you're about to spend. |
| 9 | |
| 10 |  |
| 11 | |
| 12 | [Install](#install) · [Everyday use](#everyday-use) · [Where files come from](#where-files-come-from) · [Stream processing](#stream-processing) · [Configuration](#configuration) |
| 13 | |
| 14 | ## Install |
| 15 | |
| 16 | ```bash |
| 17 | go install github.com/rasros/lx/cmd/lx@latest |
| 18 | ``` |
| 19 | |
| 20 | Or grab a pre-built binary: |
| 21 | |
| 22 | ```bash |
| 23 | curl -fsSL https://raw.github.com/rasros/lx/main/install.sh | bash |
| 24 | ``` |
| 25 | |
| 26 | The clipboard flag (`-c`) needs xclip (X11) or wl-clipboard (Wayland) on Linux; macOS and Windows already have what they |
| 27 | need. |
| 28 | |
| 29 | ## Everyday use |
| 30 | |
| 31 | The common case is "bundle this project and put it on my clipboard": |
| 32 | |
| 33 | ```bash |
| 34 | lx -c |
| 35 | ``` |
| 36 | |
| 37 | With no arguments `lx` starts from the current directory, but you can name any paths you like: |
| 38 | |
| 39 | ```bash |
| 40 | lx src/ docs/ |
| 41 | ``` |
| 42 | |
| 43 | It respects `.gitignore`, `.ignore`, and `.lxignore`, skips hidden files, and drops binaries, so you usually get |
| 44 | sensible output without asking for it. |
| 45 | |
| 46 | **Get your bearings first.** `-t` prints just the directory tree; `-T` prints the tree *and* the files under it: |
| 47 | |
| 48 | ```bash |
| 49 | lx -t src/ |
| 50 | ``` |
| 51 | |
| 52 | **Skip the bodies.** `-u` and `-Y` extract function signatures and type definitions instead of full source, which is |
| 53 | often all a model needs to reason about a codebase: |
| 54 | |
| 55 | ```bash |
| 56 | lx -u -Y src/ |
| 57 | ``` |
| 58 | |
| 59 | **Narrow things down** with include/exclude globs. Here, Python without the tests: |
| 60 | |
| 61 | ```bash |
| 62 | lx -i "*.py" -e "*test*" src/ |
| 63 | ``` |
| 64 | |
| 65 | Since `lx` reads paths from stdin, it composes with whatever you already use to pick files: |
| 66 | |
| 67 | ```bash |
| 68 | git diff --name-only main | lx -c # everything you changed |
| 69 | fd -t f | fzf -m --preview 'lx -n 20 {}' | lx -c # pick interactively |
| 70 | ``` |
| 71 | |
| 72 | **Attach a prompt** and pipe it straight into a tool like [llm](https://github.com/simonw/llm): |
| 73 | |
| 74 | ```bash |
| 75 | lx -p "Explain this project structure" src/ | llm |
| 76 | lx -p "Refactor this to use contexts:" main.go |
| 77 | ``` |
| 78 | |
| 79 | Without `-c` or `-o`, output goes to stdout. |
| 80 | |
| 81 | ## Where files come from |
| 82 | |
| 83 | Local paths are the default, but they aren't the only option. |
| 84 | |
| 85 | A URL can sit anywhere a path can: |
| 86 | |
| 87 | ```bash |
| 88 | lx https://example.com/config.yaml src/ |
| 89 | ``` |
| 90 | |
| 91 | Short repository URLs are pulled down as archives, so you can bundle a project you haven't cloned. GitHub, GitLab, |
| 92 | Bitbucket, and Codeberg all work: |
| 93 | |
| 94 | ```bash |
| 95 | lx github.com/owner/repo |
| 96 | lx https://gitlab.com/owner/repo/-/tree/dev |
| 97 | ``` |
| 98 | |
| 99 | Local archives expand with `-Z` (zip, tar, 7z, rar, and friends): |
| 100 | |
| 101 | ```bash |
| 102 | lx -Z archive.zip |
| 103 | ``` |
| 104 | |
| 105 | And `-D` pulls readable text out of PDFs, Word docs, spreadsheets, and slide decks that would otherwise be skipped as |
| 106 | binary: |
| 107 | |
| 108 | ```bash |
| 109 | lx -D docs/ |
| 110 | ``` |
| 111 | |
| 112 | ## Output formats |
| 113 | |
| 114 | Markdown is the default. The rest are one flag each: |
| 115 | |
| 116 | ```bash |
| 117 | lx --xml . # XML, handy for models that like tags |
| 118 | lx --html src/ docs/ # a standalone HTML page |
| 119 | lx --bare file.txt # plain text, almost no wrapping |
| 120 | ``` |
| 121 | |
| 122 | ## Prompts and sections |
| 123 | |
| 124 | Reusable prompts live in `~/.config/lx/prompts` (override with `$LX_PROMPTS_DIR` or `--prompts-dir`). Reference them by |
| 125 | path, filename, or any unambiguous basename. An ambiguous name just prints the candidates so you can be more specific. |
| 126 | |
| 127 | ```bash |
| 128 | lx -P refactor src/ |
| 129 | lx -P go/test src/foo.go -c |
| 130 | lx -P plan -P comments docs/ src/ # stack as many as you want |
| 131 | lx --list-prompts |
| 132 | ``` |
| 133 | |
| 134 | [rasros/prompts](https://github.com/rasros/prompts) is an example library to start from. |
| 135 | |
| 136 | Use `-s` to label groups of files, which also become section names in XML output: |
| 137 | |
| 138 | ```bash |
| 139 | lx -s "Code under test" src/database/users \ |
| 140 | -s "Test fixtures" src/tests/fixtures |
| 141 | ``` |
| 142 | |
| 143 | ## Stream processing |
| 144 | |
| 145 | This is the one idea worth understa |