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.
- Core Function: High-speed recursive text search in codebases.
- Primary Benefit: Faster than
grepby skipping ignored/binary files by default. - Where to Use: Large source code directories (e.g., WordPress plugins/themes).
- Logic: Respects
.gitignoreand.agignorefiles to filter noise.
Key characteristics:
- Optimized for searching source code quickly
- Skips binary files by default
- Respects
.gitignoreand 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
| Option | Description |
|---|---|
-i | Case-insensitive search |
-s | Case-sensitive search (default behavior) |
-w | Match whole words only |
-Q | Literal search (treat pattern as plain text, no regex) |
-v | Invert match (show non-matching lines) |
-q | Quiet mode (no output, exit code only) |
Output Control
| Option | Description |
|---|---|
| -- | |
-n | Show line numbers |
-H | Show filename (useful when searching a single file) |
-c | Count matches (usually per file) |
-l | List filenames with matches only |
-o | Print only the matched part of the line |
-m NUM | Stop after NUM matches |
Context Control
| Option | Description |
|---|---|
| -- | - |
-A NUM | Show NUM lines after match |
-B NUM | Show NUM lines before match |
-C NUM | Show NUM lines before and after match |
File Handling
| Option | Description |
|---|---|
| -- | |
--php, --js, --css | Restrict search to file type |
--ignore-dir=DIR | Exclude a directory |
--ignore=PATTERN | Exclude files matching pattern |
-a | Search all files (including binary) |
-u | Search ignored and hidden files (bypass ignore rules more aggressively) |
Regex and Matching Controls
| Option | Description |
|---|---|
| - | -- |
-G REGEX | Search only files whose names match REGEX |
-f FILE | Read patterns from FILE (one per line) |
Utility
| Option | Description |
|---|---|
| - | -- |
--depth NUM | Limit recursion depth |
--stats | Print summary stats after search |
--version | Print version |
--help | Show help |
Pattern Matching Notes
ag supports regular expressions by default.
-
Use plain text patterns for simple matching
-
Use anchors for precise placement:
^patternstart of linepattern$end of line
-
Use
-Qto 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
23. Show stats after search
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
.gitignoreto 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,--cssto avoid scanning irrelevant file types. - Use
-Gto narrow by filename patterns when type filters are not enough. - Use
-Qfor literal searches when patterns contain regex characters. - Use
-C,-A,-Bfor context during debugging. - Use
-uduring security audits when hidden/ignored files must be included. - Avoid
-aunless required; searching binaries can generate noisy results.
Troubleshooting Matrix
| Problem | Likely Cause | Fix |
|---|---|---|
| - | ||
| No results | Case mismatch | Add -i |
| Too many results | Broad search | Use --php, --js, --css or -G |
| Missing results | Ignored by default | Add -u |
| Binary file skipped | Default behavior | Add -a |
| Regex unexpected behavior | Pattern treated as regex | Use -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
- What makes
agfaster than traditionalgrepin codebases? - How do you search only in PHP files?
- Which option includes hidden or ignored files?
- How do you show 2 lines after a match?
- Which option treats the pattern as a literal string?
- What is the purpose of
-G? - When should
-abe avoided? - Which option lists only filenames with matches?
- How do you stop after the first match?
- What option prints only the matched text?