Skip to main content

ag — The Silver Searcher (Code Search Tool)

Introduction

ag (The Silver Searcher) is a fast text and code search tool designed for developers and operators who need quick, project-aware searching. It is often compared to ack and rg.

Tool Snapshot
  • Core Function: High-speed recursive text search in codebases.
  • Primary Benefit: Faster than grep by skipping ignored/binary files by default.
  • Where to Use: Large source code directories (e.g., WordPress plugins/themes).
  • Logic: Respects .gitignore and .agignore files to filter noise.

Key characteristics:

  • Optimized for searching source code quickly
  • Skips binary files by default
  • Respects .gitignore and common ignore rules (reduces noise in repositories)
  • Provides convenient file type filters (--php, --js, --css, etc.)
  • Works well in WordPress environments for scanning plugins, themes, configs, and logs

Use ag when you want a fast “search in project” experience with sensible defaults and minimal manual filtering.

Installation

Debian/Ubuntu:

sudo apt update
sudo apt install -y silversearcher-ag

Verify:

ag --version

Syntax & Expression Rules

The command follows a logical structure that reads almost like a sentence:

ag [OPTIONS] PATTERN [PATH]
  • [OPTIONS]: Flags to modify matching rules or output (e.g., -i, --php).
  • [PATTERN]: The text or regex pattern to search for.
  • [PATH]: File or directory to search (defaults to current directory if omitted).

Options Reference

Basic Searching

OptionDescription
-iCase-insensitive search
-sCase-sensitive search (default behavior)
-wMatch whole words only
-QLiteral search (treat pattern as plain text, no regex)
-vInvert match (show non-matching lines)
-qQuiet mode (no output, exit code only)

Output Control

OptionDescription
--
-nShow line numbers
-HShow filename (useful when searching a single file)
-cCount matches (usually per file)
-lList filenames with matches only
-oPrint only the matched part of the line
-m NUMStop after NUM matches

Context Control

OptionDescription
---
-A NUMShow NUM lines after match
-B NUMShow NUM lines before match
-C NUMShow NUM lines before and after match

File Handling

OptionDescription
--
--php, --js, --cssRestrict search to file type
--ignore-dir=DIRExclude a directory
--ignore=PATTERNExclude files matching pattern
-aSearch all files (including binary)
-uSearch ignored and hidden files (bypass ignore rules more aggressively)

Regex and Matching Controls

OptionDescription
---
-G REGEXSearch only files whose names match REGEX
-f FILERead patterns from FILE (one per line)

Utility

OptionDescription
---
--depth NUMLimit recursion depth
--statsPrint summary stats after search
--versionPrint version
--helpShow help

Pattern Matching Notes

ag supports regular expressions by default.

  • Use plain text patterns for simple matching

  • Use anchors for precise placement:

    • ^pattern start of line
    • pattern$ end of line
  • Use -Q to treat the pattern literally (recommended when the pattern contains regex characters like +, ., *, ?, (, ))

WordPress / VPS Examples (30)

Assumptions:

  • WordPress root: /var/www/html
  • Plugins: /var/www/html/wp-content/plugins
  • Themes: /var/www/html/wp-content/themes
  • Logs: /var/log/nginx/error.log

1. Search for DB credentials in wp-config

ag "DB_NAME" wp-config.php

Expected output:

3:define('DB_NAME', 'wpdb');

2. Case-insensitive search in logs

ag -i "error" /var/log/nginx/error.log

Expected output:

2025/10/03 [ERROR] Connection refused

3. Search only PHP files

ag --php "wp_enqueue_script" wp-content/

Expected output:

functions.php:12:wp_enqueue_script('theme-js', ...);

4. Search in CSS files

ag --css "color:" wp-content/themes/

Expected output:

style.css:18:color: #444;

5. List filenames with matches only

ag -l "add_action" wp-content/plugins/

Expected output:

plugin.php
hooks.php

6. Count matches

ag -c "define" wp-config.php

Expected output:

wp-config.php:8

7. Show line numbers

ag -n "DB_USER" wp-config.php

Expected output:

25:define('DB_USER', 'wpuser');

8. Match whole word

ag -w "admin" users.txt

Expected output:

admin

9. Invert match

ag -v "cache" plugins.txt

Expected output:

akismet
seo-plugin

10. Match at beginning of line

ag "^define" wp-config.php

Expected output:

define('DB_NAME', 'wpdb');

11. Match at end of line

ag "php$" filelist.txt

Expected output:

index.php
wp-config.php

12. Literal search (no regex interpretation)

ag -Q "a+b" file.txt

Expected output:

a+b

13. Regex OR pattern

ag "cat|dog" animals.txt

Expected output:

cat
dog

14. Show 2 lines of context around match

ag -C2 "DB_USER" wp-config.php

Expected output:

/** Database settings */
define('DB_NAME', 'wpdb');
define('DB_USER', 'wpuser');
define('DB_PASSWORD', 'secret');

15. Recursive search ignoring directory

ag "define" wp-content/ --ignore-dir=cache

Expected output:

functions.php:3:define('THEME_VERSION', '1.0');

16. Search hidden / ignored files

ag -u "DB_PASSWORD" /

Expected output:

.env:2:DB_PASSWORD=secret123

17. Search all files (including binaries)

ag -a "<?php" backups/

Expected output (example):

backup.tar.gz: contains <?php code

18. Stop after 1 match

ag -m1 "error" error.log

Expected output:

[error] File not found

19. Extract only match (URLs)

ag -o "https://[a-zA-Z0-9./]*" index.php

Expected output:

https://example.com

20. Limit search to filenames via regex

ag -G ".*\.php" "function" wp-content/

Expected output:

plugin.php:23:function custom_func() {

21. Search suspicious eval usage

ag "eval\(" wp-content/plugins/

Expected output:

bad-plugin.php:45:eval(base64_decode(...));

22. Multiple patterns (repeat -e)

ag -e "error" -e "warning" logs/

Expected output:

[error] file missing
[warning] deprecated function
ag "define" wp-config.php --stats

Expected output (example):

1 matches
1 files searched

24. Limit recursion depth

ag "pattern" --depth 2 wp-content/

Expected result: searches only 2 directory levels deep.

25. Find suspicious base64_decode usage

ag "base64_decode" wp-content/

Expected output:

malicious.php:40:eval(base64_decode(...));

26. Search in JavaScript only

ag --js "console.log" wp-content/themes/

Expected output:

main.js:12:console.log("Debugging");

27. Search CSS font-size rules

ag --css "font-size" wp-content/themes/

Expected output:

style.css:23:font-size: 16px;

28. Search comments in PHP

ag "^//" functions.php

Expected output:

// Theme setup
// Custom function

29. Search inside SQL dump

ag "CREATE TABLE" backup.sql

Expected output:

CREATE TABLE `wp_users` (
CREATE TABLE `wp_posts` (

30. Quiet mode (exit code only)

ag -q "DB_PASSWORD" wp-config.php && echo "Found"

Expected output:

Found

Benefits

  • Fast codebase searching with sensible defaults
  • Respects .gitignore to reduce noise
  • Skips binary files by default
  • Useful file type filters for common languages
  • Practical for WordPress troubleshooting and security scans

Best Practices

  • Use --php, --js, --css to avoid scanning irrelevant file types.
  • Use -G to narrow by filename patterns when type filters are not enough.
  • Use -Q for literal searches when patterns contain regex characters.
  • Use -C, -A, -B for context during debugging.
  • Use -u during security audits when hidden/ignored files must be included.
  • Avoid -a unless required; searching binaries can generate noisy results.

Troubleshooting Matrix

ProblemLikely CauseFix
-
No resultsCase mismatchAdd -i
Too many resultsBroad searchUse --php, --js, --css or -G
Missing resultsIgnored by defaultAdd -u
Binary file skippedDefault behaviorAdd -a
Regex unexpected behaviorPattern treated as regexUse -Q for literal

Cheat Sheet

ag "pattern" dir/
ag -i "error" error.log
ag --php "function" /var/www/html
ag -l "add_action" wp-content/plugins/
ag -c "define" wp-config.php
ag -A2 "pattern" file
ag -C2 "pattern" file
ag -o "https://.*" file
ag -u "DB_PASSWORD" /
ag -Q "a+b" file.txt

Mini Quiz

  1. What makes ag faster than traditional grep in codebases?
  2. How do you search only in PHP files?
  3. Which option includes hidden or ignored files?
  4. How do you show 2 lines after a match?
  5. Which option treats the pattern as a literal string?
  6. What is the purpose of -G?
  7. When should -a be avoided?
  8. Which option lists only filenames with matches?
  9. How do you stop after the first match?
  10. What option prints only the matched text?