Skip to content

Instantly share code, notes, and snippets.

@edwrdc
Created February 16, 2026 08:46
Show Gist options
  • Select an option

  • Save edwrdc/1f1d087b8b5c6b60ee1abe72fb24b4ef to your computer and use it in GitHub Desktop.

Select an option

Save edwrdc/1f1d087b8b5c6b60ee1abe72fb24b4ef to your computer and use it in GitHub Desktop.
ref-tools SKILL.md
#!/usr/bin/env node
/**
* Read URL content using Ref API
* Usage: ref-read.js "https://docs.python.org/3/library/asyncio.html"
*
* Session handling:
* - If --session-id is provided, uses that
* - Otherwise checks REF_SESSION_ID env var
* - Otherwise uses stored session from ~/.cache/ref/session
* - Prints active session to stderr for LLM awareness
*/
import { randomUUID } from "crypto";
import { readFileSync, writeFileSync, mkdirSync } from "fs";
import { dirname } from "path";
const API_URL = process.env.REF_URL || "https://api.ref.tools";
const SESSION_FILE = `${process.env.HOME}/.cache/ref/session`;
function ensureDir(path) {
try {
mkdirSync(dirname(path), { recursive: true });
} catch {}
}
function getStoredSession() {
try {
return readFileSync(SESSION_FILE, "utf-8").trim();
} catch {
return null;
}
}
function storeSession(sessionId) {
ensureDir(SESSION_FILE);
writeFileSync(SESSION_FILE, sessionId);
}
function getOrCreateSession(providedSessionId) {
// Priority: provided > env var > stored file > generate new
if (providedSessionId) return providedSessionId;
if (process.env.REF_SESSION_ID) return process.env.REF_SESSION_ID;
const stored = getStoredSession();
if (stored) return stored;
const newSession = `ref-${randomUUID()}`;
storeSession(newSession);
return newSession;
}
function getAuthHeaders(sessionId) {
const apiKey = process.env.REF_API_KEY;
if (!apiKey) {
const error = new Error(
"Missing Ref API credentials. " +
"Please set REF_API_KEY environment variable. " +
"Get your key at https://ref.tools/dashboard"
);
error.code = "MISSING_CREDENTIALS";
throw error;
}
const headers = {
"X-Ref-Api-Key": apiKey,
};
if (sessionId) {
headers["mcp-session-id"] = sessionId;
}
return headers;
}
function printUsage() {
console.log("Usage: ref-read.js <url> [--session-id <id>] [--new-session]");
console.log("\nOptions:");
console.log(" --session-id <id> Use specific session ID");
console.log(
" --new-session Generate a new session ID (clears stored session)",
);
console.log("\nEnvironment Variables:");
console.log(" REF_API_KEY API key for Ref (required)");
console.log(
" REF_URL Custom API URL (default: https://api.ref.tools)",
);
console.log(" REF_SESSION_ID Default session ID");
console.log("\nSession Storage:");
console.log(` Session ID is auto-saved to ${SESSION_FILE}`);
console.log(" Subsequent calls reuse the same session automatically");
console.log("\nExamples:");
console.log(
' ref-read.js "https://docs.python.org/3/library/asyncio.html"',
);
console.log(
' ref-read.js "https://fastapi.tiangolo.com/tutorial/" --session-id abc-123',
);
process.exit(1);
}
async function main() {
const args = process.argv.slice(2);
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
printUsage();
}
let url = "";
let sessionId = null;
let newSession = false;
// Parse arguments
for (let i = 0; i < args.length; i++) {
if (args[i] === "--session-id") {
sessionId = args[i + 1];
i++;
} else if (args[i] === "--new-session") {
newSession = true;
} else if (!url) {
url = args[i];
}
}
if (!url) {
console.error("Error: URL is required");
printUsage();
}
// Handle session logic
if (newSession) {
sessionId = `ref-${randomUUID()}`;
storeSession(sessionId);
console.error(`[New session: ${sessionId}]`);
} else {
sessionId = getOrCreateSession(sessionId);
// Only print session info if we created a new one or using stored
if (!process.env.REF_SESSION_ID && !args.includes("--session-id")) {
const stored = getStoredSession();
if (stored === sessionId) {
console.error(`[Using stored session: ${sessionId}]`);
}
}
}
const readUrl = `${API_URL}/read?url=${encodeURIComponent(url)}`;
try {
const response = await fetch(readUrl, {
headers: getAuthHeaders(sessionId),
});
if (response.status === 401) {
console.error(
"Error: 401 Unauthorized. Please verify your email at https://ref.tools/dashboard",
);
process.exit(1);
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
// Output content
console.log(data.content || "");
} catch (error) {
if (error.code === "MISSING_CREDENTIALS") {
console.error(`Error: ${error.message}`);
process.exit(2);
}
console.error(`Error reading URL: ${error.message}`);
process.exit(1);
}
}
main();
#!/usr/bin/env node
/**
* Search documentation using Ref API
* Usage: ref-search.js "python fastapi" [--session-id <id>]
*
* Session handling:
* - If --session-id is provided, uses that
* - Otherwise checks REF_SESSION_ID env var
* - Otherwise auto-generates and saves to ~/.cache/ref/session
* - Prints active session to stderr for LLM awareness
*/
import { randomUUID } from "crypto";
import { readFileSync, writeFileSync, mkdirSync } from "fs";
import { dirname } from "path";
const API_URL = process.env.REF_URL || "https://api.ref.tools";
const SESSION_FILE = `${process.env.HOME}/.cache/ref/session`;
function ensureDir(path) {
try {
mkdirSync(dirname(path), { recursive: true });
} catch {}
}
function getStoredSession() {
try {
return readFileSync(SESSION_FILE, "utf-8").trim();
} catch {
return null;
}
}
function storeSession(sessionId) {
ensureDir(SESSION_FILE);
writeFileSync(SESSION_FILE, sessionId);
}
function getOrCreateSession(providedSessionId) {
// Priority: provided > env var > stored file > generate new
if (providedSessionId) return providedSessionId;
if (process.env.REF_SESSION_ID) return process.env.REF_SESSION_ID;
const stored = getStoredSession();
if (stored) return stored;
const newSession = `ref-${randomUUID()}`;
storeSession(newSession);
return newSession;
}
function getAuthHeaders(sessionId) {
const apiKey = process.env.REF_API_KEY;
if (!apiKey) {
const error = new Error(
"Missing Ref API credentials. " +
"Please set REF_API_KEY environment variable. " +
"Get your key at https://ref.tools/dashboard"
);
error.code = "MISSING_CREDENTIALS";
throw error;
}
const headers = {
"X-Ref-Api-Key": apiKey,
};
if (sessionId) {
headers["mcp-session-id"] = sessionId;
}
return headers;
}
function printUsage() {
console.log(
"Usage: ref-search.js <query> [--session-id <id>] [--new-session]",
);
console.log("\nOptions:");
console.log(
" --session-id <id> Use specific session ID for deduplication",
);
console.log(
" --new-session Generate a new session ID (clears stored session)",
);
console.log("\nEnvironment Variables:");
console.log(" REF_API_KEY API key for Ref (required)");
console.log(
" REF_URL Custom API URL (default: https://api.ref.tools)",
);
console.log(" REF_SESSION_ID Default session ID");
console.log("\nSession Storage:");
console.log(` Session ID is auto-saved to ${SESSION_FILE}`);
console.log(" Subsequent calls reuse the same session automatically");
console.log("\nExamples:");
console.log(' ref-search.js "python fastapi"');
console.log(' ref-search.js "react hooks" --session-id abc-123');
console.log(' ref-search.js "new topic" --new-session');
process.exit(1);
}
async function main() {
const args = process.argv.slice(2);
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
printUsage();
}
let query = "";
let sessionId = null;
let newSession = false;
// Parse arguments
for (let i = 0; i < args.length; i++) {
if (args[i] === "--session-id") {
sessionId = args[i + 1];
i++;
} else if (args[i] === "--new-session") {
newSession = true;
} else if (!query) {
query = args[i];
}
}
if (!query) {
console.error("Error: Query is required");
printUsage();
}
// Handle session logic
if (newSession) {
sessionId = `ref-${randomUUID()}`;
storeSession(sessionId);
console.error(`[New session: ${sessionId}]`);
} else {
sessionId = getOrCreateSession(sessionId);
// Only print session info if we created a new one or using stored
if (!process.env.REF_SESSION_ID && !args.includes("--session-id")) {
const stored = getStoredSession();
if (stored === sessionId) {
console.error(`[Using stored session: ${sessionId}]`);
}
}
}
const url = `${API_URL}/search_documentation?query=${encodeURIComponent(query)}`;
try {
const response = await fetch(url, {
headers: getAuthHeaders(sessionId),
});
if (response.status === 401) {
console.error(
"Error: 401 Unauthorized. Please verify your email at https://ref.tools/dashboard",
);
process.exit(1);
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
if (!data.docs || data.docs.length === 0) {
console.log("No results found");
process.exit(0);
}
// Output results as formatted text
for (const doc of data.docs) {
console.log(`overview: ${doc.overview || doc.title || ""}`);
console.log(`url: ${doc.url}`);
console.log(`moduleId: ${doc.moduleId || ""}`);
console.log("---");
}
} catch (error) {
if (error.code === "MISSING_CREDENTIALS") {
console.error(`Error: ${error.message}`);
process.exit(2);
}
console.error(`Error during search: ${error.message}`);
process.exit(1);
}
}
main();
name ref-api
description Search documentation and read URLs via Ref's REST API with automatic session tracking for optimized multi-step searches. Use when you need to search technical docs or fetch URL content. Sessions are auto-managed - subsequent calls automatically reuse the same session to avoid duplicate results.

Ref API Skill

Direct API access to Ref's documentation search and URL reading tools. More context-efficient than MCP protocol for documentation workflows.

Session Handling (Automatic)

The scripts automatically manage sessions to minimize token usage:

  1. First call - Auto-generates a session ID and saves it to ~/.cache/ref/session
  2. Subsequent calls - Automatically reuse the stored session
  3. New research topic - Use --new-session to start fresh

The active session is printed to stderr so you can see which session is being used.

Quick Start

# Search for documentation
./scripts/ref-search.js "python fastapi dependency injection"

# Read a result URL
./scripts/ref-read.js "https://fastapi.tiangolo.com/tutorial/dependencies/"

# Refine your search (auto-uses same session, no duplicates)
./scripts/ref-search.js "fastapi depends callable"

Commands

Search Documentation

./scripts/ref-search.js "<query>"

Options:

  • --session-id <id> - Use a specific session ID
  • --new-session - Start a new research session (clears stored session)

Query tips:

  • Include programming language and framework names
  • Add ref_src=private to search user's private docs/repos

Example workflow:

# First search - creates session automatically
./scripts/ref-search.js "react hooks"
# [Using stored session: ref-abc-123]
# → Returns results

# Follow-up search - reuses session, avoids duplicates
./scripts/ref-search.js "react useEffect cleanup"
# [Using stored session: ref-abc-123]
# → Returns only NEW results

# New topic - clear session
./scripts/ref-search.js "python asyncio" --new-session
# [New session: ref-xyz-789]

Read URL Content

./scripts/ref-read.js "<url>"

Important: Pass the EXACT url from a search result. Content is returned as markdown.

# Read a doc from search results
./scripts/ref-read.js "https://react.dev/reference/react/useEffect"

# Use specific session
./scripts/ref-read.js "https://react.dev/reference/react/useEffect" --session-id ref-abc-123

Environment Variables

Required:

export REF_API_KEY="your-api-key"        # Get your key at https://ref.tools/dashboard

Optional:

export REF_URL="https://api.ref.tools"   # Custom API endpoint
export REF_SESSION_ID="my-session"       # Override stored session

Complete Workflow Example

# 1. Search for FastAPI middleware info
$ ./scripts/ref-search.js "fastapi middleware"
[Using stored session: ref-a1b2c3d4]
overview: Middleware - FastAPI
url: https://fastapi.tiangolo.com/tutorial/middleware/
moduleId: fastapi-official
---
overview: CORSMiddleware - FastAPI  
url: https://fastapi.tiangolo.com/tutorial/cors/
moduleId: fastapi-official
---

# 2. Read the CORS middleware docs
$ ./scripts/ref-read.js "https://fastapi.tiangolo.com/tutorial/cors/"
[Using stored session: ref-a1b2c3d4]
# CORSMiddleware

FastAPI provides a CORS middleware...

# 3. Refine search - reuses session, skips already-seen results
$ ./scripts/ref-search.js "fastapi cors origin regex"
[Using stored session: ref-a1b2c3d4]
# → Only returns new results not shown in previous searches

# 4. New topic - clear session
$ ./scripts/ref-search.js "django middleware" --new-session
[New session: ref-e5f6g7h8]

Error Handling

Error Solution
401 Unauthorized Verify email at https://ref.tools/dashboard
No API key Set REF_API_KEY environment variable
No results Try broader search terms

Comparison: Direct API vs MCP

Aspect Direct API (this skill) MCP Protocol
Context usage Low - direct text output Higher - JSON-RPC overhead
Session handling Automatic via file storage Managed by MCP server
Setup complexity None - just run scripts Requires MCP server connection
Best for Documentation lookups in scripts Complex multi-tool workflows

Use this skill when you need efficient documentation searches with minimal context overhead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment