Skip to content
Merged
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
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -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
163 changes: 49 additions & 114 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,125 +1,60 @@
<div align="left">
<img src="icon.svg" alt="Get Tabs Tool Icon" width="80" height="80">
</div>
# 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.

MIT. See [LICENSE](LICENSE).
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -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 = []
24 changes: 24 additions & 0 deletions tests/test_get_tabs_tool.py
Original file line number Diff line number Diff line change
@@ -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()
Loading