Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions spec/command_line.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,24 @@ try <url> [name] # URL shorthand (same as clone)
- `name` (optional): Custom name suffix (default: extracted from URL)

**Behavior:**
- Creates directory named `YYYY-MM-DD-<user>-<repo>` (extracted from URL)
- Clones repository into that directory
- **Default**: Creates directory named `YYYY-MM-DD-<user>-<repo>` (extracted from URL) under tries path
- **With `GH_PATH` set**: For `github.com` URLs, creates directory at `$GH_PATH/<owner>/<repo>` (or `$GH_PATH/<owner>/<custom_name>` if custom name provided). If the directory already exists, just `cd`s into it without cloning.
- Clones repository into that directory (unless it already exists when using `GH_PATH`)
- Returns shell script to cd into cloned directory

**Examples:**
```
try clone https://github.com/tobi/try.git
# Creates: 2025-11-30-tobi-try
# Creates: 2025-11-30-tobi-try (default behavior)

GH_PATH=~/github try clone https://github.com/tobi/try.git
# Creates: ~/github/tobi/try (GitHub-specific path)

GH_PATH=~/github try clone https://github.com/user/repo myproject
# Creates: ~/github/user/myproject (custom name)

try clone https://github.com/user/repo myproject
# Creates: 2025-11-30-myproject (custom name overrides)
# Creates: 2025-11-30-myproject (custom name overrides, default path)

try https://github.com/tobi/try.git
# URL shorthand (same as first example)
Expand Down Expand Up @@ -180,6 +187,7 @@ Commands are chained with `&& \` for readability, with 2-space indent on continu
| `HOME` | Used to resolve default tries path (`$HOME/src/tries`) |
| `SHELL` | Used by `init` to detect shell type |
| `NO_COLOR` | If set, disables colors (equivalent to `--no-colors`) |
| `GH_PATH` | If set, GitHub repositories are cloned to `$GH_PATH/<owner>/<repo>` instead of date-prefixed directories under tries path |

## Defaults

Expand Down
49 changes: 26 additions & 23 deletions spec/delete_spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,33 +57,27 @@ In exec mode, delete outputs a shell script that is evaluated by the shell wrapp
### Script Structure

```sh
cd '/path/to/tries' && \
[[ -d 'dir-name-1' ]] && rm -rf 'dir-name-1' && \
[[ -d 'dir-name-2' ]] && rm -rf 'dir-name-2' && \
[[ -d '/full/path/to/dir-name-1' ]] && rm -rf '/full/path/to/dir-name-1' && \
[[ -d '/full/path/to/dir-name-2' ]] && rm -rf '/full/path/to/dir-name-2' && \
( cd '/original/pwd' 2>/dev/null || cd "$HOME" )
```

Each command is on its own line, chained with `&& \` for readability, with 2-space indent on continuation lines.

### Script Components

1. **Change to tries base directory**
1. **Per-item delete commands**
```sh
cd '/path/to/tries' && \
```
All deletions happen relative to the tries base path.

2. **Per-item delete commands**
```sh
[[ -d 'name' ]] && rm -rf 'name' && \
[[ -d '/full/path/to/name' ]] && rm -rf '/full/path/to/name' && \
```
- Check directory exists before deletion
- Use basename only (not full path)
- Use absolute paths (supports both tries and GitHub sources)
- Each on its own line with continuation
- Paths are validated before script generation to ensure they're within allowed roots

3. **PWD restoration**
2. **PWD restoration**
```sh
( cd '/original/pwd' 2>/dev/null || cd "$HOME" )
( cd '/original/pwd' 2>/dev/null || cd "$HOME" )
```
- Attempt to return to original working directory
- Fall back to $HOME if original no longer exists
Expand All @@ -101,26 +95,35 @@ For deleting two directories from `/home/user/tries`:

```sh
# if you can read this, you didn't launch try from an alias. run try --help.
cd '/home/user/tries' && \
[[ -d '2025-11-29-old-project' ]] && rm -rf '2025-11-29-old-project' && \
[[ -d '2025-11-28-abandoned' ]] && rm -rf '2025-11-28-abandoned' && \
[[ -d '/home/user/tries/2025-11-29-old-project' ]] && rm -rf '/home/user/tries/2025-11-29-old-project' && \
[[ -d '/home/user/tries/2025-11-28-abandoned' ]] && rm -rf '/home/user/tries/2025-11-28-abandoned' && \
( cd '/home/user/code' 2>/dev/null || cd "$HOME" )
```

For deleting a GitHub repository (when `GH_PATH` is set):

```sh
# if you can read this, you didn't launch try from an alias. run try --help.
[[ -d '/home/user/github/owner/repo' ]] && rm -rf '/home/user/github/owner/repo' && \
( cd '/home/user/code' 2>/dev/null || cd "$HOME" )
```

## Safety Guarantees

### Path Containment

- Deletions only happen within the tries base directory
- The `cd` to tries base ensures relative paths stay contained
- No symlink traversal outside tries directory
- Deletions only happen within allowed root directories:
- Items from tries source must be within `TRY_PATH`
- Items from GitHub source must be within `GH_PATH` (when enabled)
- Path validation occurs before script generation using `File.realpath` to resolve symlinks
- Each item is validated against its appropriate root based on its source
- No symlink traversal outside allowed directories

### PWD Handling

- If shell's PWD is inside a directory being deleted:
- Script changes to tries base first
- Then performs deletion
- Attempts to restore PWD (which will fail gracefully)
- Script performs deletion using absolute paths
- Attempts to restore PWD (which will fail gracefully if PWD was deleted)
- Falls back to $HOME

### Existence Check
Expand Down
17 changes: 17 additions & 0 deletions spec/tui_spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ Tokens are preserved intact - never split a `{b}...{/b}` pair.
| Enter | Select current entry |
| Esc / Ctrl-C | Cancel selection |
| Ctrl-D | Delete selected directory |
| Ctrl-G | Toggle source between tries and GitHub (only when `GH_PATH` is set) |

### Line Editing (in search input)
| Key | Action |
Expand Down Expand Up @@ -249,6 +250,22 @@ When query doesn't match any existing directory:
- Show "[new] query-text" as first option
- Selecting creates `YYYY-MM-DD-query-text` directory
- New directory is created in tries base path
- **Note**: "Create new" is disabled when viewing GitHub source (Ctrl-G)

## Source Switching

When `GH_PATH` environment variable is set, the TUI supports switching between two sources:

- **Tries source** (default): Lists immediate subdirectories under the tries path
- **GitHub source**: Lists repositories under `$GH_PATH/<owner>/<repo>` (2-level traversal)

**Behavior:**
- Press `Ctrl-G` to toggle between sources
- When switching sources, the list cache is cleared, cursor resets to top, and scroll resets
- In GitHub source mode:
- Entries are displayed as `owner/repo` (e.g., `toby/try`)
- "Create new" option is disabled
- Navigation and selection work the same as in tries source

## Directory Deletion

Expand Down
Loading