@spjoshis/gogl
v1.4.0
Published
Ask anything to google from terminal
Maintainers
Readme
@spjoshis/gogl
Ask anything to Google from your terminal. A fast, lightweight CLI tool for searching Google and getting results directly in your shell.
✨ Features
- 🚀 Fast & Lightweight - Minimal overhead, quick searches
- 🌐 Real Search Results - Uses Playwright to automate actual searches against Google or DuckDuckGo
- 📋 Clean Output - Top 10 results with title, URL, and description
- 🔄 Retry Logic - Automatic retry on network failures
- 🛡️ Error Handling - Graceful error messages and recovery
- 📦 Zero Dependencies - Only Playwright (peer dependency)
- 🎯 Headless Mode - Runs without opening a visible browser
📋 Requirements
- Node.js: 16.0.0 or higher
- npm: 7.0.0 or higher
- Internet Connection: Required for Google searches
- Playwright: Automatically installed with dependencies
System Requirements
- macOS, Linux, or Windows
- ~200 MB disk space for Playwright browsers
- Sufficient CPU for browser automation
🚀 Installation
Global Installation (Recommended)
Install globally to use the @google command from anywhere:
npm install -g @spjoshis/goglLocal Installation
Install locally in a project:
npm install @spjoshis/goglThen use with npx:
npx @spjoshis/gogl "your query"📖 Usage
Basic Syntax
@google [options] <query>Options
| Option | Description |
|--------|-------------|
| -n, --results <count> | Number of results to return (1–20, default 10) |
| --json | Output results as JSON on stdout (ideal for scripting/piping) |
| --engine <name> | Search engine to use: google, duckduckgo (default: google) |
| --color | Force colorized output (even when piped) |
| --no-color | Disable colorized output |
| --no-dedupe | Keep duplicate-URL results (deduplicated by default) |
| --cache | Reuse a fresh cached result instead of searching again (see Caching) |
| --cache-ttl <seconds> | How long a cached result stays fresh; implies --cache (default 3600) |
| --no-cache | Force a live search, overriding --cache/--cache-ttl |
| --clear-cache | Delete all cached results and exit |
| -h, --help | Show help and exit |
| -v, --version | Show the version and exit |
| -- | Treat everything after it as the query (for queries starting with -) |
@google -n 5 nodejs streams # limit to 5 results
@google --json "rust async" # machine-readable JSON output
@google --engine duckduckgo nodejs # search DuckDuckGo instead of Google
@google --no-color nodejs # plain output, no ANSI colors
@google --cache nodejs streams # reuse a cached result if less than an hour old
@google --help # usageColorized output
Results are colorized to make them easier to scan: the numbered title is bold, the URL is cyan, and the description is dimmed. Color is applied automatically only when writing to a terminal, so piping or redirecting stays plain.
- Force it on or off with
--color/--no-color. - In
automode,goglhonors theNO_COLORconvention (any non-empty value disables color) andFORCE_COLOR(enables it off a TTY). --jsonoutput is never colorized, so it stays machine-parseable.
Result deduplication
Search results sometimes repeat the same page under cosmetically different URLs
(a trailing slash, a #fragment, or a differently-cased host). By default
gogl removes these duplicates, keeping the first (highest-ranked) copy so
ordering is preserved. URLs are compared after normalizing scheme/host case,
dropping the fragment, and ignoring a trailing slash; the query string is kept,
so ?q=1 and ?q=2 stay distinct. Pass --no-dedupe to see the raw list.
In
--jsonmode, results are printed to stdout as a JSON array while the progress banner is sent to stderr, so@google --json "q" | jqstays clean.
Examples
Single word search:
@google nodejsMulti-word search:
@google what is javascriptSearch with special characters:
@google "machine learning" algorithmsSearch with quoted phrases:
@google "artificial intelligence" OR "machine learning"Complex search:
@google how to build a web server with node📤 Output Format
The command returns up to 10 Google search results in the following format:
Searching Google for: "nodejs"
1. Node.js
URL: https://nodejs.org/
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine...
2. Node.js Documentation
URL: https://nodejs.org/docs/
Official documentation for Node.js with API reference, guides, and examples...
3. npm | Home
URL: https://www.npmjs.com/
npm is the world's largest software registry. Discover packages of reusable code...
...and up to 7 more resultsOutput Components
- Index Number: Position of the result (1-10)
- Title: Result heading/title
- URL: Full URL to the resource
- Description: Snippet or meta description from the page
🔧 Development
Setup Development Environment
# Clone the repository
git clone https://github.com/spjoshis/gogl.git
cd gogl
# Install dependencies
npm install
# Install Playwright browsers (required for testing)
npx playwright installProject Structure
@spjoshis/gogl/
├── bin/
│ └── gogl.js # CLI entry point
├── src/
│ ├── index.js # Main exports
│ ├── search.js # Playwright search orchestration (retry + engine dispatch)
│ ├── parser.js # CLI argument parsing
│ ├── formatter.js # Result formatting
│ ├── cache.js # On-disk result cache (opt-in, see Caching)
│ └── engines/ # Per-engine URL building + DOM extraction
│ ├── index.js # Engine registry (google, duckduckgo)
│ ├── google.js # Google engine
│ └── duckduckgo.js # DuckDuckGo engine
├── tests/
│ ├── parser.test.js # Argument parser tests
│ ├── search.test.js # Search function tests
│ ├── formatter.test.js # Formatter tests
│ ├── engines.test.js # Per-engine URL/extraction tests
│ └── edge-cases.test.js # Edge case tests
├── jest.config.js # Jest configuration
├── package.json # Package metadata
└── README.md # This file🧪 Testing
Run All Tests
npm testRun Specific Test Suite
# Parser tests
npm test -- tests/parser.test.js
# Search tests
npm test -- tests/search.test.js
# Formatter tests
npm test -- tests/formatter.test.js
# Edge cases
npm test -- tests/edge-cases.test.jsRun Integration Tests (Live Google Searches)
By default, live Google search tests are skipped. To run them:
LIVE_TESTS=1 npm testNote: Integration tests may timeout if Google blocks the requests.
🏗️ Architecture
How It Works
- Parse Arguments - Extract the search query and options (including
--engine) from command line arguments - Launch Browser - Start Chromium in headless mode using Playwright
- Navigate to Engine - Go to the selected engine's search URL (Google or DuckDuckGo) with the query
- Wait for Load - Wait for network idle to ensure results are loaded
- Extract Results - Use the engine's own DOM queries to extract result titles, URLs, and descriptions
- Format Output - Format results into readable, indexed output
- Display Results - Print formatted results to stdout
- Cleanup - Close browser and clean up resources
Search Engines
gogl supports multiple search engines behind a common interface
(src/engines/). Each engine module provides a buildUrl(query, count) and
an extract(count) function; search.js handles browser lifecycle and retry
logic independent of which engine is selected.
| Engine | Flag value | Notes |
|--------|-----------|-------|
| Google (default) | google | Original behavior; unchanged with no flags. |
| DuckDuckGo | duckduckgo | Uses the html.duckduckgo.com lite endpoint; useful when Google blocks automated requests. |
@google --json --engine duckduckgo "rust async" | jq '.[0].url'Error Handling
The tool includes robust error handling:
- Network Timeouts: Automatic retry with exponential backoff (up to 2 retries)
- Invalid Queries: Graceful handling of empty or whitespace-only queries
- Browser Errors: Clear error messages if browser launch fails
- Missing Results: Returns empty result set if no results found
Performance
- Startup Time: ~3-5 seconds (browser launch)
- Search Time: ~2-10 seconds (depends on network)
- Memory Usage: ~150-200 MB (Chromium process)
💾 Caching
Every search launches a real headless browser (~3-10 seconds), and both engines apply anti-bot challenges to repeated automated traffic. Caching is an opt-in way to reuse a recent result instead of paying that cost — and that risk — again for the exact same search.
@google --cache nodejs streams # cache miss: searches live, then saves the result
@google --cache nodejs streams # cache hit: returns instantly, no browser launch
@google --cache-ttl 300 nodejs streams # cache for 5 minutes instead of the 1 hour default
@google --cache --no-cache nodejs streams # --no-cache always wins: forces a live search
@google --clear-cache # delete all cached results- Off by default — a plain
@google <query>always searches live; nothing is cached or read unless you pass--cache/--cache-ttlor setGOGL_CACHE_DIR/GOGL_CACHE_TTL. - Cache key is derived from the engine, the normalized query text, and the
result count, so
--engine duckduckgoand a different-nnever collide with (or return) another search's cached entry. The query itself is hashed, so it never appears in a cache filename. - Storage: one JSON file per search in
$GOGL_CACHE_DIR, or$XDG_CACHE_HOME/gogl, or~/.cache/goglby default. - Failure is silent: if the cache directory can't be read or written
(permissions, full disk, corrupt file),
goglfalls back to a live search rather than failing the command. - Also usable as a library option:
search('nodejs', { cache: true, cacheTtlSeconds: 300 }).
🐛 Troubleshooting
"Command not found: @google"
Solution: Make sure the package is installed globally:
npm install -g @spjoshis/gogl
npm list -g @spjoshis/gogl"Playwright browsers not found"
Solution: Install Playwright browsers:
npx playwright install"No results found" for queries that should return results
Possible causes:
- Google is blocking the automated requests
- Network connectivity issue
- Query is too restrictive or doesn't exist on Google
Solutions:
- Wait a few minutes and try again
- Check your internet connection
- Try a simpler query
- Try with the browser on your machine directly
- Try
--engine duckduckgoas an alternative; both engines apply anti-bot challenges to automated traffic (especially from datacenter/cloud IPs), so neither is guaranteed to bypass the other, but it's worth a shot
"Search timed out"
Causes: Network latency or Google blocking
Solutions:
- Check internet connection
- Try a simpler query
- Use a different network
- Try again in a few minutes
Playwright installation fails
Causes: Missing system dependencies or permission issues
Solutions:
# Reinstall Playwright
npm install --no-save playwright
npx playwright install
# Or with sudo if permission denied
sudo npx playwright install💡 Usage Tips
Search Operators
Google search operators work with @google:
# Search exact phrase
@google "exact phrase here"
# Exclude words
@google nodejs -java
# OR operator
@google nodejs OR javascript
# Site search
@google site:github.com nodejs tutorial
# Wildcard search
@google "how to * in node"Complex Queries
# Multiple conditions
@google nodejs best practices 2024
# Specific type search
@google tutorial for beginners javascript
# Combination search
@google "machine learning" python open sourcePiping Results
Process results with other commands:
# Count results
@google nodejs | wc -l
# Save to file
@google "web development" > results.txt
# Search results
@google python | grep -i tutorial📦 API Usage
You can also use @spjoshis/gogl as a library in your Node.js projects:
import { search, formatResults, dedupeResults } from '@spjoshis/gogl';
// Perform search (options are optional and backward compatible)
const results = await search('nodejs');
const fewer = await search('nodejs', { results: 5 }); // limit result count
const viaDdg = await search('nodejs', { engine: 'duckduckgo' }); // alternate engine
const cached = await search('nodejs', { cache: true, cacheTtlSeconds: 300 }); // reuse a fresh cached result
// Optionally drop duplicate-URL results (keeps the first occurrence)
const unique = dedupeResults(results);
// Format results
const formatted = formatResults(unique);
const colored = formatResults(unique, { color: true }); // ANSI-colored string
const asJson = formatResults(unique, { json: true }); // JSON string
// Print results
console.log(formatted);
// Each result object has:
// {
// title: string,
// url: string,
// description: string
// }🚀 Advanced Configuration
Environment Variables
Set these to change the built-in defaults without typing flags every time. A CLI flag always overrides the matching environment variable.
| Variable | Purpose | Default / Example |
|----------|---------|---------|
| GOGL_ENGINE | Default --engine value | export GOGL_ENGINE=duckduckgo |
| GOGL_RESULTS | Default --results value | export GOGL_RESULTS=5 |
| GOGL_JSON | Default --json value | export GOGL_JSON=true (also accepts 1/yes, and false/0/no) |
| NO_COLOR | Any non-empty value disables colorized output (see no-color.org) | unset |
| FORCE_COLOR | Enables colorized output even when not writing to a terminal | unset |
| GOGL_CACHE_DIR | Directory used to store cached results | $XDG_CACHE_HOME/gogl or ~/.cache/gogl |
| GOGL_CACHE_TTL | Default cache TTL in seconds (a --cache-ttl flag wins over this) | 3600 (1 hour) |
An unrecognized GOGL_ENGINE/GOGL_RESULTS/GOGL_JSON value is ignored with
a warning on stderr; it never crashes the command, and the built-in default
is used instead. See Caching for how the cache env vars are used.
export GOGL_ENGINE=duckduckgo
export GOGL_RESULTS=5
@google nodejs streams # uses duckduckgo, 5 results
@google --engine google nodejs streams # flag overrides the env defaultCLI Options
See Options above for the supported flags (--results, --json, --color,
--cache, --engine, --help, --version). Additional options may be added:
# Planned features:
# @google --filter "*.pdf" "query" # Filter by file type🤝 Contributing
Contributions are welcome! Here's how to contribute:
Fork the repository
git clone https://github.com/yourusername/gogl.gitCreate a feature branch
git checkout -b feature/amazing-featureMake your changes and add tests
npm testCommit with semantic messages
git commit -m "feat: add amazing feature"Push to your fork
git push origin feature/amazing-featureOpen a Pull Request
Code Style
- Use ESM (ES6 modules)
- Follow consistent naming conventions
- Add tests for new features
- Keep functions focused and single-responsibility
- Use meaningful variable names
Testing Requirements
- All tests must pass:
npm test - Add tests for new features
- Maintain >80% code coverage
- Test edge cases and error scenarios
📝 Commit Message Format
Use semantic commit messages:
feat: add new feature
fix: fix a bug
docs: documentation changes
test: add tests
refactor: refactor code
perf: performance improvements
chore: maintenance tasks📄 License
MIT License - see LICENSE file for details
This means you can:
- ✅ Use commercially
- ✅ Modify the code
- ✅ Distribute
- ✅ Use privately
But you must:
- ✅ Include a copy of the license
🙏 Acknowledgments
- Built with Playwright for browser automation
- Inspired by command-line search tools
- Thanks to all contributors
📞 Support
Getting Help
- GitHub Issues: Report bugs
- Discussions: Ask questions
- Documentation: Full docs
Reporting Issues
When reporting an issue, please include:
- Your Node.js version:
node --version - Your npm version:
npm --version - The exact command you ran
- The error message or unexpected behavior
- Steps to reproduce the issue
- Your operating system
Example issue:
**Node.js Version:** v18.0.0
**npm Version:** 8.0.0
**OS:** macOS 13.0
**Description:**
When I search for "nodejs", the command times out.
**Steps to Reproduce:**
1. Run: @google nodejs
2. Wait for response
3. See timeout error
**Expected:** Return top 10 results
**Actual:** Timeout after 30 seconds🎯 Roadmap
Planned features and improvements:
- [x] JSON output format option
- [ ] Filter results by date
- [x] Custom number of results
- [ ] Result caching
- [x] Multiple search engine support (Google, DuckDuckGo)
- [x] Colorized terminal output
- [ ] Rich table/box formatting
- [x] Result deduplication
- [ ] Search history
- [ ] Configuration file support
📊 Stats
- Package Size: ~2.3 kB (minified)
- Dependencies: 1 (Playwright)
- Test Coverage: 80%+
- Latest Version: 1.4.0
- Last Updated: 2026-09-24
🔐 Security
The tool:
- ✅ Does NOT store your search queries
- ✅ Does NOT collect usage data
- ✅ Does NOT track users
- ✅ Uses secure HTTPS connections to Google
- ✅ Runs entirely locally
Your privacy is respected. No data is collected or transmitted.
⚖️ Disclaimer
@spjoshis/gogl is an unofficial tool. It is not affiliated with, endorsed by, or connected to Google Inc.
Users are responsible for complying with:
- Google Terms of Service
- Google's Robots.txt
- All applicable local laws and regulations
🎓 Learn More
Made with ❤️ by spjoshis
