llmess 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- llmess-0.1.0/.github/workflows/publish.yml +50 -0
- llmess-0.1.0/.github/workflows/test.yml +50 -0
- llmess-0.1.0/.gitignore +34 -0
- llmess-0.1.0/LICENSE +21 -0
- llmess-0.1.0/PKG-INFO +205 -0
- llmess-0.1.0/README.md +178 -0
- llmess-0.1.0/pyproject.toml +56 -0
- llmess-0.1.0/src/llmess/__init__.py +3 -0
- llmess-0.1.0/src/llmess/__main__.py +6 -0
- llmess-0.1.0/src/llmess/cli.py +311 -0
- llmess-0.1.0/src/llmess/pager.py +790 -0
- llmess-0.1.0/tests/__init__.py +0 -0
- llmess-0.1.0/tests/test_llmess.py +571 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
name: Build distribution
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v6
|
|
13
|
+
with:
|
|
14
|
+
persist-credentials: false
|
|
15
|
+
|
|
16
|
+
- name: Set up Python
|
|
17
|
+
uses: actions/setup-python@v6
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.x"
|
|
20
|
+
|
|
21
|
+
- name: Install build dependencies
|
|
22
|
+
run: python3 -m pip install build --user
|
|
23
|
+
|
|
24
|
+
- name: Build package
|
|
25
|
+
run: python3 -m build
|
|
26
|
+
|
|
27
|
+
- name: Store distribution packages
|
|
28
|
+
uses: actions/upload-artifact@v5
|
|
29
|
+
with:
|
|
30
|
+
name: python-package-distributions
|
|
31
|
+
path: dist/
|
|
32
|
+
|
|
33
|
+
publish:
|
|
34
|
+
name: Publish to PyPI
|
|
35
|
+
needs: build
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
environment:
|
|
38
|
+
name: pypi
|
|
39
|
+
url: https://pypi.org/p/llmess
|
|
40
|
+
permissions:
|
|
41
|
+
id-token: write # Required for OIDC trusted publishing
|
|
42
|
+
steps:
|
|
43
|
+
- name: Download distribution packages
|
|
44
|
+
uses: actions/download-artifact@v6
|
|
45
|
+
with:
|
|
46
|
+
name: python-package-distributions
|
|
47
|
+
path: dist/
|
|
48
|
+
|
|
49
|
+
- name: Publish to PyPI
|
|
50
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v6
|
|
17
|
+
with:
|
|
18
|
+
persist-credentials: false
|
|
19
|
+
|
|
20
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
21
|
+
uses: actions/setup-python@v6
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip install --upgrade pip
|
|
28
|
+
pip install pytest
|
|
29
|
+
pip install -e .
|
|
30
|
+
|
|
31
|
+
- name: Run tests
|
|
32
|
+
run: pytest tests/ -v
|
|
33
|
+
|
|
34
|
+
lint:
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/checkout@v6
|
|
38
|
+
with:
|
|
39
|
+
persist-credentials: false
|
|
40
|
+
|
|
41
|
+
- name: Set up Python
|
|
42
|
+
uses: actions/setup-python@v6
|
|
43
|
+
with:
|
|
44
|
+
python-version: "3.12"
|
|
45
|
+
|
|
46
|
+
- name: Install ruff
|
|
47
|
+
run: pip install ruff
|
|
48
|
+
|
|
49
|
+
- name: Run ruff
|
|
50
|
+
run: ruff check src/ tests/
|
llmess-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
|
|
7
|
+
# Distribution / packaging
|
|
8
|
+
.Python
|
|
9
|
+
build/
|
|
10
|
+
dist/
|
|
11
|
+
*.egg-info/
|
|
12
|
+
.eggs/
|
|
13
|
+
*.egg
|
|
14
|
+
|
|
15
|
+
# Virtual environments
|
|
16
|
+
.venv/
|
|
17
|
+
venv/
|
|
18
|
+
ENV/
|
|
19
|
+
|
|
20
|
+
# Testing
|
|
21
|
+
.pytest_cache/
|
|
22
|
+
.coverage
|
|
23
|
+
htmlcov/
|
|
24
|
+
|
|
25
|
+
# Editor files
|
|
26
|
+
*.swp
|
|
27
|
+
*.swo
|
|
28
|
+
*~
|
|
29
|
+
.idea/
|
|
30
|
+
.vscode/
|
|
31
|
+
|
|
32
|
+
# OS files
|
|
33
|
+
.DS_Store
|
|
34
|
+
Thumbs.db
|
llmess-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 tgies
|
|
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.
|
llmess-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: llmess
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A less pager that uses LLMs to hallucinate infinite file continuations
|
|
5
|
+
Project-URL: Homepage, https://github.com/tgies/llmess
|
|
6
|
+
Project-URL: Repository, https://github.com/tgies/llmess
|
|
7
|
+
Author: tgies
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: cli,humor,less,llm,pager
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Environment :: Console :: Curses
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: POSIX
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Topic :: Games/Entertainment
|
|
24
|
+
Classifier: Topic :: Text Processing
|
|
25
|
+
Requires-Python: >=3.8
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# llmess
|
|
29
|
+
|
|
30
|
+
Some files end too early. Some files don't contain what you're looking for.
|
|
31
|
+
|
|
32
|
+
`llmess` is a `less` pager that addresses both issues:
|
|
33
|
+
|
|
34
|
+
- When you scroll past the end of a file, an LLM generates more content.
|
|
35
|
+
- When you search for a term that doesn't exist, the LLM generates content containing it.
|
|
36
|
+
|
|
37
|
+
Works with any model supported by the [`llm`](https://llm.datasette.io/) CLI.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
### Prerequisites
|
|
42
|
+
|
|
43
|
+
You need the [`llm`](https://llm.datasette.io/) CLI tool installed and configured:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Install llm
|
|
47
|
+
pipx install llm
|
|
48
|
+
|
|
49
|
+
# Install plugins for your preferred provider
|
|
50
|
+
llm install llm-openrouter # or llm-claude, llm-ollama, etc.
|
|
51
|
+
|
|
52
|
+
# Configure API keys and default model
|
|
53
|
+
llm keys set openrouter
|
|
54
|
+
llm models default openrouter/meta-llama/llama-3.1-405b
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Install llmess
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pipx install llmess
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Or with pip:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install llmess
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
> **Note**: llmess calls `llm` via subprocess, so it uses whatever `llm` is on your PATH. Your plugins and configuration are preserved.
|
|
70
|
+
|
|
71
|
+
## Usage
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
llmess myfile.txt # View a file
|
|
75
|
+
llmess -m gpt-4o myfile.txt # Use a specific model
|
|
76
|
+
llmess -B myfile.txt # Base mode: no system prompt
|
|
77
|
+
cat file.txt | llmess # Read from stdin
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Options
|
|
81
|
+
|
|
82
|
+
| Flag | Description |
|
|
83
|
+
|------|-------------|
|
|
84
|
+
| `-m`, `--model` | LLM model to use (default: your `llm` default) |
|
|
85
|
+
| `-s`, `--system` | System prompt (default: instruct prompt) |
|
|
86
|
+
| `-B`, `--base` | Base model mode: no system prompt |
|
|
87
|
+
| `-S`, `--stealth` | Mimic `less` appearance exactly-ish probably |
|
|
88
|
+
| `-T`, `--max-tokens N` | Max tokens to generate per LLM call |
|
|
89
|
+
| `-C`, `--context CHARS` | Characters of context to send to LLM (default: 2000) |
|
|
90
|
+
| `-o`, `--option KEY VALUE` | Model option to pass to llm (can be repeated) |
|
|
91
|
+
| `-P`, `--prefetch [N]` | Prefetch N screens ahead in background (off by default; 2 if flag given without N) |
|
|
92
|
+
| `--real-lines N` | Show first N real lines, then generate continuations |
|
|
93
|
+
| `--real-screen` | Show first screenful of real content, then generate |
|
|
94
|
+
| `--install-prank` | Output shell function to wrap `less` with llmess |
|
|
95
|
+
| `-V`, `--version` | Show version |
|
|
96
|
+
|
|
97
|
+
### Environment Variables
|
|
98
|
+
|
|
99
|
+
| Variable | Description |
|
|
100
|
+
|----------|-------------|
|
|
101
|
+
| `LLMESS` | Default CLI flags (like `LESS` for less) |
|
|
102
|
+
| `LLMESS_MODEL` | Default model |
|
|
103
|
+
| `LLMESS_OPTIONS` | Default model options (comma-separated `key=value` pairs) |
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# In ~/.bashrc or ~/.zshrc
|
|
107
|
+
export LLMESS="-S -P" # stealth + prefetch by default
|
|
108
|
+
export LLMESS_MODEL="openrouter/meta-llama/llama-3.1-405b"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Priority: CLI flags > `LLMESS` > `LLMESS_MODEL`/`LLMESS_OPTIONS` > built-in defaults.
|
|
112
|
+
|
|
113
|
+
## Controls
|
|
114
|
+
|
|
115
|
+
| Key | Action |
|
|
116
|
+
|-----|--------|
|
|
117
|
+
| ↑ / k | Scroll up one line |
|
|
118
|
+
| ↓ / j | Scroll down one line |
|
|
119
|
+
| Page Up / b | Scroll up one page |
|
|
120
|
+
| Page Down / f / Space | Scroll down one page |
|
|
121
|
+
| g | Go to top |
|
|
122
|
+
| G | Go to bottom |
|
|
123
|
+
| / | Search forward |
|
|
124
|
+
| n | Next match |
|
|
125
|
+
| N | Previous match |
|
|
126
|
+
| Esc | Clear search |
|
|
127
|
+
| s | Save to file |
|
|
128
|
+
| q | Quit |
|
|
129
|
+
|
|
130
|
+
When you reach the bottom, scrolling down triggers LLM generation.
|
|
131
|
+
|
|
132
|
+
## Search
|
|
133
|
+
|
|
134
|
+
Press `/` to search. Matches are highlighted.
|
|
135
|
+
|
|
136
|
+
If the term isn't found, llmess generates content containing it:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
echo "Hello world" | llmess
|
|
140
|
+
# Press /password<Enter>
|
|
141
|
+
# → Generates content containing "password", jumps to match
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
This requires a system prompt (the default). With `-B` (base mode), search behaves normally.
|
|
145
|
+
|
|
146
|
+
## Base Models vs. Instruct Models
|
|
147
|
+
|
|
148
|
+
By default, llmess sends a system prompt instructing the model to continue text without commentary. This works well with instruct models and is ignored by base models.
|
|
149
|
+
|
|
150
|
+
**Base models** continue text naturally. Use `-B` to skip the system prompt:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
llmess -B -m openrouter/meta-llama/llama-3.1-405b myfile.txt
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Search-triggered generation is not available with base models since they don't follow instructions.
|
|
157
|
+
|
|
158
|
+
**Instruct models** work out of the box. Use `-s "custom prompt"` to override the default:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
llmess -s "Continue this text exactly. No commentary." myfile.txt
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Any model supported by `llm` works, including local models via Ollama.
|
|
165
|
+
|
|
166
|
+
## Modes
|
|
167
|
+
|
|
168
|
+
### Stealth Mode
|
|
169
|
+
|
|
170
|
+
With `-S`, llmess mimics the appearance of `less`:
|
|
171
|
+
- Status bar shows `filename lines 1-24 50%` format
|
|
172
|
+
- No `[GENERATING...]` indicator
|
|
173
|
+
- Shows `(END)` at bottom
|
|
174
|
+
|
|
175
|
+
### Prefetch Mode
|
|
176
|
+
|
|
177
|
+
With `-P`, llmess generates content ahead of where you're reading:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
llmess -P file.txt # Prefetch 2 screens ahead
|
|
181
|
+
llmess -P 5 file.txt # Prefetch 5 screens ahead
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Real-Then-Fake Mode
|
|
185
|
+
|
|
186
|
+
Show real file content first, then generate continuations:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
llmess --real-lines 50 ~/.bashrc # First 50 lines are real
|
|
190
|
+
llmess --real-screen config.yaml # First screenful is real
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Prank Installation
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
llmess --install-prank
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Outputs a shell function that wraps `less` with llmess. Add it to the target's shell config.
|
|
200
|
+
|
|
201
|
+
The wrapper uses stealth mode, shows real content first, prefetches in background, and falls back to real `less` for piped output.
|
|
202
|
+
|
|
203
|
+
## License
|
|
204
|
+
|
|
205
|
+
MIT
|
llmess-0.1.0/README.md
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# llmess
|
|
2
|
+
|
|
3
|
+
Some files end too early. Some files don't contain what you're looking for.
|
|
4
|
+
|
|
5
|
+
`llmess` is a `less` pager that addresses both issues:
|
|
6
|
+
|
|
7
|
+
- When you scroll past the end of a file, an LLM generates more content.
|
|
8
|
+
- When you search for a term that doesn't exist, the LLM generates content containing it.
|
|
9
|
+
|
|
10
|
+
Works with any model supported by the [`llm`](https://llm.datasette.io/) CLI.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
### Prerequisites
|
|
15
|
+
|
|
16
|
+
You need the [`llm`](https://llm.datasette.io/) CLI tool installed and configured:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Install llm
|
|
20
|
+
pipx install llm
|
|
21
|
+
|
|
22
|
+
# Install plugins for your preferred provider
|
|
23
|
+
llm install llm-openrouter # or llm-claude, llm-ollama, etc.
|
|
24
|
+
|
|
25
|
+
# Configure API keys and default model
|
|
26
|
+
llm keys set openrouter
|
|
27
|
+
llm models default openrouter/meta-llama/llama-3.1-405b
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Install llmess
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pipx install llmess
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Or with pip:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install llmess
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
> **Note**: llmess calls `llm` via subprocess, so it uses whatever `llm` is on your PATH. Your plugins and configuration are preserved.
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
llmess myfile.txt # View a file
|
|
48
|
+
llmess -m gpt-4o myfile.txt # Use a specific model
|
|
49
|
+
llmess -B myfile.txt # Base mode: no system prompt
|
|
50
|
+
cat file.txt | llmess # Read from stdin
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Options
|
|
54
|
+
|
|
55
|
+
| Flag | Description |
|
|
56
|
+
|------|-------------|
|
|
57
|
+
| `-m`, `--model` | LLM model to use (default: your `llm` default) |
|
|
58
|
+
| `-s`, `--system` | System prompt (default: instruct prompt) |
|
|
59
|
+
| `-B`, `--base` | Base model mode: no system prompt |
|
|
60
|
+
| `-S`, `--stealth` | Mimic `less` appearance exactly-ish probably |
|
|
61
|
+
| `-T`, `--max-tokens N` | Max tokens to generate per LLM call |
|
|
62
|
+
| `-C`, `--context CHARS` | Characters of context to send to LLM (default: 2000) |
|
|
63
|
+
| `-o`, `--option KEY VALUE` | Model option to pass to llm (can be repeated) |
|
|
64
|
+
| `-P`, `--prefetch [N]` | Prefetch N screens ahead in background (off by default; 2 if flag given without N) |
|
|
65
|
+
| `--real-lines N` | Show first N real lines, then generate continuations |
|
|
66
|
+
| `--real-screen` | Show first screenful of real content, then generate |
|
|
67
|
+
| `--install-prank` | Output shell function to wrap `less` with llmess |
|
|
68
|
+
| `-V`, `--version` | Show version |
|
|
69
|
+
|
|
70
|
+
### Environment Variables
|
|
71
|
+
|
|
72
|
+
| Variable | Description |
|
|
73
|
+
|----------|-------------|
|
|
74
|
+
| `LLMESS` | Default CLI flags (like `LESS` for less) |
|
|
75
|
+
| `LLMESS_MODEL` | Default model |
|
|
76
|
+
| `LLMESS_OPTIONS` | Default model options (comma-separated `key=value` pairs) |
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# In ~/.bashrc or ~/.zshrc
|
|
80
|
+
export LLMESS="-S -P" # stealth + prefetch by default
|
|
81
|
+
export LLMESS_MODEL="openrouter/meta-llama/llama-3.1-405b"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Priority: CLI flags > `LLMESS` > `LLMESS_MODEL`/`LLMESS_OPTIONS` > built-in defaults.
|
|
85
|
+
|
|
86
|
+
## Controls
|
|
87
|
+
|
|
88
|
+
| Key | Action |
|
|
89
|
+
|-----|--------|
|
|
90
|
+
| ↑ / k | Scroll up one line |
|
|
91
|
+
| ↓ / j | Scroll down one line |
|
|
92
|
+
| Page Up / b | Scroll up one page |
|
|
93
|
+
| Page Down / f / Space | Scroll down one page |
|
|
94
|
+
| g | Go to top |
|
|
95
|
+
| G | Go to bottom |
|
|
96
|
+
| / | Search forward |
|
|
97
|
+
| n | Next match |
|
|
98
|
+
| N | Previous match |
|
|
99
|
+
| Esc | Clear search |
|
|
100
|
+
| s | Save to file |
|
|
101
|
+
| q | Quit |
|
|
102
|
+
|
|
103
|
+
When you reach the bottom, scrolling down triggers LLM generation.
|
|
104
|
+
|
|
105
|
+
## Search
|
|
106
|
+
|
|
107
|
+
Press `/` to search. Matches are highlighted.
|
|
108
|
+
|
|
109
|
+
If the term isn't found, llmess generates content containing it:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
echo "Hello world" | llmess
|
|
113
|
+
# Press /password<Enter>
|
|
114
|
+
# → Generates content containing "password", jumps to match
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
This requires a system prompt (the default). With `-B` (base mode), search behaves normally.
|
|
118
|
+
|
|
119
|
+
## Base Models vs. Instruct Models
|
|
120
|
+
|
|
121
|
+
By default, llmess sends a system prompt instructing the model to continue text without commentary. This works well with instruct models and is ignored by base models.
|
|
122
|
+
|
|
123
|
+
**Base models** continue text naturally. Use `-B` to skip the system prompt:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
llmess -B -m openrouter/meta-llama/llama-3.1-405b myfile.txt
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Search-triggered generation is not available with base models since they don't follow instructions.
|
|
130
|
+
|
|
131
|
+
**Instruct models** work out of the box. Use `-s "custom prompt"` to override the default:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
llmess -s "Continue this text exactly. No commentary." myfile.txt
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Any model supported by `llm` works, including local models via Ollama.
|
|
138
|
+
|
|
139
|
+
## Modes
|
|
140
|
+
|
|
141
|
+
### Stealth Mode
|
|
142
|
+
|
|
143
|
+
With `-S`, llmess mimics the appearance of `less`:
|
|
144
|
+
- Status bar shows `filename lines 1-24 50%` format
|
|
145
|
+
- No `[GENERATING...]` indicator
|
|
146
|
+
- Shows `(END)` at bottom
|
|
147
|
+
|
|
148
|
+
### Prefetch Mode
|
|
149
|
+
|
|
150
|
+
With `-P`, llmess generates content ahead of where you're reading:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
llmess -P file.txt # Prefetch 2 screens ahead
|
|
154
|
+
llmess -P 5 file.txt # Prefetch 5 screens ahead
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Real-Then-Fake Mode
|
|
158
|
+
|
|
159
|
+
Show real file content first, then generate continuations:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
llmess --real-lines 50 ~/.bashrc # First 50 lines are real
|
|
163
|
+
llmess --real-screen config.yaml # First screenful is real
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Prank Installation
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
llmess --install-prank
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Outputs a shell function that wraps `less` with llmess. Add it to the target's shell config.
|
|
173
|
+
|
|
174
|
+
The wrapper uses stealth mode, shows real content first, prefetches in background, and falls back to real `less` for piped output.
|
|
175
|
+
|
|
176
|
+
## License
|
|
177
|
+
|
|
178
|
+
MIT
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "llmess"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A less pager that uses LLMs to hallucinate infinite file continuations"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "tgies" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["llm", "pager", "less", "cli", "humor"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Environment :: Console :: Curses",
|
|
20
|
+
"Intended Audience :: Developers",
|
|
21
|
+
"License :: OSI Approved :: MIT License",
|
|
22
|
+
"Operating System :: POSIX",
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Programming Language :: Python :: 3.8",
|
|
25
|
+
"Programming Language :: Python :: 3.9",
|
|
26
|
+
"Programming Language :: Python :: 3.10",
|
|
27
|
+
"Programming Language :: Python :: 3.11",
|
|
28
|
+
"Programming Language :: Python :: 3.12",
|
|
29
|
+
"Topic :: Text Processing",
|
|
30
|
+
"Topic :: Games/Entertainment",
|
|
31
|
+
]
|
|
32
|
+
dependencies = [
|
|
33
|
+
# Note: llm is NOT listed here intentionally.
|
|
34
|
+
# llmess calls llm via subprocess and expects users to have it
|
|
35
|
+
# installed at user level (pipx, etc.) with their plugins configured.
|
|
36
|
+
# Bundling llm would shadow the user's configured installation.
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[project.scripts]
|
|
40
|
+
llmess = "llmess.cli:main"
|
|
41
|
+
|
|
42
|
+
[project.urls]
|
|
43
|
+
Homepage = "https://github.com/tgies/llmess"
|
|
44
|
+
Repository = "https://github.com/tgies/llmess"
|
|
45
|
+
|
|
46
|
+
[tool.ruff]
|
|
47
|
+
target-version = "py38"
|
|
48
|
+
line-length = 100
|
|
49
|
+
|
|
50
|
+
[tool.ruff.lint]
|
|
51
|
+
select = [
|
|
52
|
+
"E", # pycodestyle errors
|
|
53
|
+
"F", # pyflakes
|
|
54
|
+
"I", # isort
|
|
55
|
+
"UP", # pyupgrade
|
|
56
|
+
]
|