tui-input 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.
@@ -0,0 +1,97 @@
1
+ name: Bug Report
2
+ description: Report a bug or unexpected behavior
3
+ title: "[Bug]: "
4
+ labels: ["bug"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for reporting a bug! Please fill in as much detail as possible.
10
+
11
+ - type: input
12
+ id: os
13
+ attributes:
14
+ label: Operating System
15
+ placeholder: "e.g., macOS 14.2, Ubuntu 24.04"
16
+ validations:
17
+ required: true
18
+
19
+ - type: input
20
+ id: terminal
21
+ attributes:
22
+ label: Terminal Emulator
23
+ placeholder: "e.g., iTerm2, Alacritty, WezTerm, Terminal.app"
24
+ validations:
25
+ required: true
26
+
27
+ - type: input
28
+ id: tmux-version
29
+ attributes:
30
+ label: tmux Version
31
+ description: "Output of `tmux -V`"
32
+ placeholder: "e.g., tmux 3.4"
33
+ validations:
34
+ required: true
35
+
36
+ - type: input
37
+ id: python-version
38
+ attributes:
39
+ label: Python Version
40
+ description: "Output of `python3 --version`"
41
+ placeholder: "e.g., Python 3.12.1"
42
+ validations:
43
+ required: true
44
+
45
+ - type: input
46
+ id: tui-input-version
47
+ attributes:
48
+ label: tui-input Version
49
+ description: "Output of `tui-input --version`"
50
+ placeholder: "e.g., tui-input 0.1.0"
51
+ validations:
52
+ required: true
53
+
54
+ - type: textarea
55
+ id: description
56
+ attributes:
57
+ label: Description
58
+ description: A clear description of what the bug is.
59
+ validations:
60
+ required: true
61
+
62
+ - type: textarea
63
+ id: steps
64
+ attributes:
65
+ label: Steps to Reproduce
66
+ description: How to reproduce the behavior.
67
+ value: |
68
+ 1. Run `tui-input ...`
69
+ 2. Type '...'
70
+ 3. Press ...
71
+ 4. See error
72
+ validations:
73
+ required: true
74
+
75
+ - type: textarea
76
+ id: expected
77
+ attributes:
78
+ label: Expected Behavior
79
+ description: What you expected to happen.
80
+ validations:
81
+ required: true
82
+
83
+ - type: textarea
84
+ id: actual
85
+ attributes:
86
+ label: Actual Behavior
87
+ description: What actually happened.
88
+ validations:
89
+ required: true
90
+
91
+ - type: textarea
92
+ id: logs
93
+ attributes:
94
+ label: Logs / Screenshots
95
+ description: Any relevant logs or screenshots.
96
+ validations:
97
+ required: false
@@ -0,0 +1,41 @@
1
+ name: Feature Request
2
+ description: Suggest a new feature or improvement
3
+ title: "[Feature]: "
4
+ labels: ["enhancement"]
5
+ body:
6
+ - type: markdown
7
+ attributes:
8
+ value: |
9
+ Thanks for the suggestion! Please describe the feature you'd like to see.
10
+
11
+ - type: textarea
12
+ id: problem
13
+ attributes:
14
+ label: Problem
15
+ description: What problem does this feature solve? What's the current limitation?
16
+ validations:
17
+ required: true
18
+
19
+ - type: textarea
20
+ id: solution
21
+ attributes:
22
+ label: Proposed Solution
23
+ description: How would you like this to work?
24
+ validations:
25
+ required: true
26
+
27
+ - type: textarea
28
+ id: alternatives
29
+ attributes:
30
+ label: Alternatives Considered
31
+ description: Any alternative solutions or workarounds you've considered.
32
+ validations:
33
+ required: false
34
+
35
+ - type: textarea
36
+ id: context
37
+ attributes:
38
+ label: Additional Context
39
+ description: Any other context, screenshots, or references.
40
+ validations:
41
+ required: false
@@ -0,0 +1,24 @@
1
+ ## Summary
2
+
3
+ <!-- Brief description of what this PR does and why -->
4
+
5
+ ## Changes
6
+
7
+ <!-- Bulleted list of key changes -->
8
+
9
+ -
10
+
11
+ ## Test Plan
12
+
13
+ <!-- How to verify these changes work -->
14
+
15
+ - [ ] `uv run pytest` passes
16
+ - [ ] `uv run ruff check src/ tests/` passes
17
+ - [ ] `uv run mypy src/` passes
18
+ - [ ] Manual testing in tmux (if applicable)
19
+
20
+ ## Checklist
21
+
22
+ - [ ] Tests added/updated for new functionality
23
+ - [ ] Documentation updated (if applicable)
24
+ - [ ] CHANGELOG.md updated (if user-facing change)
@@ -0,0 +1,32 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: astral-sh/setup-uv@v4
15
+ - run: uv sync
16
+ - run: uv run ruff check src/ tests/
17
+ - run: uv run ruff format --check src/ tests/
18
+ - run: uv run mypy src/
19
+
20
+ test:
21
+ runs-on: ${{ matrix.os }}
22
+ strategy:
23
+ matrix:
24
+ os: [ubuntu-latest, macos-latest]
25
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: astral-sh/setup-uv@v4
29
+ with:
30
+ python-version: ${{ matrix.python-version }}
31
+ - run: uv sync
32
+ - run: uv run pytest -v
@@ -0,0 +1,53 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ contents: write
10
+ id-token: write
11
+
12
+ jobs:
13
+ build:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: astral-sh/setup-uv@v4
18
+ - run: uv build
19
+ - uses: actions/upload-artifact@v4
20
+ with:
21
+ name: dist
22
+ path: dist/
23
+
24
+ pypi:
25
+ needs: build
26
+ runs-on: ubuntu-latest
27
+ environment:
28
+ name: pypi
29
+ url: https://pypi.org/p/tui-input
30
+ permissions:
31
+ id-token: write
32
+ steps:
33
+ - uses: actions/download-artifact@v4
34
+ with:
35
+ name: dist
36
+ path: dist/
37
+ - uses: pypa/gh-action-pypi-publish@release/v1
38
+
39
+ github-release:
40
+ needs: build
41
+ runs-on: ubuntu-latest
42
+ permissions:
43
+ contents: write
44
+ steps:
45
+ - uses: actions/checkout@v4
46
+ - uses: actions/download-artifact@v4
47
+ with:
48
+ name: dist
49
+ path: dist/
50
+ - uses: softprops/action-gh-release@v2
51
+ with:
52
+ files: dist/*
53
+ generate_release_notes: true
@@ -0,0 +1,39 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ *.egg
7
+ *.egg-info/
8
+ .eggs/
9
+ dist/
10
+ build/
11
+
12
+ # Virtual environments
13
+ .venv/
14
+ venv/
15
+
16
+ # Tool caches
17
+ .mypy_cache/
18
+ .ruff_cache/
19
+ .pytest_cache/
20
+ .coverage
21
+ htmlcov/
22
+
23
+ # Environment / secrets
24
+ .env
25
+ .env.*
26
+
27
+ # OS
28
+ .DS_Store
29
+ Thumbs.db
30
+
31
+ # IDE
32
+ .idea/
33
+ .vscode/
34
+ *.swp
35
+ *.swo
36
+ *~
37
+
38
+ # Debug logs
39
+ /tmp/tui-input-*.log
@@ -0,0 +1,25 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-03-14
11
+
12
+ ### Added
13
+
14
+ - Initial release
15
+ - Tmux-based split pane with companion input bar
16
+ - Multi-line input with auto-resizing (3-10 lines)
17
+ - Bracketed paste for safe text transfer
18
+ - JSON-based input history with up/down navigation
19
+ - Agent-agnostic design (works with any terminal command)
20
+ - Auto-cleanup when the target pane exits
21
+ - One-liner install script with agent detection and alias registration
22
+ - Key bindings: Enter (send), Shift+Enter (newline), Esc (clear), arrows (history)
23
+
24
+ [Unreleased]: https://github.com/maked-dev/tui-input/compare/v0.1.0...HEAD
25
+ [0.1.0]: https://github.com/maked-dev/tui-input/releases/tag/v0.1.0
@@ -0,0 +1,43 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code when working with this repository.
4
+
5
+ ## Build & Test Commands
6
+
7
+ ```bash
8
+ uv run pytest tests/ -v # Run all tests
9
+ uv run pytest tests/ -v --cov # Run with coverage
10
+ uv run ruff check src/ tests/ # Lint
11
+ uv run ruff format src/ tests/ # Format
12
+ uv run mypy src/ # Type check
13
+ ```
14
+
15
+ ## Architecture
16
+
17
+ ```
18
+ cli.py CLI entry point (argparse, dispatches to internal modes)
19
+
20
+ launcher.py Tmux environment setup (split pane, launch companion + agent)
21
+
22
+ companion.py Textual app — input bar widget with key forwarding
23
+
24
+ tmux.py Low-level tmux operations (pane queries, text pasting, hooks)
25
+ history.py JSON-based persistent input history
26
+ ```
27
+
28
+ ### Key Design Decisions
29
+
30
+ - **Companion pane ID via `TMUX_PANE` env var**: `tmux display-message -p` returns the *selected* pane, not the pane the process runs in. Always use `os.environ.get("TMUX_PANE")` for the companion's own pane ID.
31
+ - **Shell vs Direct mode**: Inside tmux, the pane runs a shell that spawns the agent. Outside tmux, the pane runs the agent directly. `_check_target_alive` uses `_is_shell()` to pick the right exit detection strategy.
32
+ - **IME deferred actions**: Enter/Shift+Enter handlers use a 50ms timer to let terminal IME settle before acting. Terminal IME composition characters are NOT sent to the app — they exist only in the terminal's overlay.
33
+ - **Separate paste + Enter**: `submit_to_pane` uses `paste-buffer` for text and `send-keys Enter` separately, so the target app reliably treats Enter as submit.
34
+ - **Hook commands wrapped in `run-shell`**: tmux hooks expect tmux commands, not shell commands. Shell commands must be wrapped in `run-shell '...'`.
35
+ - **Dynamic pane addressing**: Never use hardcoded pane indices (`.0`). Use `list-panes -F '#{pane_id}'` to handle any `pane-base-index` setting.
36
+
37
+ ## Conventions
38
+
39
+ - Language: code identifiers in English, comments/docs in English
40
+ - All modules use `from __future__ import annotations`
41
+ - Type hints on all function signatures; `mypy --strict` must pass
42
+ - `contextlib.suppress(subprocess.CalledProcessError)` over bare `except Exception`
43
+ - Constants at module level, no magic numbers in logic
@@ -0,0 +1,79 @@
1
+ # Contributing to tui-input
2
+
3
+ Thanks for your interest in contributing! This guide will help you get started.
4
+
5
+ ## Development Setup
6
+
7
+ 1. **Clone the repository:**
8
+ ```bash
9
+ git clone https://github.com/maked-dev/tui-input.git
10
+ cd tui-input
11
+ ```
12
+
13
+ 2. **Install dependencies** (using [uv](https://github.com/astral-sh/uv)):
14
+ ```bash
15
+ uv sync
16
+ ```
17
+
18
+ 3. **Verify your setup:**
19
+ ```bash
20
+ uv run pytest
21
+ uv run ruff check src/ tests/
22
+ uv run mypy src/
23
+ ```
24
+
25
+ ## Code Style
26
+
27
+ - **Formatter/Linter:** [Ruff](https://github.com/astral-sh/ruff) — configured in `pyproject.toml`
28
+ - **Type checking:** [mypy](https://mypy-lang.org/) in strict mode
29
+ - **Line length:** 100 characters
30
+ - **Python version:** 3.10+ (use `from __future__ import annotations` in all modules)
31
+
32
+ Run before committing:
33
+
34
+ ```bash
35
+ uv run ruff check --fix src/ tests/
36
+ uv run ruff format src/ tests/
37
+ uv run mypy src/
38
+ ```
39
+
40
+ ## Testing
41
+
42
+ - Tests live in `tests/`
43
+ - Use [pytest](https://pytest.org/) with [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) for async tests
44
+ - Textual apps are tested using [Textual's pilot API](https://textual.textualize.io/guide/testing/)
45
+ - All tmux calls should be mocked — tests must not require tmux to be installed
46
+
47
+ ```bash
48
+ uv run pytest # Run all tests
49
+ uv run pytest -x # Stop on first failure
50
+ uv run pytest -v # Verbose output
51
+ uv run pytest tests/test_history.py # Run a specific test file
52
+ ```
53
+
54
+ ## Pull Request Process
55
+
56
+ 1. Fork the repo and create a feature branch from `main`
57
+ 2. Write tests for any new functionality
58
+ 3. Ensure all checks pass: `ruff check`, `ruff format --check`, `mypy`, `pytest`
59
+ 4. Write a clear PR description explaining **what** and **why**
60
+ 5. Keep PRs focused — one feature or fix per PR
61
+
62
+ ## Commit Messages
63
+
64
+ - Use present tense ("Add feature" not "Added feature")
65
+ - Keep the first line under 72 characters
66
+ - Reference issues when applicable (e.g., "Fix #42")
67
+
68
+ ## Reporting Bugs
69
+
70
+ Use the [bug report template](https://github.com/maked-dev/tui-input/issues/new?template=bug_report.yml) and include:
71
+
72
+ - OS and terminal emulator
73
+ - tmux version (`tmux -V`)
74
+ - Python version (`python3 --version`)
75
+ - Steps to reproduce
76
+
77
+ ## Feature Requests
78
+
79
+ Use the [feature request template](https://github.com/maked-dev/tui-input/issues/new?template=feature_request.yml).
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 maked-dev
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.
@@ -0,0 +1,158 @@
1
+ Metadata-Version: 2.4
2
+ Name: tui-input
3
+ Version: 0.1.0
4
+ Summary: A terminal companion that pins a persistent input bar at the bottom of your tmux pane, so you can scroll freely through long TUI agent output while composing your response.
5
+ Project-URL: Homepage, https://github.com/maked-dev/tui-input
6
+ Project-URL: Repository, https://github.com/maked-dev/tui-input
7
+ Project-URL: Issues, https://github.com/maked-dev/tui-input/issues
8
+ Project-URL: Changelog, https://github.com/maked-dev/tui-input/blob/main/CHANGELOG.md
9
+ Author: maked-dev
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: agent,claude,codex,input,terminal,tmux,tui
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Terminals
22
+ Classifier: Topic :: Utilities
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: textual>=0.85.0
25
+ Description-Content-Type: text/markdown
26
+
27
+ # tui-input
28
+
29
+ [![CI](https://github.com/maked-dev/tui-input/actions/workflows/ci.yml/badge.svg)](https://github.com/maked-dev/tui-input/actions/workflows/ci.yml)
30
+ [![PyPI](https://img.shields.io/pypi/v/tui-input)](https://pypi.org/project/tui-input/)
31
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
32
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
33
+
34
+ A terminal companion that pins a persistent input bar at the bottom of your tmux pane. Scroll freely through long TUI agent output while composing your response.
35
+
36
+ <!-- TODO: demo GIF -->
37
+ <!-- ![demo](https://github.com/maked-dev/tui-input/assets/demo.gif) -->
38
+
39
+ ## The Problem
40
+
41
+ When using TUI-based AI agents (Claude Code, Codex CLI, etc.), long outputs force you to scroll up to read, then scroll back down to type. You end up:
42
+
43
+ - Losing your place in the output
44
+ - Writing responses in a separate editor, then copy-pasting
45
+ - Fighting the terminal scroll position
46
+
47
+ ## The Solution
48
+
49
+ `tui-input` splits your terminal into two panes:
50
+
51
+ ```
52
+ ┌─────────────────────────────────────┐
53
+ │ Top pane (Claude Code / Codex etc) │
54
+ │ Scroll freely through long output │
55
+ ├─────────────────────────────────────┤ ← 3-10 lines, auto-resizing
56
+ │ Type your response here... │
57
+ │ Enter to send · Shift+Enter: newline│
58
+ └─────────────────────────────────────┘
59
+ ```
60
+
61
+ ## Features
62
+
63
+ - **Pinned input bar** — always visible at the bottom, regardless of scroll position
64
+ - **Auto-resize** — companion grows from 3 to 10 lines as you type multi-line input
65
+ - **Bracketed paste** — safe multi-line text transfer via tmux buffers
66
+ - **Input history** — press `↑`/`↓` to recall previous inputs (persisted across sessions)
67
+ - **Agent-agnostic** — works with any terminal program, not just AI agents
68
+ - **Auto-cleanup** — companion exits when the agent exits
69
+
70
+ ## Installation
71
+
72
+ ### Requirements
73
+
74
+ - Python 3.10+
75
+ - tmux
76
+
77
+ ### Install via pip/uv
78
+
79
+ ```bash
80
+ # Using uv (recommended)
81
+ uv tool install tui-input
82
+
83
+ # Using pip
84
+ pip install tui-input
85
+ ```
86
+
87
+ ### One-liner (auto-detects agents + registers aliases)
88
+
89
+ ```bash
90
+ curl -fsSL https://raw.githubusercontent.com/maked-dev/tui-input/main/install.sh | bash
91
+ ```
92
+
93
+ This will:
94
+ 1. Install `tui-input`
95
+ 2. Detect installed agents (claude, codex, etc.)
96
+ 3. Register shell aliases so you can just type `claude` instead of `tui-input claude`
97
+
98
+ To uninstall aliases:
99
+
100
+ ```bash
101
+ curl -fsSL https://raw.githubusercontent.com/maked-dev/tui-input/main/install.sh | bash -s -- --uninstall
102
+ ```
103
+
104
+ ## Usage
105
+
106
+ ```bash
107
+ # Basic usage
108
+ tui-input claude
109
+
110
+ # Any command works
111
+ tui-input "vim file.py"
112
+ tui-input htop
113
+
114
+ # With aliases installed (via install.sh), just type the agent name
115
+ claude
116
+ codex
117
+ ```
118
+
119
+ ### Key Bindings
120
+
121
+ | Key | Action |
122
+ |-----|--------|
123
+ | `Enter` | Send text to top pane + clear input |
124
+ | `Shift+Enter` | Insert newline (multi-line input) |
125
+ | `↑` (on empty) | Previous history entry |
126
+ | `↓` (on empty) | Next history entry |
127
+ | `Esc` | Clear all input |
128
+
129
+ ### How It Works
130
+
131
+ 1. `tui-input` creates a tmux vertical split (or a new session if not in tmux)
132
+ 2. Your command runs in the top pane
133
+ 3. A Textual-based companion widget runs in the bottom pane
134
+ 4. Press `Enter` to send text to the top pane via `tmux paste-buffer`
135
+ 5. When the top pane command exits, the companion auto-exits
136
+
137
+ ## Development
138
+
139
+ ```bash
140
+ # Clone and install
141
+ git clone https://github.com/maked-dev/tui-input.git
142
+ cd tui-input
143
+ uv sync
144
+
145
+ # Run tests
146
+ uv run pytest
147
+
148
+ # Lint and format
149
+ uv run ruff check src/ tests/
150
+ uv run ruff format --check src/ tests/
151
+
152
+ # Type check
153
+ uv run mypy src/
154
+ ```
155
+
156
+ ## License
157
+
158
+ [MIT](LICENSE)