diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..be929bf --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,25 @@ +name: CI + +on: + pull_request: + branches: [master] + push: + branches: [master] + +permissions: + contents: read + +jobs: + checks: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.12" + + - run: python -m compileall -q get_tabs_tool.py + - run: python -m unittest discover -s tests diff --git a/README.md b/README.md index d948692..eee595e 100644 --- a/README.md +++ b/README.md @@ -1,125 +1,60 @@ -
-Get Tabs Tool Icon -
+# Get Tabs Tool -# Get Tabs Tool - README.md +A small macOS command-line utility that returns the titles and URLs of open Safari tabs as JSON. It +uses AppleScript through a short Python wrapper and can also be called from local automation tools. -A command-line tool for macOS that retrieves the titles and URLs of all open tabs in Safari. It can be used as a standalone script or integrated as a local tool into AI assistants like the Gemini CLI. +This is a best-effort hobby project built for a specific macOS workflow. It may need adjustment as +Safari, macOS permissions, or third-party assistant integrations change. +## Requirements -## How It Works -This tool relies on **AppleScript** to communicate directly with the Safari application on your Mac. A Python script executes a small AppleScript file (`get_tabs.applescript`) which asks Safari for its open tabs and returns the information. +- macOS with Safari +- Python 3.12 or newer +- [uv](https://docs.astral.sh/uv/) -Because AppleScript is a macOS-specific technology, this tool will **only run on macOS**. +## Usage +```bash +git clone https://github.com/GoWithitRoger/get-tabs-tool.git +cd get-tabs-tool +uv run get_tabs_tool.py +``` -## Requirements +Example output: + +```json +[ + { + "title": "Example", + "url": "https://example.com/" + } +] +``` + +The first run may prompt your terminal application for permission to control Safari. If needed, +review the setting under **System Settings → Privacy & Security → Automation**. + +## Gemini CLI helper scripts -- **macOS** with Safari installed. -- **Python** >= 3.12 -- [**uv**](https://github.com/astral-sh/uv) (for easy execution with managed dependencies). - - -## Standalone Usage (Command Line) -You can use this tool directly in your terminal to get a quick JSON list of your open tabs. - -1. Navigate to the project directory: - - cd /path/to/get-tabs-tool - -2. Run the tool using `uv`: - - uv run get_tabs_tool.py - -The script will print a JSON array of your open Safari tabs to the terminal. - -#### Example Output: - - [ - { - "title": "Google", - "url": "https://www.google.com/" - }, - { - "title": "Gemini CLI Documentation", - "url": "https://github.com/google-gemini/gemini-cli/blob/main/docs/tools/index.md" - } - ] - -## Gemini CLI Integration -To use this as a local tool within the Gemini CLI, you need to configure the CLI to discover and call the script. - -### Step 1: Create Helper Scripts -The Gemini CLI needs two small shell scripts to understand how to find and run your tool. Create the following two files inside your `get-tabs-tool` project directory. - -**File 1: `discover_tools.sh`** (This script tells Gemini what the tool is called and what it does.) - - #!/bin/bash - cat <<'EOF' - [ - { - "name": "get_tabs", - "description": "Gets the title and URL of all open tabs in Safari.", - "parameters": { - "type": "OBJECT", - "properties": {} - } - } - ] - EOF - -**File 2: `call_tool.sh`** (This script tells Gemini how to execute the tool when it's needed.) - - #!/bin/bash - TOOL_NAME=$1 - SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) - - if [ "$TOOL_NAME" == "get_tabs" ]; then - (cd "$SCRIPT_DIR" && uv run get_tabs_tool.py) - else - echo "Error: Unknown tool '$TOOL_NAME'" >&2 - exit 1 - fi - -### Step 2: Make Scripts Executable -In your terminal, navigate to the `get-tabs-tool` directory and run the following command to make the helper scripts runnable: - - chmod +x discover_tools.sh call_tool.sh - -### Step 3: Configure Gemini CLI `settings.json` -Finally, edit your Gemini CLI `settings.json` file to tell it about your new scripts. You will need to add the `toolDiscoveryCommand` and `toolCallCommand` keys, pointing to the absolute paths of the scripts you just created. - - { - "theme": "Default", - "selectedAuthType": "oauth-personal", - "contextFileName": "GEMINI.md", - "preferredEditor": "vscode", - "toolDiscoveryCommand": "/Users/your_username/Projects/get-tabs-tool/discover_tools.sh", - "toolCallCommand": "/Users/your_username/Projects/get-tabs-tool/call_tool.sh", - "mcpServers": { - "...": "..." - } - } - -**Important:** Replace `/Users/your_username/` with the actual path to your home directory. - -After saving `settings.json`, restart the Gemini CLI. It will now have the `get_tabs` tool available. - - -## Important: macOS Permissions -The first time you run this tool (either standalone or via Gemini), macOS will likely ask for permission for your terminal application (e.g., `Terminal.app`, `iTerm.app`) to control Safari. **You must approve this request for the tool to work.** - -If you miss the pop-up or deny it, you can grant permission manually: - -1. Open **System Settings**. -2. Go to **Privacy & Security > Automation**. -3. Find your terminal application in the list. -4. Ensure the checkbox for **Safari** is enabled. - - -## Contributing -Contributions are welcome! Please feel free to submit a pull request or open an issue. +The repository includes `discover_tools.sh` and `call_tool.sh` for the older Gemini CLI local-tool +interface. Point Gemini's `toolDiscoveryCommand` and `toolCallCommand` settings at those files and +make them executable: +```bash +chmod +x discover_tools.sh call_tool.sh +``` + +That integration is kept as a convenience and may change with Gemini CLI releases. The standalone +Python command does not depend on Gemini. + +## Development + +The parser tests do not open Safari and can run on any platform: + +```bash +python -m unittest discover -s tests +``` ## License -This project is licensed under the MIT License. \ No newline at end of file + +MIT. See [LICENSE](LICENSE). diff --git a/pyproject.toml b/pyproject.toml index 0c9d31c..ad66fc9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "get-tabs-tool" version = "0.1.0" -description = "Add your description here" +description = "Read titles and URLs from open Safari tabs on macOS" readme = "README.md" requires-python = ">=3.12" dependencies = [] diff --git a/tests/test_get_tabs_tool.py b/tests/test_get_tabs_tool.py new file mode 100644 index 0000000..2df6d7a --- /dev/null +++ b/tests/test_get_tabs_tool.py @@ -0,0 +1,24 @@ +import unittest + +from get_tabs_tool import parse_tab_line + + +class ParseTabLineTests(unittest.TestCase): + def test_parses_title_and_url(self): + self.assertEqual( + parse_tab_line("Example|||https://example.com/"), + {"title": "Example", "url": "https://example.com/"}, + ) + + def test_preserves_delimiter_inside_url(self): + self.assertEqual( + parse_tab_line("Example|||https://example.com/a|||b"), + {"title": "Example", "url": "https://example.com/a|||b"}, + ) + + def test_ignores_unrecognized_lines(self): + self.assertIsNone(parse_tab_line("not a tab record")) + + +if __name__ == "__main__": + unittest.main()