{"id":50814765,"url":"https://github.com/irskep/automate-terminal","last_synced_at":"2026-06-13T08:33:12.793Z","repository":{"id":323237621,"uuid":"1092541928","full_name":"irskep/automate-terminal","owner":"irskep","description":"Wrapper for terminal automation in iTerm2, tmux, Kitty, Guake, WezTerm, Terminal.app, Ghostty, and VSCode","archived":false,"fork":false,"pushed_at":"2026-05-14T17:54:01.000Z","size":139,"stargazers_count":6,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-14T19:30:34.660Z","etag":null,"topics":["automation","cli","terminal","terminal-emulator"],"latest_commit_sha":null,"homepage":"","language":"Python","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/irskep.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2025-11-08T20:22:49.000Z","updated_at":"2026-05-14T18:04:03.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/irskep/automate-terminal","commit_stats":null,"previous_names":["irskep/automate-terminal"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/irskep/automate-terminal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/irskep%2Fautomate-terminal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/irskep%2Fautomate-terminal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/irskep%2Fautomate-terminal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/irskep%2Fautomate-terminal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/irskep","download_url":"https://codeload.github.com/irskep/automate-terminal/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/irskep%2Fautomate-terminal/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34278153,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["automation","cli","terminal","terminal-emulator"],"created_at":"2026-06-13T08:33:12.030Z","updated_at":"2026-06-13T08:33:12.788Z","avatar_url":"https://github.com/irskep.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# automate-terminal\n\nAutomate opening of new tabs and windows in terminal programs. Currently supports iTerm2, Terminal.app, Ghostty, Guake, tmux, WezTerm, Kitty, Cursor, and Visual Studio Code.\n\nautomate-terminal is a best-effort project. Some terminals do not support automation at all! It's also intended to be used as a component in other tools, so it errs on the side of strictness over fallbacks. See the command reference for specifics.\n\n`automate-terminal` was originally part of [autowt](https://steveasleep.com/autowt/), the git worktree manager.\n\n## Installation\n\n```bash\n# mise (recommended)\nmise install ubi:irskep/automate-terminal\n\n# ubi\nubi --project irskep/automate-terminal --in ~/bin\n\n# go install\ngo install github.com/irskep/automate-terminal/cmd/automate-terminal@latest\n```\n\nPre-built static binaries are also available on the [GitHub Releases](https://github.com/irskep/automate-terminal/releases) page for macOS and Linux.\n\nFor Guake terminal support on Linux, make sure the `gdbus` CLI from GLib/GIO is on your `PATH`. On most desktop distributions it already is; if you use a minimal system, install the GLib utilities package (e.g., `apt install libglib2.0-bin`, `dnf install glib2`, `pacman -S glib2`, or `apk add glib`).\n\n## Supported Terminals\n\n| Terminal     | Platform       | New Tabs/Windows | Switch by ID | Switch by Working Dir | List Sessions | Paste Commands | Run in Active Session |\n| ------------ | -------------- | ---------------- | ------------ | --------------------- | ------------- | -------------- | --------------------- |\n| iTerm2       | macOS          | ✅               | ✅           | ✅                    | ✅            | ✅             | ✅                    |\n| Terminal.app | macOS          | ✅               | ❌           | ✅                    | ✅            | ✅             | ✅                    |\n| Ghostty      | macOS          | ✅               | ❌           | ❌                    | ❌            | ✅             | ✅                    |\n| Guake        | Linux          | ⚠️ (tabs only)   | ✅           | ✅                    | ✅            | ✅             | ✅                    |\n| tmux         | Cross-platform | ✅               | ✅           | ✅                    | ✅            | ✅             | ✅                    |\n| WezTerm      | Cross-platform | ✅               | ✅           | ✅                    | ✅            | ✅             | ✅                    |\n| Kitty        | Cross-platform | ✅\\*             | ✅\\*         | ✅\\*                  | ✅\\*          | ✅\\*           | ✅\\*                  |\n| VSCode       | Cross-platform | ⚠️ (no tabs)     | ❌           | ✅                    | ❌            | ❌             | ❌                    |\n| Cursor       | Cross-platform | ⚠️ (no tabs)     | ❌           | ✅                    | ❌            | ❌             | ❌                    |\n\n\\* **Kitty requires `allow_remote_control yes` in `kitty.conf`** to enable automation features.\n\n**Guake** requires only the `gdbus` command (usually provided by GLib/GIO) for DBus communication.\n\nOther terminals are not supported. `automate-terminal` will exit with an error code in unsupported terminals.\n\n## Quick Start\n\n### Command Line\n\n```bash\n# Check if your terminal is supported\nautomate-terminal check\n\n# Create a new tab\nautomate-terminal new-tab /path/to/project\n\n# Switch to existing session by directory\nautomate-terminal switch-to --working-directory=/path/to/project\n\n# Create new window with initialization script\nautomate-terminal new-window --paste-and-run=\"source .env \u0026\u0026 npm run dev\" /path/to/project\n\n# Run a command in the currently active session\nautomate-terminal run-in-active-session \"git status\"\n```\n\n## What is possible with terminal automation?\n\nThis is the \"manage expectations\" section of the README.\n\nThe scope of automation covered by `automate-terminal` is \"create or navigate to a terminal session in a specific working directory.\"\n\n### What is a terminal emulator?\n\nA terminal emulator, for the purposes of this project, is the thing you type your terminal commands into. For the author, it's iTerm2. For many people, it's the built-in terminal in Visual Studio Code. For hipsters, it's Ghostty. Linux users have more options than I know of, including KConsole. And there's WezTerm, and the built-in terminals for macOS and Windows. Every few years, somebody spins up a new one.\n\nWithin terminal emulators, a _session_ is, for the purposes of this project, one specific terminal running a shell. Your sessions might be organized in windows, or tabs, or splits within a window or tab.\n\n### How are they controlled?\n\nIn **many different ways**, which is why this problem is complex enough to warrant a library! The ability to open a new tab or window, or switch to a specific existing session based on some criteria, is not standardized _at all_ among terminal emulators. The spread of what is possible for a given terminal emulator is incredibly wide, as shown by the table at the top of this README.\n\nmacOS terminals are primarily controlled via AppleScript. iTerm2, for example, has a comprehensive AppleScript API, which is why it has the best support. Ghostty has _no_ AppleScript API at all, so `automate-terminal` uses the `SystemEvents` API to \"click\" its menu items, and we have no way of knowing which Ghostty tab is in a particular working directory. VSCode also has no AppleScript API, but it does have its `code \u003cpath\u003e` command to open or switch to a specific window.\n\n**tmux** uses its native CLI commands (`tmux list-panes`, `tmux select-window`, `tmux send-keys`, etc.) and works identically across all platforms where tmux is available.\n\n**WezTerm** uses its native CLI commands (`wezterm cli list`, `wezterm cli activate-pane`, `wezterm cli send-text`, etc.) and works identically across all platforms where WezTerm is available.\n\n**Kitty** uses its remote control protocol (`kitten @ ls`, `kitten @ focus-window`, `kitten @ send-text`, etc.) and works across all platforms where Kitty is available. **Note: Kitty requires `allow_remote_control yes` in your `kitty.conf` file to enable automation.**\n\nAll this is to say, if you are unhappy with the level of automation provided by `automate-terminal` on macOS, switch to another terminal emulator, or lobby the authors of your favorite one to add automation support.\n\n## Commands\n\n### check\n\nDetect terminal capabilities.\n\n```bash\nautomate-terminal check\nautomate-terminal check --output=json\n```\n\nExample output:\n\n```\nTerminal: iTerm2\nTerminal Program: iTerm.app\nShell: zsh\nCurrent session ID: w0t5p1:24AF055B-8BD2-4C7F-AB1E-B310FDCBCEA1\nCurrent working directory: /Users/steve/dev/libraries/automate-terminal\n\nCapabilities:\n  can_create_tabs: True\n  can_create_windows: True\n  can_list_sessions: True\n  can_switch_to_session: True\n  can_detect_session_id: True\n  can_detect_working_directory: True\n  can_paste_commands: True\n  can_run_in_active_session: True\n```\n\n### new-tab\n\nCreate new tab in a specific directory, optionally pasting content into the new tab.\n\nThe term \"paste\" here means it will be _as if_ the user pasted text into the new terminal and hit Enter. It doesn't use your system pasteboard.\n\n```bash\nautomate-terminal new-tab /path/to/dir\n\nautomate-terminal new-tab --paste-and-run=\"echo 'I am in the new directory!'\" /path/to/dir\n```\n\nThere are options to run additional scripts only in specific shells. This is useful if your wrapper tool needs to support multiple shells for workflows that require nontrivial shell commands.\n\n```bash\nautomate-terminal new-tab --paste-and-run-fish=\"echo 'I am a fish shell user'\" /path/to/dir\n```\n\n### new-window\n\nCreate new window. Takes the same arguments as `automate-terminal new-tab`.\n\n```bash\nautomate-terminal new-window /path/to/dir\n```\n\n### switch-to\n\nSwitch to an existing session, returning an error no matching session can be found or your terminal doesn't provide session information. You can either pass a working directory with `--working-directory`/`--wd`, or a session ID if the session ID is known.\n\nIf you pass session ID, working directory is ignored. `--wd` is likely what you want, though.\n\nIf you are using an unsupported terminal emulator and want to open a new terminal in a given directory as a fallback, use `new-tab` or `new-window`. `automate-terminal` doesn't do this automatically because it would create unpleasant edge cases for tools that use `automate-terminal`.\n\n```bash\n# By working directory (or use --wd alias)\nautomate-terminal switch-to --working-directory=/path/to/dir\n\n# By session ID (or use --id alias)\nautomate-terminal switch-to --session-id=w0t0p2:ABC123\n```\n\n### list-sessions\n\nList all sessions.\n\n```bash\nautomate-terminal list-sessions\nautomate-terminal list-sessions --output=json\n```\n\n### run-in-active-session\n\nRun a command in the currently active terminal session.\n\nThis command sends the specified command to the active terminal session without switching windows or tabs. It's useful for programmatically executing commands in the terminal session you're currently working in.\n\n```bash\n# Run a simple command\nautomate-terminal run-in-active-session \"echo 'Hello World'\"\n\n# Run a git command\nautomate-terminal run-in-active-session \"git status\"\n\n# Run multiple commands\nautomate-terminal run-in-active-session \"cd /tmp \u0026\u0026 ls -la\"\n```\n\n**Note:** This feature requires terminal support. VSCode and Cursor do not support running commands in the active session. Check capabilities with `automate-terminal check` to see if your terminal supports this feature.\n\n## Options\n\n### Output Format\n\n- `--output=text` - Human-readable (default)\n- `--output=json` - JSON for programmatic use\n- `--output=none` - Silent\n\nOn failure, JSON output includes `\"success\": false` and an `\"error\"` field with a specific reason. For example, a missing accessibility permission on macOS produces:\n\n```json\n{\"success\": false, \"error\": \"Ghostty failed to create tab (missing accessibility permissions? grant accessibility permissions to the calling application in System Settings -\u003e Privacy \u0026 Security -\u003e Accessibility)\", \"terminal\": \"Ghostty\"}\n```\n\nError messages include actionable remediation hints where possible (e.g. missing CLI tools, missing permissions, missing Kitty remote control config).\n\n### Paste and Run\n\nExecute commands after creating/switching sessions.\n\n```bash\n--paste-and-run=\"echo 'I run unconditionally'\"\n--paste-and-run-bash=\"echo 'I only run if the current shell is bash'\"\n--paste-and-run-zsh=\"echo 'I only run if the current shell is zsh'\"\n--paste-and-run-fish=\"echo 'I only run if the current shell is fish'\"\n```\n\nShell-specific flags override generic `--paste-and-run` when detected shell matches.\n\n**Note:** Some terminals (VSCode, Cursor) cannot execute paste scripts programmatically. When using `--output=json`, check the `paste_script_executed` field to determine if you need to run the script manually:\n\n- `true`: The paste script was executed by the terminal\n- `false`: The paste script was provided but the terminal cannot execute it (you should run it manually)\n- Field omitted: No paste script was provided\n\n### Debug and Dry Run\n\n```bash\n--debug     # Enable debug logging to stderr\n--dry-run   # Log actions instead of executing them\n```\n\nUse `--dry-run` to see what commands would be executed without actually running them (AppleScript for macOS terminals, tmux CLI commands for tmux). Useful for debugging and understanding what the tool will do.\n\n## Go Module\n\nautomate-terminal can be imported as a Go library. Module versions follow git tags (`v0.2.0`, etc.), which are the same tags used for binary releases.\n\n```\ngo get github.com/irskep/automate-terminal@latest\n```\n\nUsage:\n\n```go\npackage main\n\nimport (\n    \"log\"\n\n    \"github.com/irskep/automate-terminal/detect\"\n    \"github.com/irskep/automate-terminal/exec\"\n)\n\nfunc main() {\n    runner := \u0026exec.Runner{}\n    t := detect.Detect(runner)\n    if t == nil {\n        log.Fatal(\"unsupported terminal\")\n    }\n\n    // Check what the terminal can do.\n    caps := t.GetCapabilities()\n    if caps.CanCreateTabs {\n        if err := t.OpenNewTab(\"/path/to/dir\", nil); err != nil {\n            log.Fatal(err)\n        }\n    }\n\n    // List open sessions.\n    for _, s := range t.ListSessions() {\n        log.Printf(\"%s -\u003e %s\", s.SessionID, s.WorkingDirectory)\n    }\n\n    // Send a command to the active session.\n    if err := t.RunInActiveSession(\"git status\"); err != nil {\n        log.Fatal(err)\n    }\n}\n```\n\nThe three public packages are:\n\n- `terminal` -- the `Terminal` interface, `Capabilities`, `Session`, and all backend implementations\n- `detect` -- `Detect(runner)` returns the appropriate backend for the current environment\n- `exec` -- `Runner` for subprocess execution (with dry-run support) and `AppleScript` helpers\n\nFull API docs are on [pkg.go.dev](https://pkg.go.dev/github.com/irskep/automate-terminal) once the module is tagged.\n\n## References\n\n- [iTerm2 AppleScript reference](https://iterm2.com/documentation-scripting.html)\n- [Kitty automation reference](https://sw.kovidgoyal.net/kitty/remote-control/)\n- [WezTerm automation reference](https://wezterm.org/cli/cli/index.html)\n- [tmux man page](https://man.openbsd.org/OpenBSD-current/man1/tmux.1)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Firskep%2Fautomate-terminal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Firskep%2Fautomate-terminal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Firskep%2Fautomate-terminal/lists"}