A terminal-based AI agent with tool use, semantic document search (RAG), file management, shell execution, and web search.
I extended this terminal agent with a full RAG workflow and web search support:
- RAG search over local documents using ChromaDB
- Document ingestion for Markdown, TXT, and PDF files
- Google embeddings for semantic search
- Hash-based re-indexing so unchanged files are skipped
- Collection support for separate knowledge bases
- LLM-callable
ragSearchtool - Tavily-powered
webSearchtool - Shell command execution through
runCommand - Human-in-the-loop tool handling
- CLI ingestion flow with
agi ingest
This makes the agent useful for searching local notes, PDFs, project docs, and web results from the same terminal chat interface.
This project started as a fork of Hendrixer/agents-v2. My work focuses on adding RAG, Tavily web search, shell execution, document ingestion, and agent tooling improvements.
- Node.js >= 20
- A running Chroma server (for RAG)
- API keys (see Environment variables)
npm install
npm run build
npm link # makes `agi` available globallyOr run without installing globally:
npm run startCreate a .env file in the project root:
# Required for LLM (OpenAI)
OPENAI_API_KEY=your_openai_key
# Required for RAG embeddings (Google)
GOOGLE_GENERATIVE_AI_API_KEY=your_google_key
# Optional: Tavily web search
TAVILY_API_KEY=your_tavily_key
# Optional: Laminar tracing
LMNR_API_KEY=your_lmnr_key
# Optional RAG tuning
CHROMA_COLLECTION=knowledge # default collection name
CHUNK_SIZE=1000
CHUNK_OVERLAP=200
TOP_K=5
GOOGLE_EMBEDDING_MODEL=gemini-embedding-001Chroma is required for the RAG (ragSearch) tool to work.
# Start in the background (stores data to .rag/chroma)
npx chroma run --path .rag/chroma --host localhost --port 8000Or add it to a startup script. Chroma runs on http://localhost:8000 by default.
To verify it is running:
curl http://localhost:8000/api/v2/heartbeatagiThis opens the interactive chat UI. Type your message and press Enter.
To quit: type exit or quit.
Index documents so the agent can search them with ragSearch.
agi ingestagi ingest ./notes
agi ingest ~/Documents
agi ingest /path/to/any/folderagi ingest ./notes --collection notes
agi ingest ./research --collection research
agi ingest ~/Documents --collection personalCollections let you organize different knowledge bases and search them separately.
| Extension | Type |
|---|---|
.md |
Markdown |
.txt |
Text |
.pdf |
- Unchanged files are skipped (hash-based).
- Modified files are re-indexed (old chunks deleted, new ones inserted).
- Deleted files have their chunks removed from Chroma automatically.
Once documents are indexed, ask the agent naturally:
Who created the course?
What is this course about?
Summarize the notes on tool calling.
Search my notes for information about Docker networking.
The agent will call ragSearch automatically. You can also guide it:
Search the agent-notes collection for tool calling examples.
Look in my notes collection for JWT authentication.
| Tool | Description |
|---|---|
ragSearch |
Semantic search over indexed local documents |
readFile |
Read the contents of a file |
writeFile |
Write content to a file (creates parent directories) |
listFiles |
List files and folders in a directory |
deleteFile |
Delete a file (irreversible) |
webSearch |
Search the web (powered by Tavily) |
runCommand |
Run a shell command |
# Check how many chunks are in a collection
npx tsx --env-file=.env -e '
import { getCollection } from "./src/agent/rag/collection.ts";
const c = await getCollection("agent-notes");
console.log("chunks:", await c.count());
'npx tsx --env-file=.env -e '
import { getChromaClient } from "./src/agent/rag/collection.ts";
const client = getChromaClient();
await client.deleteCollection({ name: "agent-notes" });
console.log("deleted");
'rm .rag/hashes.jsonrm -rf .rag/chromarm -rf .ragAfter wiping, re-ingest your documents:
agi ingest ./notes --collection notesnpm run buildOutput goes to ./dist.
npm run devRuns with tsx (no build step needed). Watches for file changes.
Make sure Chroma is running:
npx chroma run --path .rag/chroma --port 8000Check:
curl http://localhost:8000/api/v2/heartbeat- Make sure you ingested documents first:
agi ingest ./your-docs --collection your-collection - Tell the agent which collection to search:
"Search the notes collection for..." - Check the collection has data:
npx tsx --env-file=.env -e '
import { getCollection } from "./src/agent/rag/collection.ts";
const c = await getCollection("your-collection");
console.log(await c.count());
'Make sure GOOGLE_GENERATIVE_AI_API_KEY is set and valid. The default embedding model is gemini-embedding-001.
Delete its entry from .rag/hashes.json or delete the whole file:
rm .rag/hashes.json # will re-index everything next ingest