bascially ready to ship
This commit is contained in:
119
README.md
119
README.md
@@ -1,63 +1,92 @@
|
||||
# Session Mover TUI
|
||||
# opencode-session-mover
|
||||
|
||||
A Python Textual TUI for easily moving OpenCode sessions between projects and workspaces without writing SQL.
|
||||
*USE AT YOUR OWN RUSK*
|
||||
|
||||
## Quick Start
|
||||
⚠️ This is entirely vibe coded and mostly untested. It should backup yout database before changing anything, but you should make your own backup first ⚠️
|
||||
|
||||
A terminal UI for managing [OpenCode](https://opencode.ai) sessions — move, copy, or delete sessions across projects without writing SQL.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.11+
|
||||
- [Textual](https://github.com/Textualize/textual) (`pip install -r requirements.txt`)
|
||||
|
||||
A `mise.toml` is included if you use [mise](https://mise.jdx.dev) — it pins Python 3.14 and SQLite 3.51. Run `mise install` to set up the environment.
|
||||
|
||||
OpenCode stores its data in an SQLite database, usually at `~/.local/share/opencode/opencode.db`.
|
||||
|
||||
## Running
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
# Install dependencies With mise
|
||||
mise install
|
||||
|
||||
# Install dependencies and run
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Run (looks for opencode.db in current directory)
|
||||
python session-mover.py
|
||||
|
||||
# Or specify a database path
|
||||
python session-mover.py /path/to/opencode.db
|
||||
python main.py /path/to/opencode.db
|
||||
```
|
||||
|
||||
## How to Use
|
||||
If no path is given it looks for `opencode.db` in the current directory.
|
||||
|
||||
1. **Browse** - See all sessions organized by project/workspace on the left
|
||||
2. **Select** - Click or use arrow keys + Enter to select sessions (multiple with Shift+Click)
|
||||
3. **Filter** - Type in the filter box to search session titles
|
||||
4. **Move** - Press `m` to move selected sessions to another project
|
||||
5. **Copy** - Press `c` to duplicate sessions to another project
|
||||
6. **Backup** - Press `b` to manually create a database backup
|
||||
## Layout
|
||||
|
||||
### Hotkeys (always visible at bottom)
|
||||
The UI has two panels:
|
||||
|
||||
- `b` - Backup database
|
||||
- `m` - Move selected sessions
|
||||
- `c` - Copy selected sessions
|
||||
- `a` - Toggle archived sessions visibility
|
||||
- `r` - Refresh all data
|
||||
- `q` - Quit
|
||||
- `Escape` - Deselect / close dialogs
|
||||
- **Left — All Projects**: a list of your OpenCode projects with active session counts
|
||||
- **Right — Sessions**: sessions for the selected project, with a filter bar at the top
|
||||
|
||||
### Move/Copy Dialog
|
||||
## Keybindings
|
||||
|
||||
1. Select destination project (dropdown)
|
||||
2. Optionally select a workspace within that project
|
||||
3. Review the SQL preview to see what will execute
|
||||
4. Press `Enter` or click Confirm to execute
|
||||
5. A backup is automatically created before the first write operation
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `Tab` | Move focus between project list and session table |
|
||||
| `f` | Focus the filter input |
|
||||
| `Enter` (in filter) | Return focus to session table |
|
||||
| `Escape` | Clear filter if active, otherwise clear selection |
|
||||
| `Space` | Select / deselect the highlighted session |
|
||||
| `m` | Move selected sessions to another project |
|
||||
| `c` | Copy selected sessions to another project |
|
||||
| `d` | Delete selected sessions (with confirmation) |
|
||||
| `a` | Toggle visibility of archived sessions |
|
||||
| `b` | Create a manual database backup |
|
||||
| `r` | Refresh all data from the database |
|
||||
| `q` | Quit |
|
||||
|
||||
### Safety
|
||||
## Selecting Sessions
|
||||
|
||||
- Before any move/copy, a timestamped backup is created: `opencode-YYYYMMDD-HHMMSS.db`
|
||||
- Confirmation dialog shows exactly what will happen
|
||||
- Changes appear immediately in the UI after success
|
||||
Navigate the session table with the arrow keys. Press `Space` to toggle selection on the highlighted row. The selection count is shown at the bottom of the session panel. Selection is cleared when you switch projects.
|
||||
|
||||
## Database Schema Support
|
||||
Use `f` to filter sessions by title or slug (case-insensitive). Filtering and selection work together — you can filter, select matching sessions, clear the filter, and the selections persist.
|
||||
|
||||
Works with OpenCode's `opencode.db` with tables:
|
||||
- `session` (with project_id, workspace_id, parent_id)
|
||||
- `project`, `workspace`
|
||||
- `message` → `part`, `todo`, `session_share` (all cascade automatically)
|
||||
## Move / Copy
|
||||
|
||||
## Tips
|
||||
1. Select one or more sessions with `Space`
|
||||
2. Press `m` (move) or `c` (copy)
|
||||
3. Choose a destination project from the dropdown (sorted alphabetically, current project excluded)
|
||||
4. Optionally choose a workspace within that project
|
||||
5. Click Confirm or press `Enter`
|
||||
|
||||
- Filter by typing in the search box (searches title and slug)
|
||||
- Toggle archived sessions with `a` (hidden by default)
|
||||
- The left panel shows Projects → Workspaces hierarchy
|
||||
- Selected sessions remain selected when filtering, so you can search, select, then clear filter
|
||||
A timestamped backup is created automatically before the first write operation in a session: `opencode-YYYYMMDD-HHMMSS.db`
|
||||
|
||||
Copy duplicates the session and all related records (messages, parts, todos). Move updates the session's project/workspace in place.
|
||||
|
||||
## Delete
|
||||
|
||||
1. Select one or more sessions with `Space`
|
||||
2. Press `d`
|
||||
3. Review the list of sessions to be deleted in the confirmation dialog
|
||||
4. Click Delete to confirm, or Cancel / `Escape` to abort
|
||||
|
||||
Deletion is permanent and removes all related records (messages, todos, etc). A backup is created automatically before the first delete.
|
||||
|
||||
## Archived Sessions
|
||||
|
||||
OpenCode can archive sessions. By default they are hidden. Press `a` to show them alongside active sessions — the session panel header will update to indicate archived mode is on.
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `main.py` | Entry point |
|
||||
| `app.py` | Textual TUI — layout, keybindings, UI logic |
|
||||
| `database.py` | SQLite queries — sessions, move, copy, delete, backup |
|
||||
|
||||
5
app.py
5
app.py
@@ -381,8 +381,13 @@ class SessionMoverApp(App):
|
||||
|
||||
def on_mount(self) -> None:
|
||||
"""Initialize app."""
|
||||
try:
|
||||
self.db.connect()
|
||||
self.db.load_reference_data()
|
||||
except FileNotFoundError as e:
|
||||
self.notify(str(e), severity="error", timeout=10)
|
||||
self.set_timer(1, self.exit)
|
||||
return
|
||||
|
||||
self._project_ids: List[str] = []
|
||||
self.refresh_project_list()
|
||||
|
||||
@@ -62,6 +62,8 @@ class Database:
|
||||
|
||||
def connect(self):
|
||||
"""Establish database connection."""
|
||||
if not self.db_path.exists():
|
||||
raise FileNotFoundError(f"Database not found: {self.db_path}")
|
||||
self.conn = sqlite3.connect(self.db_path)
|
||||
self.conn.row_factory = sqlite3.Row
|
||||
|
||||
|
||||
10
main.py
10
main.py
@@ -1,8 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Session Mover TUI - Move OpenCode sessions between projects without SQL."""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from app import SessionMoverApp
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = SessionMoverApp()
|
||||
db_path = Path(sys.argv[1]) if len(sys.argv) > 1 else Path("opencode.db")
|
||||
|
||||
if not db_path.exists():
|
||||
print(f"Error: database file not found: {db_path}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
app = SessionMoverApp(str(db_path))
|
||||
app.run()
|
||||
|
||||
Reference in New Issue
Block a user