{"_id":"@abdallahkh7/jarvis","name":"@abdallahkh7/jarvis","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@abdallahkh7/jarvis","version":"0.1.0","description":"A terminal-based, natural-language agentic AI assistant.","author":{"name":"Abdallah Khatib"},"license":"MIT","type":"module","bin":{"jarvis":"dist/index.js"},"main":"dist/index.js","scripts":{"build":"tsc","dev":"tsx src/index.ts","dev:watch":"tsx watch src/index.ts","start":"node dist/index.js"},"engines":{"node":">=18"},"devDependencies":{"@types/bcrypt":"^6.0.0","@types/better-sqlite3":"^7.6.13","@types/figlet":"^1.7.0","@types/inquirer":"^9.0.10","@types/mailparser":"^3.4.6","@types/node":"^26.0.1","@types/nodemailer":"^8.0.1","tsx":"^4.22.4","typescript":"^6.0.3"},"dependencies":{"@anthropic-ai/sdk":"^0.109.0","@octokit/rest":"^22.0.1","@xenova/transformers":"^2.17.2","ansi-escapes":"^7.3.0","bcrypt":"^6.0.0","better-sqlite3":"^12.11.1","boxen":"^8.0.1","chalk":"^5.6.2","dotenv":"^17.4.2","ffmpeg-static":"^5.3.0","figlet":"^1.11.0","gradient-string":"^3.0.0","imapflow":"^1.4.3","inquirer":"^14.0.2","keytar":"^7.9.0","mailparser":"^3.9.12","mammoth":"^1.12.0","msedge-tts":"^2.0.6","nodemailer":"^9.0.3","openai":"^6.45.0","ora":"^9.4.1","pdf-parse":"^2.4.5","systeminformation":"^5.31.11"},"gitHead":"15867d4e2efd965c37cbf28a0ba0654a6a63d5ad","_id":"@abdallahkh7/jarvis@0.1.0","_nodeVersion":"22.16.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-930CnzkhceXhC/54fV1dracdBfFBb1eRNJVW9alRECxAgirxF+w2hW+XNkdK7fc2dJlg/Y8BulNX2xmS1tpYVg==","shasum":"e930b566721979e3f2d050472e92d775ca773e2a","tarball":"https://registry.npmjs.org/@abdallahkh7/jarvis/-/jarvis-0.1.0.tgz","fileCount":96,"unpackedSize":79565547,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDf2urzlKp0v91hBXLBk8CjmXMnbr6uI9QqpdLW4Y/o9QIgUjk3i9HpauYq7TI2CoPosf3xurKtPp4qJSyP4k+x+20="}]},"_npmUser":{"name":"abdallahkh7","email":"abdallah.khatib2003@gmail.com"},"directories":{},"maintainers":[{"name":"abdallahkh7","email":"abdallah.khatib2003@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/jarvis_0.1.0_1782980863934_0.4113967486231931"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-02T08:27:43.805Z","0.1.0":"2026-07-02T08:27:44.637Z","modified":"2026-07-02T08:27:44.802Z"},"maintainers":[{"name":"abdallahkh7","email":"abdallah.khatib2003@gmail.com"}],"description":"A terminal-based, natural-language agentic AI assistant.","author":{"name":"Abdallah Khatib"},"license":"MIT","readme":"# JARVIS\r\n\r\n![Node.js](https://img.shields.io/badge/Node.js-18+-339933?style=for-the-badge&logo=node.js&logoColor=white)\r\n![TypeScript](https://img.shields.io/badge/TypeScript-5-3178C6?style=for-the-badge&logo=typescript&logoColor=white)\r\n![SQLite](https://img.shields.io/badge/SQLite-better--sqlite3-003B57?style=for-the-badge&logo=sqlite&logoColor=white)\r\n![OpenAI](https://img.shields.io/badge/OpenAI-GPT--4o--mini-412991?style=for-the-badge&logo=openai&logoColor=white)\r\n![License](https://img.shields.io/badge/License-Portfolio-orange?style=for-the-badge)\r\n![Status](https://img.shields.io/badge/Status-In%20Development-yellow?style=for-the-badge)\r\n\r\n> *\"Just A Rather Very Intelligent System.\"*\r\n\r\nA terminal-based, natural-language agentic AI assistant — you talk to it in plain English, not memorized commands. JARVIS decides which tool to use (read a file, search the project, look up GitHub, search the web) through real function-calling, not a command parser pretending to be smart. Runs entirely local: your own machine, your own SQLite database, your own API keys.\r\n\r\nBuilt by **Abdallah Khatib** — Computer Science graduate, Lebanese International University, reusing hard-earned patterns from [Rakiz](https://github.com/Abdallah-khatib-7/rakiz).\r\n\r\n---\r\n\r\n## Table of Contents\r\n\r\n- [About](#about)\r\n- [Key Features](#-key-features)\r\n- [Tech Stack](#️-tech-stack)\r\n- [Architecture Decisions](#architecture-decisions-worth-knowing)\r\n- [Project Structure](#-project-structure)\r\n- [Database Schema](#️-sqlite-schema)\r\n- [Running Locally](#-running-locally)\r\n- [Build Progress](#-build-progress)\r\n- [Known Limitations](#known-limitations--honest-caveats)\r\n- [About the Author](#-about)\r\n\r\n---\r\n\r\n## About\r\n\r\nMost \"AI terminal tools\" are really just a chat window bolted onto a shell. JARVIS is built the other way around: the agentic loop *is* the product. You describe what you want, the model decides which tool answers that — reading a file, searching the project tree, checking a GitHub PR, searching the web — runs it, and reasons over the real result. Nothing is hardcoded to a specific phrase or command shape.\r\n\r\nIt's local-first by design. No hosted backend, no multi-tenant server, no central database — each person runs their own copy, with their own SQLite file, their own API keys, their own JARVIS. The tradeoff is deliberate: no hosting bill, no \"your data on our servers,\" and every user's JARVIS is genuinely theirs.\r\n\r\nThe build has been intentionally incremental — foundation before flow, data layer before UI, one working piece before the next — with a real personality layered in from the start rather than bolted on at the end.\r\n\r\n---\r\n\r\n## ✨ Key Features\r\n\r\n### 🖥️ Cinematic Terminal Identity\r\n- Boot sequence with a glitch-resolve title animation — ASCII art assembles out of scrambled noise, not a static print\r\n- Staggered boot-status lines (`CORE ONLINE`, `MEMORY LINKED`...) with a typewriter tagline reveal\r\n- Every JARVIS response types out character-by-character in cyan — except code blocks, which print instantly and untouched so formatting never breaks\r\n\r\n### 🔐 Local Identity & Accounts\r\n- New-user / returning-user flow with back-navigation and a global `exit` escape hatch at any prompt\r\n- bcrypt-hashed passwords (cost factor 12), local SQLite, WAL mode\r\n- Password confirmation on signup, capped wrong-password attempts on login\r\n\r\n### 🧠 Smart, Age-Aware Onboarding\r\n- Freeform Q&A seeds JARVIS's memory of you: name, gender, age, role, education, self-description, favorite dessert\r\n- Age-inference: under 18, JARVIS *guesses* you're in high school and asks you to confirm rather than interrogating cold; 18+ gets asked plainly, since it's genuinely ambiguous\r\n- Hard age gate at 16 — invalid input gets one warning (\"I am JARVIS, you can't fool me\"), a second bad answer triggers a real animated self-destruct countdown; under-16 gets a respectful farewell with a quote. Both paths cleanly delete the account and its memory, no orphaned rows\r\n\r\n### 🎭 Selectable Personality\r\n- Four distinct voices — Cool & cinematic (Iron Man's JARVIS), Warm & witty, Playful & cheeky, Serious & professional — defined once in a shared registry and used everywhere\r\n- First greeting always speaks in the default cinematic voice; the user picks their preferred tone right after, no wasted regeneration calls\r\n- The chosen personality is injected into every system prompt for the rest of every session, not just the welcome message\r\n\r\n### 🤖 Real Agentic Tool Use\r\n- Provider-agnostic AI adapter layer — the app talks to one internal interface, never directly to a vendor SDK, so adding Claude/Gemini/DeepSeek later is a new adapter file, not a rewrite\r\n- OpenAI function-calling wired up as a genuine multi-turn loop: model calls a tool → result feeds back into context → model calls another tool or answers in text → bounded by a hard turn ceiling with a graceful no-tools fallback if it's ever hit\r\n- Tools ship as `{ ok, output }` results, dispatched through one central registry — adding a tool is one array entry plus one switch case\r\n\r\n### 🛠️ Tools Available Today\r\n| Tool | What it does |\r\n|---|---|\r\n| `read_file` | Reads a file, returns content with real line numbers prefixed so JARVIS can reference exact lines instead of guessing |\r\n| `list_directory` | Lists a folder's contents, directories marked with a trailing `/` |\r\n| `search_files` | Recursively searches the whole project by filename, skips `node_modules`/`.git`/`dist` — so JARVIS finds files himself instead of being told the path |\r\n| `web_search` | Live web search via Serper — free tier, no card required |\r\n| `github_search` / `github_list_repos` / `github_get_pr` / `github_get_issue` | Read-only GitHub lookups across your repos |\r\n| `github_create_issue` / `github_comment` | Writes to GitHub, gated behind an on-screen preview panel before anything posts |\r\n\r\n### 💬 Persistent Chat Loop\r\n- Not a one-shot script — a genuine ongoing conversation with running history, so JARVIS remembers what you said three messages ago\r\n- Every reply speaks in your chosen personality and is aware of everything from onboarding, injected fresh into the system prompt each session\r\n- Thinking spinner with rotating phrases (\"Studying you,\" \"Tinkering,\" \"Connecting the dots\") covers any tool-use latency instead of a silent hang\r\n\r\n---\r\n\r\n## 🛠️ Tech Stack\r\n\r\n| Technology | Purpose |\r\n|---|---|\r\n| Node.js 18+ / TypeScript 5 | Runtime and type safety, ES modules throughout |\r\n| tsx | Zero-build dev execution + watch mode |\r\n| better-sqlite3 | Local, synchronous, single-file database — WAL mode |\r\n| bcrypt | Password hashing, cost factor 12 |\r\n| openai | Primary AI provider SDK, wrapped behind an internal adapter interface |\r\n| Inquirer.js | All interactive terminal prompts (text, password, select, confirm) |\r\n| Chalk | Terminal color throughout |\r\n| Ora | Live \"thinking\" spinner during AI calls and tool use |\r\n| Figlet / Gradient-string / ansi-escapes | Boot sequence — ASCII title, color gradient, frame-by-frame glitch redraw |\r\n| dotenv | Local `.env` key loading — never committed |\r\n| @octokit/rest | GitHub connector |\r\n| Serper | Web search — free tier, no card required |\r\n\r\n---\r\n\r\n## Architecture decisions worth knowing\r\n\r\n- **Provider adapter, not a vendor SDK call.** Every AI call goes through `AIProvider` — one shared interface (`chat(messages) → string`). `openai.ts` is the only file that knows OpenAI's actual request shape; the rest of the app is provider-blind. Adding a second provider later means one new adapter file translating the same interface, never touching the tools, the chat loop, or the personality system.\r\n\r\n- **Tools are pure functions, dispatched centrally.** Every tool returns `{ ok, output }` and never throws past its own boundary — a missing file becomes a readable message, not a stack trace. `registry.ts` is the single place that maps an AI-requested tool name to the real function that runs it. The AI only ever sees a name, a description, and a parameter schema; it never touches real code directly.\r\n\r\n- **Memory is key/value, not fixed columns.** Onboarding facts, personality choice, anything JARVIS learns about a user — all stored as `(user_id, key, value)` rows with an upsert on conflict. Adding a new fact the app cares about is zero schema changes, ever.\r\n\r\n- **Destructive actions are architecturally separate from read actions.** Reading, searching, and listing require no confirmation. Anything that would modify or delete — file edits, file deletion — is scoped from day one to require a typed confirm-phrase that echoes the specific action back, never a password re-prompt. This boundary is enforced by which functions exist, not by a runtime check that could be bypassed.\r\n\r\n- **Local-only, by design, not by limitation.** No server, no shared auth, no multi-tenant anything. `jarvis.db` lives next to the source, resolved via a fixed path derived from the module's own location — not the caller's working directory — so the database is always found in the same place regardless of how the process was launched.\r\n\r\n- **Age-gate deletion is transactional.** Removing an under-16 or repeatedly-invalid-age account wipes both the `users` row and every `memory` row tied to it inside a single `better-sqlite3` transaction — either both succeed or neither does. No orphaned memory rows pointing at a user that no longer exists.\r\n\r\n---\r\n\r\n## 📁 Project Structure\r\n\r\n```\r\njarvis/\r\n├── src/\r\n│   ├── ai/\r\n│   │   ├── types.ts              AIProvider interface, ChatMessage, ToolCall — the shared contract\r\n│   │   ├── openai.ts             OpenAI adapter — the only file that speaks OpenAI's real shape\r\n│   │   └── personality.ts        The 4 voices, single source of truth for tone everywhere\r\n│   ├── auth/\r\n│   │   ├── login.ts              Signup/login flow, back-navigation, session shape\r\n│   │   ├── onboarding.ts         Age-aware Q&A, education branching, age gate\r\n│   │   ├── effects.ts            Self-destruct countdown, underage farewell animations\r\n│   │   ├── welcome.ts            First AI-generated personalized greeting\r\n│   │   ├── personalityPicker.ts  Post-welcome tone selection, saved to memory\r\n│   │   └── prompts.ts            Shared Inquirer wrappers — every prompt honors exit/back\r\n│   ├── chat/\r\n│   │   └── loop.ts               The ongoing conversation loop — real session, not one-shot\r\n│   ├── connectors/\r\n│   │   └── github.ts             GitHub tools — search, PRs, issues, comments (confirm-gated writes)\r\n│   ├── database/\r\n│   │   ├── db.ts                 SQLite connection, WAL mode, users table\r\n│   │   ├── users.ts              User CRUD — create, verify, delete (transactional)\r\n│   │   └── memory.ts             Key/value fact store per user\r\n│   ├── tools/\r\n│   │   ├── fileTools.ts          read_file, list_directory, search_files\r\n│   │   ├── webSearch.ts          Serper-backed web search tool\r\n│   │   └── registry.ts           Tool definitions + central dispatch\r\n│   ├── ui/\r\n│   │   ├── thinking.ts           Reusable spinner wrapper for any async work\r\n│   │   └── reveal.ts             Typewriter speech reveal, code-block-aware\r\n│   ├── boot.ts                   Glitch-resolve title animation, boot-status lines\r\n│   └── index.ts                  Entry point — boot → auth → onboarding → chat loop\r\n├── PROGRESS.md                   Living phase tracker\r\n├── JARVIS-BRIEF.md                Full project spec and architectural ground rules\r\n├── tsconfig.json\r\n└── package.json\r\n```\r\n\r\n---\r\n\r\n## 🗄️ SQLite Schema\r\n\r\n| Table | Purpose |\r\n|---|---|\r\n| `users` | Accounts — username, bcrypt password hash, created_at |\r\n| `memory` | Per-user key/value facts (onboarding answers, chosen personality, anything learned later) — unique per `(user_id, key)`, upserted on conflict |\r\n\r\nSmall by design — the schema grows exactly as fast as the features that need it, never ahead of them.\r\n\r\n---\r\n\r\n## 🚀 Running Locally\r\n\r\n### Prerequisites\r\n- Node.js 18+\r\n- An OpenAI API key\r\n- A GitHub personal access token (`repo` scope) — optional, only needed for the GitHub connector\r\n- A Serper API key — optional, only needed for web search\r\n\r\n### 1. Clone and install\r\n```bash\r\ngit clone https://github.com/Abdallah-khatib-7/Jarvis.git\r\ncd jarvis\r\nnpm install\r\n```\r\n\r\n### 2. Environment\r\nCreate a `.env` file at the project root:\r\n```\r\nOPENAI_API_KEY=sk-your-key-here\r\nGITHUB_TOKEN=ghp-your-token-here\r\nSERPER_API_KEY=your-serper-key-here\r\n```\r\n`.env` is gitignored — never committed, never leaves your machine.\r\n\r\n### 3. Run\r\n```bash\r\nnpm run dev        # run once via tsx\r\nnpm run dev:watch  # auto-restart on save\r\nnpm run build       # compile to dist/\r\nnpm start           # run the compiled build\r\n```\r\n\r\nFirst launch creates `jarvis.db` automatically next to the source — nothing to seed by hand.\r\n\r\n---\r\n\r\n## 📊 Build Progress\r\n\r\n**Complete**\r\n- Full project setup — TypeScript, build pipeline, GitHub-connected from the first file\r\n- Terminal shell + identity — boot sequence, signup/login, onboarding, memory seeding\r\n- AI foundation — provider adapter, OpenAI wired up, personality system, agentic tool-calling loop\r\n- Persistent chat loop with typewriter reveal and thinking spinner\r\n- GitHub connector (read + confirm-gated write)\r\n- Web search via Serper\r\n\r\n**In progress / next**\r\n- Real execution capability (running `tsc`, shell commands) — needed for JARVIS to *verify* things, not just read and guess\r\n- `edit_file` / `delete_file`, gated behind a typed confirm-phrase\r\n- Per-user connector credentials (GitHub token is currently install-wide, not per-account)\r\n- Broader memory — facts learned mid-conversation, not just at onboarding\r\n- Multi-provider support (Claude, Gemini, DeepSeek adapters)\r\n- Telegram and Gmail connectors\r\n- Image input\r\n- Voice (stretch)\r\n\r\nFull phase-by-phase detail lives in `PROGRESS.md`.\r\n\r\n---\r\n\r\n## Known limitations / honest caveats\r\n\r\n- **GitHub token is shared, not per-user.** In a multi-account local install, every user currently pulls the same `GITHUB_TOKEN` from `.env`. This needs to move to a per-session or `keytar`-backed per-user credential before it's genuinely multi-user safe — flagged, not yet fixed.\r\n- **No execution tools yet.** JARVIS can read and reason about code but can't run it — \"does this file have errors\" gets an honest best-effort read-through, not a real compiler answer, until `tsc`/shell execution tools exist.\r\n- **No file-write tools yet.** `edit_file` and `delete_file` are scoped and designed (confirm-phrase gated) but not built — JARVIS is currently read-only on your filesystem.\r\n- **Single AI provider.** Only OpenAI is wired up today; the adapter layer is built to make adding others straightforward, but Claude/Gemini/DeepSeek don't exist yet.\r\n- **No shared-key token cap enforcement yet.** The 75k/day shared-key model is specified but not implemented — today, every local user with the shared `.env` key has unlimited use.\r\n\r\n---\r\n\r\n## 👨‍💻 About\r\n\r\nI'm Abdallah Khatib, a Computer Science graduate from Lebanese International University 🇱🇧, with 5+ years of pharmacy experience prior to this. JARVIS is a from-scratch build — terminal, database, AI orchestration, and personality — following the same no-shortcuts approach as [Rakiz](https://github.com/Abdallah-khatib-7/rakiz), my multi-currency wallet and payments platform.\r\n\r\n📧 abdallah.khatib2003@gmail.com\r\n\r\n---\r\n\r\n## 📄 License\r\n\r\nThis project is for portfolio and demonstration purposes. All rights reserved © 2026 Abdallah Khatib.","readmeFilename":"README.md","_rev":"1-40afdf7edff1ba30757f2283078587a6"}