You find a useful code pattern on Stack Overflow. You copy it somewhere β a text file, a Notion page, a GitHub Gist. Three weeks later, you need it again and canβt find it.
In this tutorial, weβll build snip β a CLI tool that saves code snippets and uses AI to auto-tag, describe, and search them. Save a snippet in 5 seconds, find it in 2.
What weβre building
# Save a snippet (AI auto-generates tags and description)
$ snip save "Express error handler middleware"
# Opens your $EDITOR, paste the code, save and close
β
Saved: Express error handler middleware
Tags: express, middleware, error-handling, nodejs
Language: javascript
# Search by natural language
$ snip find "how to handle errors in express"
1. Express error handler middleware (javascript)
Tags: express, middleware, error-handling, nodejs
Saved: 2026-03-25
# View the snippet
$ snip show 1
The code
#!/usr/bin/env node
// index.js
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
import { homedir } from 'os';
import { join } from 'path';
import { execSync } from 'child_process';
import Anthropic from '@anthropic-ai/sdk';
const STORE = join(homedir(), '.snip');
const DB = join(STORE, 'snippets.json');
if (!existsSync(STORE)) mkdirSync(STORE);
if (!existsSync(DB)) writeFileSync(DB, '[]');
const snippets = JSON.parse(readFileSync(DB, 'utf-8'));
const save = () => writeFileSync(DB, JSON.stringify(snippets, null, 2));
const anthropic = new Anthropic();
const [,, command, ...args] = process.argv;
if (command === 'save') {
const title = args.join(' ') || 'Untitled snippet';
// Open editor for code input
const tmpFile = join(STORE, 'tmp.txt');
writeFileSync(tmpFile, '');
execSync(`${process.env.EDITOR || 'nano'} ${tmpFile}`, { stdio: 'inherit' });
const code = readFileSync(tmpFile, 'utf-8').trim();
if (!code) { console.log('Empty snippet, not saved.'); process.exit(0); }
// AI generates tags and description
const response = await anthropic.messages.create({
model: 'claude-haiku-3.5',
max_tokens: 200,
messages: [{
role: 'user',
content: `Analyze this code snippet titled "${title}":
\`\`\`
${code.slice(0, 2000)}
\`\`\`
Return JSON only:
{"language": "...", "tags": ["tag1", "tag2", ...], "description": "one sentence description"}
Use lowercase tags. Max 6 tags. Be specific (e.g., "react-hooks" not just "react").`
}],
});
let meta;
try {
meta = JSON.parse(response.content[0].text);
} catch {
meta = { language: 'unknown', tags: [], description: title };
}
snippets.push({
id: snippets.length + 1,
title,
code,
...meta,
created: new Date().toISOString().split('T')[0],
});
save();
console.log(`β
Saved: ${title}`);
console.log(` Tags: ${meta.tags.join(', ')}`);
console.log(` Language: ${meta.language}`);
} else if (command === 'find') {
const query = args.join(' ').toLowerCase();
const results = snippets.filter(s =>
s.title.toLowerCase().includes(query) ||
s.tags.some(t => t.includes(query)) ||
s.description.toLowerCase().includes(query) ||
s.language.includes(query)
);
if (!results.length) { console.log('No snippets found.'); process.exit(0); }
results.forEach(s => {
console.log(`${s.id}. ${s.title} (${s.language})`);
console.log(` Tags: ${s.tags.join(', ')}`);
console.log(` ${s.created}\n`);
});
} else if (command === 'show') {
const id = parseInt(args[0]);
const snippet = snippets.find(s => s.id === id);
if (!snippet) { console.log('Snippet not found.'); process.exit(1); }
console.log(`# ${snippet.title}`);
console.log(`# ${snippet.description}`);
console.log(`# Tags: ${snippet.tags.join(', ')}\n`);
console.log(snippet.code);
} else if (command === 'list') {
snippets.forEach(s => console.log(`${s.id}. ${s.title} (${s.language}) β ${s.created}`));
} else {
console.log('Usage: snip <save|find|show|list> [args]');
console.log(' snip save "title" Save a new snippet');
console.log(' snip find "query" Search snippets');
console.log(' snip show <id> Show a snippet');
console.log(' snip list List all snippets');
}
Setup
mkdir snip-cli && cd snip-cli
npm init -y && npm install @anthropic-ai/sdk
# Add "bin": {"snip": "./index.js"} to package.json
chmod +x index.js && npm link
Usage examples
# Save from clipboard (macOS)
pbpaste | snip save "Docker multi-stage build"
# Save interactively
snip save "PostgreSQL connection pool setup"
# Editor opens, paste code, save
# Find snippets
snip find "docker"
snip find "authentication"
snip find "python"
# List everything
snip list
Making it better
- Semantic search: Use embeddings instead of keyword matching for smarter search
- Sync: Store snippets in a GitHub Gist for cross-machine access
- Import: Bulk import from GitHub Gists or a snippets folder
- Export: Generate a searchable HTML page of all your snippets
- Pipe support:
cat file.js | snip save "my utility functions"
Total build time: ~30 minutes. API cost: ~$0.001 per snippet (Haiku).
Related: Best AI Coding Tools 2026 Β· VS Code Keyboard Shortcuts Β· Build a Git Diff Summarizer Β· Build Meeting Notes Summarizer