{"id":45804050,"url":"https://github.com/leeovery/portal","last_synced_at":"2026-03-01T22:05:49.266Z","repository":{"id":334024391,"uuid":"1139707754","full_name":"leeovery/portal","owner":"leeovery","description":null,"archived":false,"fork":false,"pushed_at":"2026-02-26T12:52:15.000Z","size":1404,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-26T17:14:48.415Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leeovery.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-22T10:04:57.000Z","updated_at":"2026-02-26T12:52:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/leeovery/portal","commit_stats":null,"previous_names":["leeovery/cx","leeovery/portal"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/leeovery/portal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leeovery%2Fportal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leeovery%2Fportal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leeovery%2Fportal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leeovery%2Fportal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leeovery","download_url":"https://codeload.github.com/leeovery/portal/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leeovery%2Fportal/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29986242,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-01T21:06:37.093Z","status":"ssl_error","status_checked_at":"2026-03-01T21:05:45.052Z","response_time":124,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-26T13:08:08.122Z","updated_at":"2026-03-01T22:05:49.254Z","avatar_url":"https://github.com/leeovery.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# Portal\n\n**Interactive session picker for tmux**\n\nA CLI that gives you fast, fuzzy session management from bare shell,\n\u003cbr\u003ewith project memory, path aliases, and a keyboard-driven TUI.\n\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![Go](https://img.shields.io/badge/Go-1.25+-00ADD8.svg)](https://go.dev)\n\n[Install](#install) · [Quick Start](#quick-start) · [Commands](#commands) · [Shell Integration](#shell-integration) · [Configuration](#configuration)\n\n\u003c/div\u003e\n\n---\n\nPortal is a CLI that runs at bare shell (before entering tmux) and provides an interactive TUI for picking, creating, and managing tmux sessions. It remembers your projects, resolves paths via aliases and zoxide, and auto-detects git roots for new sessions.\n\nAfter [shell integration](#shell-integration), you interact with Portal through two functions: **`x`** (session picker / opener) and **`xctl`** (subcommands like list, kill, alias). The function names are customizable — see `--cmd` below.\n\n## Install\n\n**macOS**\n\n```bash\nbrew install leeovery/tools/portal\n```\n\n**Linux**\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/leeovery/portal/main/scripts/install.sh | bash\n```\n\n**Go**\n\n```bash\ngo install github.com/leeovery/portal@latest\n```\n\n## Quick Start\n\n```bash\n# Add shell integration (creates x() and xctl() functions)\necho 'eval \"$(portal init zsh)\"' \u003e\u003e ~/.zshrc\n\n# Launch the interactive picker\nx\n\n# Open a session at a path\nx ~/Code/myproject\n\n# Open with a command\nx ~/Code/myproject -e \"make dev\"\n\n# Set up an alias\nxctl alias set work ~/Code/work-project\nx work\n\n# List running sessions\nxctl list\n\n# Kill a session\nxctl kill myproject\n```\n\n## Shell Integration\n\nPortal generates shell functions via `portal init`. Add to your shell profile:\n\n```bash\n# zsh\neval \"$(portal init zsh)\"\n\n# bash\neval \"$(portal init bash)\"\n\n# fish\nportal init fish | source\n```\n\nThis creates two functions:\n\n- **`x()`** — launches Portal (interactive picker or path-based session creation)\n- **`xctl()`** — direct access to Portal subcommands (`list`, `kill`, `alias`, etc.)\n\nCustomize the function name with `--cmd`:\n\n```bash\neval \"$(portal init zsh --cmd p)\"   # creates p() and pctl()\n```\n\n## Commands\n\n\u003e Examples below use the default `x` / `xctl` function names. If you used `--cmd p`, substitute `p` and `pctl`. You can also call the `portal` binary directly.\n\n### `x` (open)\n\nInteractive session picker or path-based session creation. `x` maps to `portal open`.\n\n```bash\nx                                    # interactive TUI\nx ~/Code/myproject                   # open session at path\nx myalias                            # resolve alias → path → session\nx ~/Code/app -e \"make dev\"           # run command in new session\nx ~/Code/app -- npm start            # alternative command syntax\n```\n\n| Flag | Description |\n|---|---|\n| `-e, --exec` | Command to execute in the new session |\n\nPath resolution order: aliases → zoxide → TUI with filter.\n\nNew sessions auto-resolve to the git repository root when applicable.\n\n### `xctl attach`\n\nAttach to an existing tmux session by name.\n\n```bash\nxctl attach myproject\n```\n\n### `xctl list`\n\nList running tmux sessions.\n\n```bash\nxctl list                            # auto-detect format\nxctl list --long                     # full details\nxctl list --short                    # names only\n```\n\n| Flag | Description |\n|---|---|\n| `--long` | Full session details (name, status, window count) |\n| `--short` | Session names only, one per line |\n\n### `xctl kill`\n\nKill a tmux session by name.\n\n```bash\nxctl kill myproject\n```\n\n### `xctl alias`\n\nManage path aliases for quick session access.\n\n```bash\nxctl alias set work ~/Code/work      # create alias\nxctl alias rm work                   # remove alias\nxctl alias list                      # list all aliases\n```\n\n### `xctl clean`\n\nRemove stale projects whose directories no longer exist on disk.\n\n```bash\nxctl clean\n```\n\n### `xctl version`\n\nPrint the Portal version.\n\n```bash\nxctl version\n```\n\n### `portal init`\n\nOutput shell integration script for eval. See [Shell Integration](#shell-integration). This is the one command you call via the `portal` binary directly.\n\n```bash\nportal init zsh\nportal init bash --cmd p\n```\n\n## TUI Keybindings\n\n| Key | Action |\n|---|---|\n| `↑`/`k` | Move up |\n| `↓`/`j` | Move down |\n| `Enter` | Select session / confirm |\n| `/` | Filter mode (fuzzy search) |\n| `R` | Rename session |\n| `K` | Kill session |\n| `q`/`Esc` | Quit |\n\nThe TUI has three views: session list, project picker, and file browser.\n\n## Configuration\n\nPortal stores config in `~/.config/portal/`:\n\n| File | Purpose | Env override |\n|---|---|---|\n| `aliases` | Path aliases (key=value, one per line) | `PORTAL_ALIASES_FILE` |\n| `projects.json` | Remembered project directories | `PORTAL_PROJECTS_FILE` |\n\nProjects are auto-populated when you create new sessions and cleaned with `xctl clean`.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleeovery%2Fportal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleeovery%2Fportal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleeovery%2Fportal/lists"}