claude-launcher 0.1.0__py3-none-any.whl

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,79 @@
1
+ """Logging configuration for claude-launcher."""
2
+
3
+ import logging
4
+ import sys
5
+ from pathlib import Path
6
+ from typing import Optional
7
+
8
+ from platformdirs import user_log_path
9
+
10
+
11
+ def setup_logging(
12
+ level: str = "INFO",
13
+ log_file: Optional[Path] = None,
14
+ verbose: bool = False,
15
+ ) -> logging.Logger:
16
+ """Configure logging for claude-launcher.
17
+
18
+ Args:
19
+ level: Logging level (DEBUG, INFO, WARNING, ERROR)
20
+ log_file: Optional path to log file
21
+ verbose: If True, set level to DEBUG
22
+
23
+ Returns:
24
+ Configured logger instance
25
+ """
26
+ # Create logger
27
+ logger = logging.getLogger("claude_launcher")
28
+
29
+ # Set level
30
+ if verbose:
31
+ logger.setLevel(logging.DEBUG)
32
+ else:
33
+ logger.setLevel(getattr(logging, level.upper(), logging.INFO))
34
+
35
+ # Clear existing handlers
36
+ logger.handlers.clear()
37
+
38
+ # Console handler (stderr)
39
+ console_handler = logging.StreamHandler(sys.stderr)
40
+ console_handler.setLevel(logging.WARNING) # Only warnings and errors to console
41
+ console_formatter = logging.Formatter("%(levelname)s: %(message)s")
42
+ console_handler.setFormatter(console_formatter)
43
+ logger.addHandler(console_handler)
44
+
45
+ # File handler (if log file specified or in debug mode)
46
+ if log_file or verbose:
47
+ if log_file is None:
48
+ log_dir = user_log_path("claude-launcher")
49
+ log_dir.mkdir(parents=True, exist_ok=True)
50
+ log_file = log_dir / "claude-launcher.log"
51
+
52
+ file_handler = logging.FileHandler(log_file)
53
+ file_handler.setLevel(logging.DEBUG)
54
+ file_formatter = logging.Formatter(
55
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
56
+ datefmt="%Y-%m-%d %H:%M:%S",
57
+ )
58
+ file_handler.setFormatter(file_formatter)
59
+ logger.addHandler(file_handler)
60
+
61
+ if verbose:
62
+ logger.info(f"Logging to file: {log_file}")
63
+
64
+ # Don't propagate to root logger
65
+ logger.propagate = False
66
+
67
+ return logger
68
+
69
+
70
+ def get_logger(name: str = "claude_launcher") -> logging.Logger:
71
+ """Get logger instance.
72
+
73
+ Args:
74
+ name: Logger name (default: claude_launcher)
75
+
76
+ Returns:
77
+ Logger instance
78
+ """
79
+ return logging.getLogger(name)
@@ -0,0 +1,61 @@
1
+ """Path utilities for claude-launcher."""
2
+
3
+ import os
4
+ from pathlib import Path
5
+
6
+
7
+ def expand_path(path_str: str) -> Path:
8
+ """Expand path with ~ and environment variables.
9
+
10
+ Args:
11
+ path_str: Path string to expand
12
+
13
+ Returns:
14
+ Expanded Path object
15
+
16
+ Examples:
17
+ >>> expand_path("~/projects")
18
+ Path('/home/user/projects')
19
+
20
+ >>> expand_path("$HOME/work")
21
+ Path('/home/user/work')
22
+ """
23
+ # Expand environment variables
24
+ expanded = os.path.expandvars(path_str)
25
+ # Expand ~ to home directory
26
+ return Path(expanded).expanduser().resolve()
27
+
28
+
29
+ def validate_directory(path: Path) -> bool:
30
+ """Check if a path exists and is a directory.
31
+
32
+ Args:
33
+ path: Path to validate
34
+
35
+ Returns:
36
+ True if path exists and is a directory, False otherwise
37
+ """
38
+ return path.exists() and path.is_dir()
39
+
40
+
41
+ def get_relative_path(path: Path, base: Path) -> Path:
42
+ """Get relative path from base, or return path if not relative.
43
+
44
+ Args:
45
+ path: Path to make relative
46
+ base: Base path
47
+
48
+ Returns:
49
+ Relative path if possible, otherwise original path
50
+
51
+ Examples:
52
+ >>> get_relative_path(Path("/home/user/projects/foo"), Path("/home/user"))
53
+ Path('projects/foo')
54
+
55
+ >>> get_relative_path(Path("/other/path"), Path("/home/user"))
56
+ Path('/other/path')
57
+ """
58
+ try:
59
+ return path.relative_to(base)
60
+ except ValueError:
61
+ return path
@@ -0,0 +1,332 @@
1
+ Metadata-Version: 2.4
2
+ Name: claude-launcher
3
+ Version: 0.1.0
4
+ Summary: Fast context switching for Claude Code in multi-project environments
5
+ Author: Solent Labs™
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/solentlabs/claude-launcher
8
+ Project-URL: Repository, https://github.com/solentlabs/claude-launcher
9
+ Project-URL: Issues, https://github.com/solentlabs/claude-launcher/issues
10
+ Keywords: claude,launcher,project-switcher,productivity,cli
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Operating System :: OS Independent
21
+ Classifier: Topic :: Software Development
22
+ Classifier: Topic :: Utilities
23
+ Requires-Python: >=3.8
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: iterfzf>=1.4.0
27
+ Requires-Dist: typer>=0.12.0
28
+ Requires-Dist: platformdirs>=4.0.0
29
+ Requires-Dist: tomli>=2.0.0; python_version < "3.11"
30
+ Requires-Dist: tomli-w>=1.0.0
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
33
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
34
+ Requires-Dist: black>=23.0.0; extra == "dev"
35
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
36
+ Requires-Dist: flake8>=6.0.0; extra == "dev"
37
+ Requires-Dist: isort>=5.12.0; extra == "dev"
38
+ Requires-Dist: pre-commit>=3.0.0; extra == "dev"
39
+ Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
40
+ Dynamic: license-file
41
+
42
+ # Claude Launcher
43
+
44
+ Fast context switching for Claude Code in multi-project environments.
45
+
46
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
47
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
48
+
49
+ > **Community Project** - This is an independent tool built by the community, not affiliated with Anthropic.
50
+
51
+ ## Overview
52
+
53
+ Claude Launcher is a productivity tool for developers working with multiple Claude Code projects. It provides fast project discovery, tree-structured navigation, and intelligent context switching with an interactive fuzzy-search interface powered by fzf.
54
+
55
+ ## Features
56
+
57
+ - 🔍 **Auto-discovery** - Automatically finds git repositories in configured directories
58
+ - 📋 **Alphabetical organization** - Projects sorted by path for easy navigation
59
+ - ⚡ **Smart defaults** - Cursor starts on your last opened project
60
+ - 🔎 **Fuzzy search** - Interactive project selection powered by fzf
61
+ - 📄 **Rich previews** - Shows CLAUDE.md, git status, and directory contents
62
+ - 🎯 **Manual paths** - Add non-git projects manually
63
+ - 🔄 **Git clone integration** - Clone and launch repositories directly
64
+ - 🛡️ **Error recovery** - Automatic database corruption recovery
65
+ - 🖥️ **Cross-platform** - Works on Linux, macOS, and Windows
66
+
67
+ ## Installation
68
+
69
+ ### From PyPI (Recommended)
70
+ ```bash
71
+ pip install claude-launcher
72
+ ```
73
+
74
+ ### From Source (Development)
75
+ ```bash
76
+ git clone https://github.com/solentlabs/claude-launcher.git
77
+ cd claude-launcher
78
+ pip install -e .
79
+ ```
80
+
81
+ ### With Development Dependencies
82
+ ```bash
83
+ pip install -e ".[dev]"
84
+ ```
85
+
86
+ ## Quick Start
87
+
88
+ ### Initial Setup
89
+ Run the first-time setup wizard to configure scan directories:
90
+
91
+ ```bash
92
+ claude-launcher --setup
93
+ ```
94
+
95
+ You'll be prompted to enter directories to scan for projects (e.g., `~/projects`, `~/work`).
96
+
97
+ ### Basic Usage
98
+
99
+ ```bash
100
+ # Launch interactive project selector
101
+ claude-launcher
102
+
103
+ # Jump directly to last opened project
104
+ claude-launcher --recent
105
+
106
+ # List all discovered projects
107
+ claude-launcher --list
108
+ ```
109
+
110
+ ### Managing Projects
111
+
112
+ ```bash
113
+ # Add a manual project path
114
+ claude-launcher --add
115
+
116
+ # Remove a manual path
117
+ claude-launcher --remove
118
+
119
+ # Clone a git repository
120
+ claude-launcher --clone
121
+ ```
122
+
123
+ ## Commands
124
+
125
+ | Command | Description |
126
+ |---------|-------------|
127
+ | `claude-launcher` | Launch interactive project selector |
128
+ | `claude-launcher --setup` | Run first-time setup or reconfigure |
129
+ | `claude-launcher --add` | Add a manual project path via directory browser |
130
+ | `claude-launcher --remove` | Remove a manual path |
131
+ | `claude-launcher --list` | List all discovered projects |
132
+ | `claude-launcher --recent` | Jump to last opened project |
133
+ | `claude-launcher --clone` | Clone a git repository |
134
+
135
+ ## Configuration
136
+
137
+ Configuration files are stored in platform-specific locations:
138
+
139
+ - **Linux/WSL:** `~/.config/claude-launcher/config.toml`
140
+ - **macOS:** `~/Library/Application Support/claude-launcher/config.toml`
141
+ - **Windows:** `%LOCALAPPDATA%\claude-launcher\config.toml`
142
+
143
+ ### Configuration Options
144
+
145
+ ```toml
146
+ [scan]
147
+ # Directories to scan for git repositories
148
+ paths = [
149
+ "~/projects",
150
+ "~/work",
151
+ "/mnt/c/Users/username/dev", # WSL example
152
+ ]
153
+
154
+ # Maximum directory depth to scan
155
+ max_depth = 5
156
+
157
+ # Directories to skip during scanning
158
+ prune_dirs = [
159
+ "node_modules",
160
+ ".cache",
161
+ "venv",
162
+ "__pycache__",
163
+ ".git",
164
+ ]
165
+
166
+ [ui]
167
+ # Preview pane width (characters)
168
+ preview_width = 70
169
+
170
+ # Show git status in preview
171
+ show_git_status = true
172
+
173
+ [history]
174
+ # Maximum access history entries to keep
175
+ max_entries = 50
176
+ ```
177
+
178
+ ### Path Expansion
179
+
180
+ Paths in configuration support:
181
+ - Tilde expansion: `~/projects` → `/home/user/projects`
182
+ - Environment variables: `$HOME/projects` → `/home/user/projects`
183
+
184
+ ## Data Storage
185
+
186
+ Project data (manual paths, history) is stored in SQLite:
187
+
188
+ - **Linux/WSL:** `~/.local/share/claude-launcher/projects.db`
189
+ - **macOS:** `~/Library/Application Support/claude-launcher/projects.db`
190
+ - **Windows:** `%LOCALAPPDATA%\claude-launcher\projects.db`
191
+
192
+ ## How It Works
193
+
194
+ 1. **Discovery**: Scans configured directories for `.git` folders
195
+ 2. **Manual Paths**: Combines discovered repos with manually added paths
196
+ 3. **Sorting**: Sorts all projects alphabetically by path
197
+ 4. **Selection**: Shows fuzzy-searchable list with preview pane
198
+ 5. **Default Cursor**: Positions cursor on last opened project
199
+ 6. **Launch**: Changes to selected directory and executes `claude` command
200
+ 7. **Tracking**: Records selection for next session
201
+
202
+ ## Preview Pane
203
+
204
+ The preview pane shows:
205
+
206
+ 1. **CLAUDE.md** (first 20 lines) - Project-specific Claude Code instructions
207
+ 2. **Git Status** - Current working tree status (if git repo)
208
+ 3. **Directory Listing** - Top-level files and folders
209
+
210
+ ## Windows Terminal Integration
211
+
212
+ Add to your Windows Terminal `settings.json`:
213
+
214
+ ```json
215
+ {
216
+ "name": "Claude Launcher",
217
+ "commandline": "wsl.exe -d Ubuntu -- bash -lic claude-launcher",
218
+ "icon": "📂"
219
+ }
220
+ ```
221
+
222
+ ## Error Handling
223
+
224
+ Claude Launcher includes robust error recovery:
225
+
226
+ - **Database corruption**: Automatically backs up and recreates
227
+ - **Missing manual paths**: Auto-removes from database
228
+ - **Invalid config**: Falls back to sensible defaults
229
+ - **Git failures**: Gracefully degrades (shows project without status)
230
+ - **Permission errors**: Logs and continues scanning
231
+
232
+ ## Development
233
+
234
+ ### Running Tests
235
+
236
+ ```bash
237
+ # Run all tests
238
+ pytest
239
+
240
+ # Run with coverage
241
+ pytest --cov=claude_launcher --cov-report=term-missing
242
+
243
+ # Run specific test file
244
+ pytest tests/test_discovery.py
245
+
246
+ # Run with verbose output
247
+ pytest -v
248
+ ```
249
+
250
+ ### Code Quality
251
+
252
+ ```bash
253
+ # Format code
254
+ black src/ tests/
255
+
256
+ # Type checking
257
+ mypy src/
258
+
259
+ # Lint
260
+ flake8 src/ tests/
261
+ ```
262
+
263
+ ### Project Structure
264
+
265
+ ```
266
+ claude-workflow/
267
+ ├── src/claude_launcher/
268
+ │ ├── core/ # Core functionality
269
+ │ │ ├── models.py # Data models
270
+ │ │ ├── config.py # Configuration management
271
+ │ │ ├── discovery.py # Project discovery
272
+ │ │ └── storage.py # SQLite storage
273
+ │ ├── ui/ # User interface
274
+ │ │ ├── selector.py # Main TUI
275
+ │ │ ├── preview.py # Preview generation
276
+ │ │ └── browser.py # Directory browser
277
+ │ ├── utils/ # Utilities
278
+ │ │ └── git.py # Git operations
279
+ │ └── cli.py # CLI entry point
280
+ └── tests/ # Test suite
281
+ ```
282
+
283
+ ## Requirements
284
+
285
+ - **Python**: 3.8 or higher
286
+ - **fzf**: Interactive fuzzy finder ([installation guide](https://github.com/junegunn/fzf#installation))
287
+ - Ubuntu/Debian: `sudo apt install fzf`
288
+ - macOS: `brew install fzf`
289
+ - Windows: `choco install fzf`
290
+ - **Git**: For repository discovery and status
291
+ - **Claude Code CLI**: Must be installed and in PATH
292
+
293
+ ## Troubleshooting
294
+
295
+ ### "claude command not found"
296
+ Ensure Claude Code CLI is installed and accessible in your PATH.
297
+
298
+ ### No projects found
299
+ 1. Run `claude-launcher --setup` to configure scan paths
300
+ 2. Verify paths exist and contain git repositories
301
+ 3. Check permissions on directories
302
+
303
+ ### Database errors
304
+ The database auto-recovers from corruption. Check for `.db.backup.*` files if you need to restore data.
305
+
306
+ ### Permission denied during scan
307
+ Some directories may not be readable. These are automatically skipped with a warning.
308
+
309
+ ## Contributing
310
+
311
+ Contributions are welcome! Please:
312
+
313
+ 1. Fork the repository
314
+ 2. Create a feature branch
315
+ 3. Add tests for new functionality
316
+ 4. Ensure all tests pass
317
+ 5. Submit a pull request
318
+
319
+ ## License
320
+
321
+ MIT License - see [LICENSE](LICENSE) file for details.
322
+
323
+ ## Changelog
324
+
325
+ ### 0.1.0 (Initial Release)
326
+ - Project discovery with git repository scanning
327
+ - Alphabetical sorting with last-opened default
328
+ - Interactive fuzzy search with preview pane
329
+ - Manual path management
330
+ - Git clone integration
331
+ - Error recovery
332
+ - Cross-platform support
@@ -0,0 +1,23 @@
1
+ claude_launcher/__init__.py,sha256=Mx2xmzSCBzceFDYJn38FjVmROwuwGk-L0eqBt0JXbNA,96
2
+ claude_launcher/__main__.py,sha256=f3pKnCN2ClMQp04jcxA2CJsbLB5i9x02Ay393rqR6G4,124
3
+ claude_launcher/cli.py,sha256=NvZfl43h_YlYTEUPKySfq1_63lDnbKHeKpKauQf2nbY,6171
4
+ claude_launcher/core/__init__.py,sha256=blrH7IxttUY1lNfB1ODWfQi-JGOXzGZgtstLVWzaTe0,46
5
+ claude_launcher/core/config.py,sha256=_8P46YZOshbfztCbOcUHZ_1y2WlNJl-ymg4DhmIpH3g,7295
6
+ claude_launcher/core/discovery.py,sha256=kconwnfBD0-6G1_QDAfdlX120DOO4iorT0Hgnqj5bHI,2882
7
+ claude_launcher/core/models.py,sha256=HcUVExgO0BOU7ZW1MXIEkpPfH_GVvSdOaehJ_s_eROY,3251
8
+ claude_launcher/core/storage.py,sha256=kEWYH64Wgq7S0_x4OlE-bmzZMPegcPecO6RUxlru13I,7172
9
+ claude_launcher/ui/__init__.py,sha256=ldsGr4N1T3u_S6h1yp0henOvStzyx6nV6hla7assi4M,53
10
+ claude_launcher/ui/_preview_helper.py,sha256=AU87OodttgRrM5NHYaKx7v6LHVDz6XGyHpRST1eWgKg,2179
11
+ claude_launcher/ui/browser.py,sha256=2U4lkeB99Md637KHmUT_pnGfEOpsLwBonqmjCjHTIpU,5624
12
+ claude_launcher/ui/preview.py,sha256=S5DAcrlCR11TazftVu3QYbTdcULXn2Mhk8epoqBPAdM,8966
13
+ claude_launcher/ui/selector.py,sha256=4n1lzakNaZzRtC6GdSeQVvDDSA6rycDPjBqUi0eylmc,10293
14
+ claude_launcher/utils/__init__.py,sha256=6cemx9bytMG4GZrbEtxhqwzhIaLMRGlRkj90PCOrH4k,45
15
+ claude_launcher/utils/git.py,sha256=mry84cLf07qBWdNmeeTA5J4XSMrz0J7--arpI4mVSOw,4102
16
+ claude_launcher/utils/logging.py,sha256=0v9qR3Iln3l4K72LBEdZC6Xzd4L5Qp_zEwQ62QOv9Dg,2218
17
+ claude_launcher/utils/paths.py,sha256=rbREoVCAbGV9-YaSiZg2I0ExmsOnWbjnDKwSd933g9s,1457
18
+ claude_launcher-0.1.0.dist-info/licenses/LICENSE,sha256=3EyvXvCOXv-KdxLeyLGTwf0_q1buihHRW4Y02himIjk,1085
19
+ claude_launcher-0.1.0.dist-info/METADATA,sha256=LCNJVAZhOq-g5ABfxwIjbeabpP8eiGOB2SRP1GC-sNE,9527
20
+ claude_launcher-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
21
+ claude_launcher-0.1.0.dist-info/entry_points.txt,sha256=9D2wFyj4LPXZmEdIb2V-8GZanXTTNfuhcadIHGuX8iU,60
22
+ claude_launcher-0.1.0.dist-info/top_level.txt,sha256=lcBURRPJ6SvXsbBBnO2DmobA3hCFcSMQz9IVqg4gDr0,16
23
+ claude_launcher-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ claude-launcher = claude_launcher.cli:app
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Claude Launcher Contributors
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 @@
1
+ claude_launcher