About
CLI for managing tags in Obsidian with Claude Code
README
Test Go Report Card Go Version License
A powerful CLI tool and MCP server for managing tags in Obsidian vaults. Provides Claude Code with precise tag management capabilities while also offering a comprehensive command-line interface for direct use.
Features
- 🏷️ Comprehensive Tag Support: Hashtags (
#tag) and YAML frontmatter (arrays and lists) - 🧠 Advanced Filtering: Intelligent filtering of hex colors, IDs, URLs, and noise
- ⚡ Memory Efficient: Streaming file processing using Go 1.23 iterators
- 🔄 Batch Operations: Batch tag replacement with individual error reporting
- 🔌 Dual Mode: CLI tool + MCP server for Claude Code integration
Installation
go install github.com/thrawn01/tag-manager/cmd/tag-manager@latest
Verify installation
$ tag-manager --help
Quick Start
List all tags in your Obsidian vault
$ tag-manager list
Found 652 tags:
#daily-notes 814 files
#people 49 files
#blog 17 files
#startups 17 files
#book 16 files
-- snip --
Find files with specific tags
$ tag-manager find --tags="golang,programming"
#golang (6 files):
Interests/Technology/Concepts/Programming/Language/Golang.md
Interests/Technology/Concepts/Programming/Patterns/Logging Guide.md
Interests/Technology/Language/Golang Trace Profile Example.md
Interests/Technology/Latency.md
Calendar Notes/2022/07 July/2022-07-25.md
#programming (11 files):
Projects/Writing/Published/Mastering HTTP REST Design.md
Things/Education/Education.md
Interests/Software Development.md
Interests/Technology/Algorithms and Protocols/Binary Tree.md
Interests/Technology/Algorithms and Protocols/Ring Buffer.md
Interests/Technology/Concepts/Cognitive Load.md
Interests/Technology/Programming/Language/Golang.md
Interests/Technology/Programming/Patterns/Object Oriented Programming.md
Interests/Technology/Latency.md
-- snip --
Replace a tag across your vault (dry run first!)
tag-manager replace --old="old-tag" --new="new-tag" --root="/vault" --dry-run
DRY RUN MODE - No files will be modified
Modified files: 6
Claude MCP Server
claude mcp add -s project tag-manager -- tag-manager -mcp
CLI Usage Guide
📋 Command Reference
| Command | Purpose | Example |
|---|---|---|
list |
Show all tags with usage counts | tag-manager list |
find |
Find files containing specific tags | tag-manager find --tags="golang,python" |
replace |
Rename/replace tags across files | tag-manager replace --old="old" --new="new" |
untagged |
Find files without any tags | tag-manager untagged |
validate |
Check tag syntax and get suggestions | tag-manager validate --tags="test-tag,invalid!" |
file-tags |
Show tags for specific files | tag-manager file-tags --files="file1.md,file2.md" |
info |
Get detailed tag information | tag-manager info --tags="golang,python" |
🔍 Finding Files by Tags
# Find files with single tag
tag-manager find --tags="golang" --root="/vault"
# Find files with multiple tags (OR logic)
tag-manager find --tags="golang,python,programming" --root="/vault"
# Limit results and output as JSON
tag-manager find --tags="golang" --root="/vault" --max-results=10 --json
# Find with hashtag prefix (both work the same)
tag-manager find --tags="#golang" --root="/vault"
tag-manager find --tags="golang" --root="/vault"
📊 Listing All Tags
# List all tags with usage counts
tag-manager list --root="/vault"
# Filter tags by minimum usage count
tag-manager list --root="/vault" --min-count=5
# Filter tags by pattern (contains "dev")
tag-manager list --root="/vault" --pattern="dev"
# Combine filters and output as JSON
tag-manager list --root="/vault" --min-count=2 --pattern="programming" --json
🔄 Replacing/Renaming Tags
# Single tag replacement (always dry-run first!)
tag-manager replace --old="javascript" --new="js" --root="/vault" --dry-run
# Apply the changes after reviewing
tag-manager replace --old="javascript" --new="js" --root="/vault"
# Multiple tag replacements in one command
tag-manager replace --replacements="js:javascript,py:python,ts:typescript" --root="/vault" --dry-run
# Global dry-run flag (affects all subcommands that modify files)
tag-manager --dry-run replace --old="test" --new="testing" --root="/vault"
🏷️ Tag Information
# Get detailed info about specific tags
tag-manager info --tags="golang,python" --root="/Users/john/vault"
# Limit files shown per tag
tag-manager info --tags="golang" --root="/Users/john/vault" --max-files-per-tag=5 --json
📝 Finding Untagged Files
# Find all files without any tags
tag-manager untagged --root="/Users/john/vault"
# Output as JSON for processing
tag-manager untagged --root="/Users/john/vault" --json | jq '.[] | .path'
✅ Validating Tags
# Validate tag syntax
tag-manager validate --tags="valid-tag,invalid!,toolong123456789"
# Get suggestions for invalid tags
tag-manager validate --tags="test-tag,123invalid,special@chars" --json
📄 Getting Tags from Specific Files
# Get tags from specific files
tag-manager file-tags --files="/vault/note1.md,/vault/note2.md"
# Process multiple files with JSON output
find /vault -name "*.md" -print0 | \
xargs -0 -I {} tag-manager file-tags --files="{}" --json
Global Options
| Option | Description | Example |
|---|---|---|
-h, --help |
Show help message | tag-manager -h |
-v, --verbose |
Enable verbose output | tag-manager -v list |
--dry-run |
Preview changes without modifying files | tag-manager --dry-run replace --old=test --new=testing |
--config FILE |
Use custom configuration file | tag-manager --config=custom.yaml list |
Configuration
Default Configuration
The tool uses intelligent defaults optimized for Obsidian vaults:
# These directories are automatically excluded
exclude_dirs:
- "100 Archive" # Common archive folder
- "Attachments" # Media files
- ".git" # Version control
- ".obsidian" # Obsidian settings
# These file patterns are excluded
exclude_patterns:
- "*.excalidraw.md" # Excalidraw drawings
- "*.canvas" # Canvas files
# Tag extraction patterns (advanced users only)
hashtag_pattern: "#[a-zA-Z][\\w\\-]*"
yaml_tag_pattern: "(?m)^tags:\\s*\\[([^\\]]+)\\]"
yaml_list_pattern: "(?m)^tags:\\s*$\\n((?:\\s+-\\s+.+\\n?)+)"
# Tag validation rules
min_tag_length: 3 # Minimum characters
max_digit_ratio: 0.5 # Maximum 50% digits
# Keywords that are automatically filtered out
exclude_keywords:
- "bibr" # Bibliography references
- "ftn" # Footnotes
- "issuecomment" # GitHub issue comments
- "discussion" # GitHub discussions
- "diff-" # Git diff markers
Custom Configuration
Create a config.yaml file to override defaults:
# Example: config.yaml
min_tag_length: 2
max_digit_ratio: 0.7
exclude_dirs:
- "Archive"
- "Templates"
- "Daily Notes"
exclude_keywords:
- "temp"
- "draft"
- "wip"
# Add custom exclusions without losing defaults
additional_exclude_dirs:
- "Personal"
- "Private"
Use with: tag-manager --config=config.yaml list --root=/vault
Tag Formats Supported
1. Hashtag Format (Inline Tags)
# My Programming Note
This note covers #golang and #web-development.
I'm also learning #data-structures and #algorithms.
## Advanced Topics
- #concurrency in Go
- #design-patterns for scalable systems
2. YAML Frontmatter - Array Format
---
title: "Advanced Go Programming"
tags: ["golang", "programming", "concurrency", "web-development"]
date: 2024-01-15
---
# Content goes here
3. YAML Frontmatter - List Format
---
title: "Learning Python"
tags:
- python
- programming
- data-science
- machine-learning
author: John Doe
---
# Content goes here
4. Mixed Format Support
---
tags: ["yaml-tag", "frontmatter"]
---
# Mixed Tags Example
This note has both YAML frontmatter tags above and
inline hashtags like #programming and #tutorial.
Smart Tag Filtering
The tool automatically filters out common false positives:
❌ Filtered Out (False Positives)
- Hex Colors:
#ff0000,#abc123,#ffffff - GitHub References:
#123,#456(issue numbers) - URL Fragments:
#section,#top,#http - High Digit Ratio:
#abc123456789(>50% digits) - Short Tags:
#go,#js(less than 3 chars) - Noise Keywords:
#bibr123,#ftn1,#issuecomment - ID-like Strings:
#aB3dEf9H2jK4lM(looks like generated ID)
✅ Kept (Real Tags)
- Descriptive Tags:
#golang,#programming,#web-development - Valid Short Forms:
#api,#css,#sql(configurable) - Hyphenated Tags:
#machine-learning,#data-science - Underscore Tags:
#data_structures,#unit_testing
Advanced Usage Examples
Batch Tag Management Workflow
# 1. First, explore your vault's tags
tag-manager list --root=/vault --min-count=2
# 2. Find inconsistent naming
tag-manager list --root=/vault --pattern="js\|javascript"
# 3. Plan replacements (dry-run)
tag-manager replace --replacements="js:javascript,py:python" --root=/vault --dry-run
# 4. Apply changes
tag-manager replace --replacements="js:javascript,py:python" --root=/vault
# 5. Verify results
tag-manager find --tags="javascript,python" --root=/vault --json
Finding Maintenance Issues
# Find files that need tags
tag-manager untagged --root=/vault
# Find tags that might be typos (very low usage)
tag-manager list --root=/vault --min-count=1 --json | jq '.[] | select(.count == 1)'
# Validate existing tags for syntax issues
tag-manager list --root=/vault --json | \
jq -r '.[] | .name' | \
xargs tag-manager validate --tags
Integration with Other Tools
# Export all tags as a list
tag-manager list --root=/vault --json | jq -r '.[].name' > all-tags.txt
# Find files with specific tag and open in editor
tag-manager find --tags="todo" --root=/vault --json | \
jq -r '.todo[]' | \
head -5 | \
xargs code # Opens in VS Code
# Generate tag usage report
tag-manager list --root=/vault --json | \
jq -r '["Tag", "Count", "Files"], (.[] | [.name, .count, (.files | length)]) | @csv' > report.csv
Error Handling & Recovery
Batch Operations Are Non-Atomic
{
"replacements": [
{"old_tag": "javascript", "new_tag": "js"},
{"old_tag": "python", "new_tag": "py"}
],
"modified_files": [
"/vault/note1.md",
"/vault/note2.md"
],
"failed_files": [
"/vault/readonly.md"
],
"errors": [
"/vault/readonly.md: permission denied"
],
"dry_run": false
}
Benefits:
- ✅ Partial success is preserved
- ✅ Individual file errors don't stop the entire operation
- ✅ Operations are idempotent (safe to retry)
- ✅ Clear error reporting per file
Common Error Scenarios
# Permission denied - make files writable
chmod -R u+w /path/to/vault
tag-manager replace --old="test" --new="testing" --root="/path/to/vault"
# Invalid configuration - check regex patterns
tag-manager --config=custom.yaml list --root=/vault
# Error: invalid hashtag pattern: missing closing bracket
# Path traversal protection
tag-manager list --root="../../../etc"
# Error: path contains directory traversal
MCP Server Mode (Claude Code Integration)
Setup for Claude Code
Start the MCP server:
claude mcp add -s project tag-manager -- tag-manager -mcp
Configure Claude Code (.mcp.json):
{
"mcpServers": {
"tag-manager": {
"type": "stdio",
"command": "tag-manager",
"args": [
"-mcp",
],
"env": {}
}
}
}
Available MCP Tools
| Tool | Purpose | Parameters |
|---|---|---|
find_files_by_tags |
Find files containing tags | tags, root_path, max_results |
get_tags_info |
Detailed tag information | tags, root_path, max_files_per_tag |
list_all_tags |
List all tags with stats | root_path, min_count, pattern, max_results |
replace_tags_batch |
Batch tag replacement | replacements, root_path, dry_run |
get_untagged_files |
Find untagged files | root_path, max_results |
validate_tags |
Validate tag syntax | tags, include_suggestions |
get_files_tags |
Get tags from specific files | file_paths, max_files |
Performance & Scalability
Memory Usage
- Constant Memory: Uses Go iterators for streaming processing
- Large Vaults: Tested with 1000+ files, memory stays constant
Performance Tips
# For very large vaults, use filters to reduce scope
tag-manager list --root=~/huge-vault --min-count=5
# Process subsets of files
tag-manager find --tags="golang" --root=/vault/programming-notes
# Use JSON output for programmatic processing (faster parsing)
tag-manager list --root=/vault --json | jq '.[] | select(.count > 10)'
Benchmarks
- Small Vault (100 files): ~50ms
- Medium Vault (1000 files): ~500ms
- Large Vault (5000 files): ~2.5s
- Memory Usage: <10MB regardless of vault size
Troubleshooting
Common Issues
🚫 "No tags found"
# Check file extensions (only .md files processed)
find /vault -name "*.md" | wc -l
# Check if files have actual tags
grep -r "#" /vault/*.md | head -5
# Verify exclude patterns aren't too broad
tag-manager --config=minimal.yaml list --root=/vault
🚫 "Permission denied"
# Make files writable
find /vault -name "*.md" -not -writable
chmod u+w /vault/*.md
# Run dry-run first to preview changes
tag-manager --dry-run replace --old=test --new=testing --root=/vault
🚫 "Invalid regex configuration"
# Test your custom patterns
tag-manager validate --tags="test" --config=custom.yaml
# Error: invalid hashtag pattern: [missing bracket
# Use default config to verify the tool works
tag-manager list --root=/vault # Uses defaults
🚫 "MCP server not responding"
# Test MCP server manually
tag-manager -mcp --config=test.yaml
# Should start without errors and wait for input
# Check Claude Code logs for connection issues
# Verify paths in claude_desktop_config.json
Debug Mode
# Enable verbose logging
tag-manager -v list --root=/vault
# See what files are being processed
tag-manager -v find --tags=golang --root=/vault
# Debug MCP server (check stderr)
tag-manager -mcp -v 2>debug.log
Getting Help
# General help
tag-manager --help
# Command-specific help
tag-manager find --help
tag-manager replace --help
# Show current configuration
tag-manager list --root=. --json | jq '.config' 2>/dev/null || echo "Using defaults"
Development
Building from Source
git clone https://github.com/thrawn01/tag-manager.git
cd tag-manager
# Run tests
go test -v ./...
# Build binary
go build -o tag-manager ./cmd/tag-manager
# Install to GOPATH/bin
go install ./cmd/tag-manager
Using the Makefile
make help # Show available targets
make build # Build binary
make test # Run tests
make test-coverage # Run tests with coverage
make install # Install to GOPATH/bin
make clean # Clean build artifacts
make demo # Create demo data and run examples
Testing with Sample Data
# Create test vault
make test-data
# Run demo commands
make demo
# Test MCP server
make mcp-server # In one terminal
# Test with Claude Code or manual JSON-RPC calls
Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Write tests for new functionality
- Ensure tests pass:
go test ./... - Submit a pull request
Code Style
- Follow standard Go conventions
- Add tests for new features
- Update documentation for user-facing changes
- Use meaningful commit messages
License
MIT License - see LICENSE file for details.
Acknowledgments
- Built for the Obsidian community
- Designed for Claude Code integration
- Inspired by the need for intelligent tag management
- Built by Claude Code (See tag-manager-plan.md)
Installing Tag Manager
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/thrawn01/tag-managerFAQ
Is Tag Manager MCP free?
Yes, Tag Manager MCP is free — one-click install via Unyly at no cost.
Does Tag Manager need an API key?
No, Tag Manager runs without API keys or environment variables.
Is Tag Manager hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install Tag Manager in Claude Desktop, Claude Code or Cursor?
Open Tag Manager on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
GitHub
PRs, issues, code search, CI status
by GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
by mcpdotdirectAmap Maps Mcp Server
MCP server for using the AMap Maps API
by duxiaohuiSupabase
Database, auth and storage
by SupabaseEverything
Reference / test server with prompts, resources, and tools.
Git
Tools to read, search, and manipulate Git repositories.
Sequential Thinking
Dynamic and reflective problem-solving through thought sequences.
Time
Time and timezone conversion capabilities.
Compare Tag Manager with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All development MCPs
