auditreach
About
BYOK Reddit/YouTube research CLI with a tamper-evident audit log and an MCP server.
Details
- Author
- rudrendupaul
- Categories
- Search, Knowledge Base, Other
Jump to
Setup
Install auditreach in your MCP client (Claude Desktop, Cursor, Windsurf, and others).
Repository: https://github.com/rudrendupaul/auditreach
Follow the installation instructions in the repository README, then restart your MCP client.
Install•What it does•Getting started•Commands•Security•FAQ
Research Reddit and YouTube from your AI agent using only official APIs, your own keys, and a log that proves exactly what you queried and why it was allowed.
auditreach ships as two independent, equally first-class packages: an npm package (this repo, JavaScript/TypeScript) and aPyPI package(python/, Python). Both implement the same hash-chain algorithm and BYOK model against the same official Reddit/YouTube APIs. Pick whichever fits your toolchain, or install both.
npx auditreach-cli search --platform reddit --query "your query"
npm install -g auditreach-cli auditreach search --platform reddit --query "your query"
pip install auditreach-cli auditreach search --platform reddit --query "your query"
Building from source works the same way, if you want to read or modify the code first:
git clone https://github.com/RudrenduPaul/auditreach.git cd auditreach npm install npm run build node dist/cli.js search --platform reddit --query "your query"
node dist/cli.js search --platform reddit --query "agent memory poisoning" --subreddit MachineLearning AuditReach -- Official-API Research CLI Platform: Reddit | Auth: OAuth script-app grant, read-only, public-subreddit scope Fetching... (official API, rate-limit aware) ✓ 14 results returned (Reddit API Terms -- public content, official API, read-only script-app credentials) RESULTS (14) [1] "How are people testing for memory poisoning in long-running agents?" u/some_researcher · 2026-07-05T14:22:00.000Z https://reddit.com/r/MachineLearning/comments/... ... Audit log entry written: ar_2026-07-12_9f3c2a Consent basis: Reddit API Terms -- public content, official API, read-only script-app credentials Full results: ./auditreach-results-2026-07-12.json Full audit trail: ./auditreach.log.jsonl
Every entry inauditreach.log.jsonlis hash-chained -- each entry's hash is computed from its own content, and the next entry references it. Editing, deleting, or reordering an entry breaks the chain:
$ node dist/cli.js verify-log Verifying ./auditreach.log.jsonl... ✓ Chain intact: 14 entries, no gaps, no tampering detected. # after someone hand-edits a line in the log file: $ node dist/cli.js verify-log Verifying ./auditreach.log.jsonl... ✗ Chain broken at entry 3 (ar_2026-07-12_9f3c2a): entry ar_2026-07-12_9f3c2a hash does not match its own content -- entry was edited after being written
Numbers measured directly against each repo's public GitHub metadata and, for the dependency comparison, againstsnoowrap's own publishedpackage.jsonas of this writing -- reproducible by anyone withgh api repos/<owner>/<repo>.
We started building auditreach's Reddit client on top ofsnoowrap, the most-used Reddit API wrapper in the Node ecosystem. Installing it pulls inrequest,request-promise,form-data, andhar-validator-- a dependency chain that currently carries 2 CRITICAL, 2 HIGH, and 5 moderate severity advisories (9 total, pernpm audit), none of which snoowrap can fix because the project has been archived since 2023. We rewrote the Reddit client as a directfetch-based OAuth2 client against Reddit's own documented REST endpoints instead: same functionality, none of those CVEs, zero extra runtime dependencies for that client. SeeSecurityfor auditreach's own currentnpm auditstatus.
1. Install:seeInstallabove --npx auditreach-cli,npm install -g auditreach-cli, or clone and build from source.
2. Set up credentials for the platform you want to search (BYO-key -- your own, never ours):
node dist/cli.js auth --platform reddit # Prompts for Client ID, Client secret, username, password. # Create a script-app at https://www.reddit.com/prefs/apps first. node dist/cli.js auth --platform youtube # Prompts for an API key. # Create one at https://console.cloud.google.com/apis/credentials
All credentials are stored in your OS keychain (@napi-rs/keyring), never in a config file, never transmitted anywhere except the platform's own official auth endpoint. Once credentials are set, verify them without running a real search:
node dist/cli.js auth --platform reddit --verify
node dist/cli.js search --platform reddit --query "your query" --subreddit some_subreddit node dist/cli.js search --platform youtube --query "your query" --channel @SomeChannel
auditreachhas four subcommands. Every flag below is pulled directly from the CLI's own--helpoutput, not from memory of what it used to support.
Search a platform using its official API only.
node dist/cli.js search --platform reddit --query "agent memory poisoning" --subreddit MachineLearning --max-results 50 node dist/cli.js search --platform reddit --query "agent memory poisoning" --json | jq '.results | length'
Set up, verify, or clear BYOK credentials for a platform (stored in your OS keychain).
node dist/cli.js auth --platform reddit --verify
Verify the local hash-chained audit log has not been tampered with.
node dist/cli.js verify-log --path ./auditreach.log.jsonl
node dist/cli.js mcp # or, once published: npx auditreach-cli mcp
Add it to your MCP client's config (for Claude Desktop,claude_desktop_config.json). Either distribution works since both ship the samemcpsubcommand:
{ "mcpServers": { "auditreach": { "command": "npx", "args": ["-y", "auditreach-cli", "mcp"] } } }
{ "mcpServers": { "auditreach": { "command": "uvx", "args": ["--from", "auditreach-cli", "auditreach", "mcp"] } } }
Setting up or clearing BYOK credentials (auditreach auth --platform <p>/--clear) is deliberatelynotexposed over MCP -- that stays a local-CLI-only, human-driven action, so a calling agent can check whether credentials work but can never provision or wipe them itself. See.well-known/agent.jsonfor the machine-readable manifest (auth requirements, tool schemas, invocation commands) that an agent or agent registry can read to discover this server without a human reading the README first.
Runauditreach <command> --helpany time to see the exact flags your installed version supports.
auditreach-clidoubles as an importable library. Every export below comes straight fromdist/index.d.tsin the published package.
import { RedditClient, YoutubeClient, getCredential, setCredential, deleteCredential, getRedditCredentials, getYoutubeCredentials, appendAuditLogEntry, getLastEntryHash, computeEntryHash, verifyAuditLogChain, credentialFingerprint, canonicalJson, sha256Hex, DEFAULT_AUDIT_LOG_PATH, executeSearch, SearchCommandError, checkAuthStatus, executeVerifyLog, buildMcpServer, runMcpServerCommand, } from "auditreach-cli";
- new RedditClient(credentials: RedditCredentials)-- talks to Reddit's official OAuth API only, using the password grant ("script app" flow)..search(options: RedditSearchOptions): Promise<SearchOutcome>,.verifyCredentials(): Promise<void>.
- new YoutubeClient(credentials: YoutubeCredentials)-- wraps the official YouTube Data API v3..search(options: YoutubeSearchOptions): Promise<SearchOutcome>,.verifyCredentials(): Promise<void>(a 1-quota-unit call, no query needed).
const credentials = getRedditCredentials(); if (!credentials) throw new Error("run auditreach auth --platform reddit first"); const client = new RedditClient(credentials); const outcome = await client.search({ query: "agent memory poisoning", subreddit: "MachineLearning", });
Credentials(setCredential/getCredential/deleteCredential/getRedditCredentials/getYoutubeCredentials) -- all credential I/O goes through this module. It's the one place allowed to touch a raw secret; values come back only to hand directly to a client's constructor, never to log or print.
- appendAuditLogEntry(entryWithoutHash: UnhashedAuditLogEntry, logPath?: string): Promise<AuditLogEntry>-- the only write path into the log; entries are never edited or deleted in place.
- getLastEntryHash(logPath?: string): Promise<string | null>
- computeEntryHash(entry: UnhashedAuditLogEntry): string
- verifyAuditLogChain(logPath?: string): Promise<ChainVerificationResult>-- re-derives every entry's hash and checks the chain end to end.
- DEFAULT_AUDIT_LOG_PATH--"./auditreach.log.jsonl"
const result = await verifyAuditLogChain(); if (!result.valid) { console.error(Chain broken at entry ${result.brokenAtIndex}: ${result.reason}); }
- canonicalJson(value: unknown): string-- recursively sorts object keys so the same logical entry always serializes to the same bytes, which the hash chain depends on to verify deterministically.
- sha256Hex(input: string): string
- credentialFingerprint(secret: string): string-- keeps only the last 6 hex characters of the hash, enough to distinguish rotated keys in a local audit log, never enough to be a partial credential leak.
- executeSearch(args),checkAuthStatus(platform),executeVerifyLog(path?)-- the same programmatic cores thesearch/auth --verify/verify-logCLI commands and the MCP tools both call into; none of them write to console/stdout, so they're safe to call from any host, including one sharing stdout with an MCP transport.
- SearchCommandError-- the error classexecuteSearchthrows for an expected, user-actionable failure: no BYOK credentials stored yet for the target platform, or a Reddit search called without--query. Catch it specifically to distinguish "you called this wrong" from a real network/API failure.
- buildMcpServer({ version }): McpServer-- constructs the MCP server (from@modelcontextprotocol/sdk) with thesearch/auth_status/verify_logtools registered, without starting a transport -- useful for testing or embedding in a larger MCP server.
- runMcpServerCommand({ version })-- whatauditreach mcpruns: builds the server and connects it over stdio. Never returns while the server is running.
No generated API docs site exists yet (no TypeDoc build wired into CI) -- the exports above are the complete public surface. Checkdist/index.d.tsin the published package for exact types.
The Python package (auditreach-clion PyPI) exposes the same surface withsnake_casenames --from auditreach import RedditClient, YoutubeClient, get_reddit_credentials, verify_audit_log_chain, ...-- seepython/README.mdfor the full Python API reference.
--max-results <n>controls how many items a singlesearchcall returns. Leave it off and auditreach silently applies a default of 25 -- the same shape of surprise PRAW'sget_comments()had for years (praw#119): a caller who does not already know to pass the flag gets a quietly truncated result set.
[!NOTE] A search that returns exactly the applied limit (25 by default, or your--max-resultsvalue) may not be the full result set. auditreach prints a stderr warning when this happens, but scripts that only parse stdout/--jsonoutput won't see it -- check for the warning or pass an explicit--max-resultsif completeness matters.
Values above the cap are silently clamped to it. For Reddit,--before/--afterlet you page through a search's result set using the real cursor Reddit's own response returns, up to Reddit's own ~1,000-item search cap (seeSuccess storiesfor why cursor pagination alone can't go further than that); YouTube has no equivalent yet. Whenever the number of items returned equals the limit that was actually applied, whether that is the silent default or an explicit--max-resultsvalue, auditreach prints a warning to stderr telling you more results may exist and how to raise--max-results(up to the platform cap).
What is a "consent basis," honestly
Theconsent_basisfield on every audit-log entry names the specific platform API terms and auth mechanism used for that query. It certifies that the request went through the platform's official, documented API surface under the credentials you supplied.It does not certify that your specific use case is legally sufficient for your jurisdiction or contract-- that determination is yours to make, informed by an accurate, complete, tamper-evident record of what actually happened.
Nothing about auditreach requires a hosted account or server. Every command runs entirely on your machine; the audit log is a plain file you own. This is the same flow asInstallabove:
git clone https://github.com/RudrenduPaul/auditreach.git cd auditreach npm install npm run build node dist/cli.js search --platform reddit --query "..."
npm install npm run lint # ESLint npm run format # Prettier check npm run typecheck # tsc --noEmit --strict npm run test:coverage # vitest, 91 tests, 95.1% statement coverage
cd python python3 -m venv .venv && source .venv/bin/activate pip install -e ".[dev]" pytest # 95 tests
SeeCONTRIBUTING.mdfor the rules on adding a new platform client -- the short version: official API only, honest rate-limit disclosure, tests that mock the network boundary, never anything that reads or writes a raw credential outsidesrc/auth/credential-store.ts(orpython/src/auditreach/auth/credential_store.pyon the Python side).
SeeSECURITY.mdfor the vulnerability disclosure policy. A pre-launch OWASP/STRIDE review found zero CRITICAL/HIGH findings in auditreach's own code. As of this writing,npm audit --audit-level=highon a fresh install reports 3 advisories (1 moderate, 2 high) inip-addressandhono-- both pulled in transitively by the official@modelcontextprotocol/sdkdependency's HTTP-transport code.auditreach mcponly ever starts the SDK's stdio transport (StdioServerTransport), so that code path never runs, but the packages still ship innode_modulesand still tripnpm audituntil upstream bumps its pinned versions. GitHub secret scanning and push protection are enabled on this repo.
[!NOTE] Ifnpm auditflagsip-address/honoon your install, that's the unused HTTP-transport code path described above, not a reachable vulnerability in howauditreach mcpactually runs (stdio only). It will clear once@modelcontextprotocol/sdkbumps its pinned versions upstream.
Four real issues reported againstpraw-dev/praw-- PRAW, Reddit's official Python API wrapper, and the closest thing this project has to prior art -- root-caused against auditreach's own source and used to close genuine gaps in this tool before it had a single outside user. Each line below is tied to the actual report that prompted it.
- praw#614(@mananwason) -- asked how to page past Reddit's ~1,000-result search cap. The real fix is narrower than that: Reddit's own API returns no before/after cursor at all once you're past that cap, cursor-based paging or not -- confirmed directly in the issue thread. Whatsearch()actually does now is extract the real cursor from Reddit's response (SearchOutcome.nextCursor) and expose--before/--afterflags so you can page through the results within a single search's capped result set, instead of only ever seeing the first page. Going past the 1,000-item cap itself needs cloudsearch timestamp-window re-querying, which isn't built yet.
- praw#1939(@Auditormadness9) -- hit an undiagnosed 400 error caused by a subreddit name that still carried a leadingr/prefix. Search errors now name that specific cause when it's the likely culprit: previously the CLI just returned a bare status code and left the guessing to you.
- praw#984(@MaxMatti) -- asked for a simple way to check whether Reddit bot credentials were still valid, without PRAW's confusinggetMe()-recursion workaround.auditreach auth --platform reddit --verifydoes exactly that now: one lightweight check, no search required, nothing written to disk.
- praw#119(@nsp) -- hit PRAW's historic silent 25-result default, discoverable only by reading an unrelated base class's docstring; PRAW's own maintainer admitted he "wasn't sure the best way to make this clear."--helpand this README now state the real default and per-platform caps, and a runtime warning fires whenever a search actually got truncated.
What platforms and versions does auditreach run on?The npm package (auditreach-cli) requires Node.js 20 or newer (enginesfield inpackage.json). The PyPI package (alsoauditreach-cli) requires Python 3.10+ (requires-pythoninpython/pyproject.toml), which also carries theOperating System :: OS Independentclassifier. Credentials go into your OS keychain through@napi-rs/keyring(npm) orkeyring(PyPI) instead of a config file, so there is no platform-specific setup beyond having Node or Python installed.
Does auditreach store my Reddit or YouTube credentials anywhere?No. Credentials go straight into your OS keychain through@napi-rs/keyring(src/auth/credential-store.ts). There is no config file, no environment variable, and no code path that writes a raw credential to disk.
How many results does a search return by default, and can I get more?25, silently, unless you pass--max-results-- seeResult limits. The hard cap is 100 for Reddit and 50 for YouTube. A stderr warning fires whenever a search actually hits the applied limit, whether that's the silent default or an explicit value you passed.
How do I check my credentials are still valid without running a real search?node dist/cli.js auth --platform reddit --verify(or--platform youtube). It performs the minimal authenticated check and reports pass or fail, with no--queryneeded, no results file written, and no audit-log entry appended.
Is the audit log actually tamper-evident, or just a log file?Tamper-evident: each entry's hash is computed from its own content and the next entry references it, soverify-logcan point to the exact entry a hand-edit broke. See the demo underWhat it does.
What are auditreach's current limitations?Two worth knowing up front. First, X (Twitter) is not shipped -- X API v2's pricing and post-volume caps have been prohibitive for small teams doing real research since the 2023 changes; seePlatform coverage. Second, Reddit paging:search()reads the realafter/beforecursor out of Reddit's own response and exposes--before/--afterflags to page through a single search's result set, but that does not get you past Reddit's own ~1,000-item search cap -- see thepraw#614 success storyfor what the fix covers and doesn't.
How does the MCP server mode work?auditreach mcp(npm) orpipx run auditreach-cli mcp(PyPI) starts aModel Context Protocolserver over stdio, built on the official@modelcontextprotocol/sdk/mcpSDKs. It exposes exactly 3 tools --search,auth_status(read-only, cannot set or clear credentials), andverify_log-- each a thin wrapper around the same programmatic core the CLI commands use, so nothing is reimplemented for the agent path. Seeauditreach mcpabove for the full tool table and.well-known/agent.jsonfor the machine-readable manifest an agent registry can read directly.
How does auditreach compare to Agent-Reach specifically?Agent-Reach covers more platforms (six, versus auditreach's two) by importing a logged-in browser session and scraping as that user, at zero API cost. auditreach only calls official, documented APIs with your own keys and writes a hash-chained consent/audit entry per query; it has no session-import code path at all. Neither approach is strictly better -- they're built for different buyers. SeeHow it comparesfor the full side-by-side.
Is auditreach free to use commercially, and what does the license actually require?Yes. auditreach is Apache 2.0 (seeLICENSE), which permits commercial use, modification, and redistribution, including as part of a closed-source product. The conditions are: include a copy of the license with anything you redistribute, mark any files you modified, and keep the existing copyright/attribution notices. It does not grant rights to auditreach's name or trademarks.
SeeCONTRIBUTING.mdfor the rules on adding a new platform client. Short version: official API only, honest rate-limit disclosure, tests that mock the network boundary, never a code path that reads or writes a raw credential outsidesrc/auth/credential-store.ts.
Search global news using natural language. Webz.io News Search API returns the most relevant articles and content, with filters for source, country, language, date, sentiment, and category.
An agent-based tool for web search and advanced research, including analysis of PDFs, documents, images, and YouTube transcripts.
An MCP server providing search capabilities for Reddit, YouTube, and Twitter.
Provides search capabilities and data retrieval from SerpAPI and YouTube for AI assistants.
Get YouTube transcripts, search videos, browse channels, and extract playlists from any AI agent — powered by TranscriptAPI.com with no API key required.
Search YouTube videos and retrieve their transcripts using the YouTube API.
Connect AI assistants to YouTube - search, transcripts, metadata, and more.
Self-hosted YouTube research MCP with 17 tools for search, transcripts, timestamped frames, comments, and private local semantic corpora.
Search a YouTube video's transcript and read its frames — every answer cites a clickable timestamp.
A set of tools to interact with YouTube, including video search, transcript extraction, and comment retrieval.
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.




