npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

rutkar

v1.3.1

Published

Automate AI chat (ChatGPT + Gemini) from the command line using a real Chromium-based browser with Playwright. Send questions, attach files, and save responses as Markdown.

Readme

askweb

Automate AI chat from the command line using a real Chromium-based browser with Playwright. Send questions, attach files, and save responses as Markdown.

askweb controls a persistent browser session, so the same browser profile and (optional) login are reused across runs. Logging in is optional for ChatGPT: askweb runs anonymously by default and only needs a login for file uploads and very large payloads. Gemini typically requires a Google login.

askweb supports multiple AI providers behind a common interface. ChatGPT is the default; Gemini is also available. Use --provider <name> for a one-off override, or --ai / --ai-order / --ai-reset to configure the default and fallback order (stored in .ai-prefs.json).

Features

  • CLI-driven AI chat automation with a persistent browser profile
  • Multiple AI providers behind a common interface: ChatGPT (default) and Gemini (--provider, --ai, --ai-order, --ai-reset)
  • Question submission with retry logic and UI-state validation
  • File attachment support: text/code files pasted inline, binary files uploaded (when logged in)
  • Local commands (--cmd) — run a shell command and pipe its output into the prompt sent to the AI
  • Dry runs (--dry-run) — preview the exact prompt payload that would be sent, without launching a browser
  • Prompt presets as native flags (--explain, --find-error, ...), with a built-in and a custom (editable) set
  • Append/prepend answer output to an existing file (--append / --prepend), or print to stdout with no file (--print)
  • Multiple browser fallback: Chrome, Brave, Edge (configurable order and default)
  • Login/logout flow with session persistence across runs
  • Works from any working directory: browser profiles, preferences, and history are anchored to the install location
  • Visible progress while waiting for login instead of silent hangs
  • Conversation history with --continue [id] and --new
  • Large payloads delivered as numbered multi-part transmissions or a single attachment
  • Browser preference persistence (.browser-prefs.json)
  • AI provider preference persistence (.ai-prefs.json)
  • Conversation history persistence (.chatgpt-conversations.json, max 50 entries)
  • Graceful shutdown on SIGINT/SIGTERM

Tech Stack

  • Runtime: Node.js (CommonJS)
  • Browser automation: Playwright (playwright-extra)
  • Stealth: puppeteer-extra-plugin-stealth
  • AI providers: pluggable registry in providers/ (chatgpt, gemini) with shared payload/transmission logic in lib/payload.js
  • Config: dotenv

Installation

The easiest way to install askweb is from npm as a global CLI:

npm install -g rutkar
npx playwright install chromium   # one-time: install Playwright's browser support

After installation, askweb is available from any directory. The npm package is named rutkar; the installed command is askweb. For asking questions you also need a Chromium-based browser installed (Chrome, Brave, or Edge) — askweb drives your system browser via a persistent profile, falling back through the configured order when one is missing:

askweb "What is JavaScript?"

Update

npm update -g rutkar

Uninstall

npm uninstall -g rutkar

Development / Source Install

For development or local builds from source:

git clone https://github.com/omkar142web/askweb.git
cd askweb
npm install
npx playwright install chromium

npm Script Shortcuts

npm run ask   "What is JavaScript?"
npm run new   "New topic"
npm run cont  "Follow up question"
npm run forget <conversation-id>
npm run wipe

Quick Start

askweb (global install) and node index.js (source checkout) are interchangeable in all examples below. You can run either from any directory; only -o <path> and file arguments resolve relative to your current working directory.

# Ask a question
askweb "What is JavaScript?"

# Ask with output to a specific file
askweb -o result.md "Explain quantum computing"

# Print to stdout instead of writing a file (for pipes and AI CLIs)
askweb --print "Explain closures"

# Attach a text/code file (pasted inline)
askweb "Summarize this file" @notes.txt

# Attach multiple files
askweb "Compare these files" file1.json file2.tsx

# Run a prompt preset
askweb --explain "JavaScript closures"
askweb --find-error src/index.js

# Run a local shell command and reason over its output
askweb --cmd "git status" "Explain the current repository state."

# Preview the payload that would be sent (no browser launched)
askweb --dry-run "Explain closures"

# Continue the most recent conversation
askweb --continue "Follow up question"

# Continue a specific conversation by id prefix
askweb --continue a2cc6a02 "More on this"

# Start a fresh conversation
askweb --new "New topic"

# Use a specific AI provider for one run
askweb --provider gemini "Explain React"

# Choose the default AI provider interactively
askweb --ai

# Question text that starts with a dash
askweb -- " -explain this flag"

# Login once per provider (optional for ChatGPT; session persists)
askweb --login
askweb --login --provider gemini

Usage

askweb [options] [question] [files...]
node index.js [options] [question] [files...]
  • question is optional (default: "What is JavaScript?").
  • files... is optional; zero or more files.
  • options may appear before, between, or after the question and files.
  • -- stops option parsing: every token after it is treated literally.
  • A bare token is attached as a file only if it exists on disk; @path always forces a file reference.

A new user can run node index.js --help for the full in-tool mini-manual.

CLI Options

| Option | Argument | Description | | --- | --- | --- | | askweb [options] [question] [files...] | — | Ask the selected AI a question, optionally attaching files. | | <question> | — | Free-form question text (default: "What is JavaScript?"). | | <file> / @file | path | Attach a file. A bare path is used only if it exists; @path always forces a file. | | -o, --output | <file> | Save the answer to a file (default: ./output.md). Also accepts --output=<file>. | | --append | — | Append the answer to an existing output file. Requires --output. | | --prepend | — | Prepend the answer to an existing output file. Requires --output. | | --print | — | Print the answer to stdout and never write the answer file. Strict: cannot be combined with -o/--output, --append, or --prepend (except with --dry-run, which writes nothing). Conversation history is still saved. | | --login | — | Open the selected AI site to log in and save the session. Standalone (ignores question/files/--continue/--new). | | --logout | — | Open the selected AI site to log out manually; the session cookie is cleared. Standalone (up to 10 min). | | --continue | [id] | Resume the most recent conversation, or a specific one by id prefix. | | --new | — | Start a fresh conversation (the default). Cannot be used with --continue. | | --prompts | — | Open the interactive Prompt Manager. | | --prompt-create | [name] | Interactively create a prompt preset. | | --<preset> | [text] | Run a preset as a native command (e.g. --explain, --find-error). | | --browser | — | Choose the default browser interactively. | | --browser-order | — | Reorder the browser fallback list interactively. | | --browser-reset | — | Reset browser preferences to automatic (Chrome first). | | --provider | <name> | Use a specific AI provider for this run only (e.g. chatgpt, gemini). Overrides the default from --ai. Also accepts --provider=<name>. | | --ai | — | Choose the default AI provider interactively. | | --ai-order | — | Reorder the AI provider fallback list interactively. | | --ai-reset | — | Delete saved AI preferences and return to defaults (ChatGPT first). | | --clear-session | — | Wipe saved local/session storage and cookies before launching (starts logged out). | | --clear-conversations | — | Delete all saved conversation history. | | --clear-conversation | <id> | Delete one saved conversation by id (prefix match). Also accepts --clear-conversation=<id>. | | -h, --help | — | Show help. | | -v, --version | — | Show the version. | | --dry-run | — | Print the exact prompt payload that would be sent to the selected AI provider, then exit. No browser is launched and nothing is sent. | | --cmd | <command> | Execute a local shell command and include its stdout/stderr in the prompt. Can be repeated. Each command runs with a 30s timeout, capped at ASKWEB_MAX_CMD_OUTPUT chars per stream. | | -- | — | Stop option parsing; tokens after it are the question/files literally. |

Combinations to avoid

  • --continue and --new cannot be used together.
  • --append and --prepend cannot be used together (and each requires --output).
  • --print cannot be used with -o/--output, --append, or --prepend (except alongside --dry-run, which writes nothing).
  • Only one prompt preset may be used per run (--explain --review is rejected).
  • --output and --clear-conversation each require their argument.
  • --continue=<id> is not supported; use a space: --continue <id>.
  • --dry-run cannot be combined with standalone actions (--login, --logout, --browser, --browser-order, --browser-reset, --ai, --ai-order, --ai-reset, --prompts, --prompt-create, --clear-conversations, --clear-conversation). --clear-session, --continue/--new, --provider, --cmd, presets, and output flags remain allowed.

Local Commands (--cmd)

--cmd runs a local shell command and folds its stdout/stderr into the prompt sent to the AI as a <command name="..."> block. Combine with a question to ask about the command's output. The flag can be repeated for multiple commands.

node index.js --cmd "git status" "Explain the current repository state."
node index.js --cmd "git diff" --cmd "git status" "Review my changes."
node index.js --cmd "git log -5" "Summarize the recent changes."
  • Each command runs with your user's permissions and a 30s timeout.
  • Output is capped at ASKWEB_MAX_CMD_OUTPUT characters per stream (default 100000, i.e. 100 KB). Set the variable to override.
  • Obvious destructive patterns (rm -rf /, mkfs, etc.) are blocked.

Dry Run (--dry-run)

--dry-run builds the prompt payload exactly as it would be sent (question, attached/inlined files, command results, and any <file> blocks) and prints it to stdout, then exits. No browser is launched and nothing is sent to the AI provider. The header names the selected provider (--- DRY RUN: PROMPT THAT WOULD BE SENT TO <PROVIDER> ---). This is useful for inspecting how files and --cmd outputs are assembled before committing tokens to a real run.

node index.js --dry-run "Review this" src/index.js

Prompt Presets

Presets are reusable prompts invoked like native flags. They accept files and an optional question, just like a normal ask.

# Run a built-in that takes {{input}} (requires a word):
askweb --explain "JavaScript closures"

# Run a built-in with no {{input}} over files:
askweb --find-error src/index.js a.js b.js

# Run a preset and save the result:
askweb --review src/index.js -o review.md
  • Words after the flag fill the template's {{input}} slot. A preset with {{input}} requires at least one word (otherwise the CLI errors with Preset --<name> takes an argument); a preset without {{input}} appends the words as "Extra focus".
  • Preset names cannot collide with CLI flags (--continue, --login, ...), so those tokens always behave as options.

Built-in presets

| Preset | Uses {{input}} | | --- | --- | | --find-error | no | | --review | no | | --refactor | no | | --tests | no | | --summarize | no | | --explain | yes | | --teach | yes | | --generate | yes |

Custom presets are stored in .askweb-prompts.json (in the install directory). Manage them with the interactive managers:

node index.js --prompts          # add / edit / rename / delete / view
node index.js --prompt-create fix # interactively create "fix"

File Attachments

Text and Code Files

Files with these extensions are pasted inline into the prompt as fenced code blocks:

.css, .csv, .html, .js, .json, .jsx, .md, .py, .ts, .tsx, .txt, .xml, .yaml, .yml

Each file is truncated to 400,000 characters if larger. Text attachments are wrapped in <file name="..." lang="..."> blocks.

Binary Files

Non-text files are uploaded as attachments when logged in, and inlined as base64 inside <file name="..." encoding="base64"> blocks (with an automatic decode note) when logged out.

Upload Methods

For binary uploads, the following strategies are tried in order:

  1. input[type="file"] (inputs tried last-to-first)
  2. File chooser button with menu fallback
  3. Drag-and-drop on the composer (programmatic DragEvent dispatch)

Large Payloads

  • A single paste is capped at about 25 KB (25,000 chars). Anything larger is delivered as a numbered multi-part transmission that the AI acknowledges part-by-part before answering.
  • Logged-in users can also upload a large payload as a single attachment.
  • Anonymous (logged-out) transmissions are capped at about ~293 KB (~6 parts) on ChatGPT. Beyond that, log in (askweb --login) or trim the input.
  • Gemini caps composer input at ~32K chars (truncates at exactly 32,001), so Gemini part bodies are limited to 29,000 chars each (vs ChatGPT's ~49 KB packing): the same payload needs more parts on Gemini, and the anonymous 6-part budget holds fewer total characters (~170 KB). Anonymous Gemini bursts are also throttled server-side: parts send back-to-back with only a short settle gap, and if generation never starts within ~45s the finale is resent once after a 15s cooldown before failing fast with a rate-limit hint (wait a minute and retry, or log in). A long stall with no progress also aborts after ~90s instead of hanging.
  • Set ASKWEB_CHUNK_SIZE=<chars> to override the automatic part size (applies to both providers; an explicit override skips the Gemini 29 KB cap).

Conversation History

Conversation history is saved to .chatgpt-conversations.json in the askweb install directory. Up to 50 conversations are retained. The filename is historical: entries from every provider (chatgpt, gemini, ...) share this one file.

Each entry stores:

  • id (from the ChatGPT URL UUID, a Gemini URL token, or generated)
  • provider (e.g. "chatgpt", "gemini"; defaults to "chatgpt" for old entries)
  • url
  • title
  • updatedAt
  • delivery (optional, present only when the payload was large) — mode: "chunked" (anonymous multi-part) or "attachment" (uploaded as a single file), plus parts/chars (chunked) or chars (attachment)
  • messages[]

Conversation ids are provider-agnostic: --continue replays the saved transcript as plain text into a new chat with the currently selected provider, so it works across providers and even when logged out. The selected provider is never silently switched — if the saved conversation came from a different provider you get a note (or a warning when --provider explicitly overrides it) with a hint to pass --provider <original> to stay on the original one.

Use --continue to replay the most recent conversation's full transcript into a fresh chat. Use --continue <id> (full id or a unique prefix) for a specific one. Use --new to explicitly start a fresh conversation without history. The id of each saved conversation is printed after a run so you can pass it to --continue <id> later.

Manage history with:

  • --clear-conversations — delete all saved conversations
  • --clear-conversation <id> — delete one conversation by id (prefix match supported)

Output

Answers are saved to ./output.md by default. Use -o to change the path.

  • -o, --output <file> — write the answer to <file> (overwrites by default).
  • --append — append the answer after existing content.
  • --prepend — prepend the answer before existing content.
  • --print — print the answer to stdout and never write the answer file (e.g. for AI CLIs and scripts: askweb --print "Explain closures").

--append and --prepend are mutually exclusive and both require --output. --print is strict: it cannot be combined with -o/--output, --append, or --prepend (except with --dry-run, which writes nothing). Note --print skips only the answer file — conversation history is still recorded so --continue keeps working. The output path (-o) is resolved relative to your current working directory; all other paths (browser profiles, history, preferences) live in the install directory.

The answer is captured exclusively from the browser's copy button and read from the clipboard, which preserves the original Markdown formatting. The browser context is granted clipboard-read and clipboard-write permissions for reliable extraction.

Login & Browser

ChatGPT needs no account. It runs anonymously by default; the browser opens and you can start asking right away. Logging in is only required for file uploads and large payloads. Gemini typically requires a Google login — run askweb --login (or askweb --login --provider gemini) and sign in inside the opened window.

node index.js --login    # open the login page; session cookie is saved in the profile
node index.js --logout   # open the AI site and log out manually; cookie is cleared

--login / --logout act on the currently selected provider (--provider <name> overrides for that run, otherwise the default from --ai). The session cookie is saved in the browser profile and reused by later runs, so you only log in once per provider.

Browser Selection

Persistent profiles are stored in the askweb install directory (resolved against the install location, not your current working directory):

  • user-data-chrome (Chrome)
  • user-data-brave (Brave)
  • user-data-edge (Edge)

Because profile paths are anchored to the install directory, your login session is shared across every invocation regardless of where you run askweb from.

These directories contain cookies, localStorage, and session state and are not tracked in version control. Profile directories are cleaned on exit by setting exit_type=Normal and exited_cleanly=true in Default/Preferences.

askweb tries browsers in a saved order (Chrome first by default) and uses the first one installed on this machine. Manage this interactively:

node index.js --browser        # choose the default browser
node index.js --browser-order  # reorder the fallback list
node index.js --browser-reset  # reset to automatic (Chrome first)

--clear-session wipes saved local/session storage and cookies for the next launch, so the browser starts logged out/anonymous:

node index.js --clear-session "Who won the 2024 election?"

--clear-session is a modifier (it combines with a question or with --login); it is allowed alongside --dry-run.

AI Providers

askweb supports multiple AI providers behind a common interface. ChatGPT is the default; Gemini is also available.

node index.js --provider gemini "Explain React"  # one-off override for this run
node index.js --ai          # choose the default AI provider interactively
node index.js --ai-order    # reorder the AI provider fallback list
node index.js --ai-reset    # delete saved AI preferences (back to ChatGPT first)

When --provider is omitted, askweb uses the default from --ai (or ChatGPT if no preference is saved). Unknown --provider names error out with the list of available providers. --provider also accepts --provider=<name>. --continue keeps your selected provider (see Conversation History) — pass --provider <original> explicitly if you want to stay on the conversation's original provider.

Configuration

Browser preferences are stored in .browser-prefs.json in the askweb install directory:

{
  "defaultBrowser": "chrome",
  "browserOrder": ["chrome", "edge", "brave"]
}

The configured preferred browser is tried first, followed by the saved order, then any remaining defaults.

AI provider preferences are stored separately in .ai-prefs.json in the askweb install directory:

{
  "defaultAI": "chatgpt",
  "aiOrder": ["chatgpt", "gemini"]
}

The configured default AI is tried first, followed by the saved order, then any remaining registered providers. Unknown names left in the file by removed providers are silently ignored. Deleting the file (via --ai-reset) returns to automatic selection (ChatGPT first). Browser (.browser-prefs.json) and AI (.ai-prefs.json) preferences are fully independent.

Environment

| Variable | Description | | --- | --- | | ASKWEB_CHUNK_SIZE | Force the part size (in characters) used by the anonymous multi-part transmission path. Only used when a payload exceeds the single-message budget (~25 KB). | | ASKWEB_MAX_CMD_OUTPUT | Maximum characters to capture per command output stream (stdout or stderr) when using --cmd. Output beyond this is truncated with an explicit marker in the prompt. Default: 100000 (100 KB). |

# Windows
$env:ASKWEB_CHUNK_SIZE=40000; node index.js "long question"
$env:ASKWEB_MAX_CMD_OUTPUT=20000; node index.js --cmd "git log"

# Unix
ASKWEB_CHUNK_SIZE=40000 node index.js "long question"
ASKWEB_MAX_CMD_OUTPUT=20000 node index.js --cmd "git log"

Known Issues

  • Brave's executable path is hardcoded for Windows in index.js:
    • executablePath: ${process.env.LOCALAPPDATA}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe
    • On macOS/Linux, LOCALAPPDATA is undefined and Brave may be skipped silently.
  • If the provider's copy button is unavailable, the tool polls rapidly for up to 10 seconds before reporting an error. Re-run or refresh the page to retry.
  • UI changes by the provider may require selector updates in chatgpt-ui.js (ChatGPT) or providers/gemini/ui.js (Gemini).
  • Maximum of 50 saved conversations in .chatgpt-conversations.json.
  • Anonymous (logged-out) chats are capped at ~293 KB of transmitted content (~6 parts) on ChatGPT, and ~170 KB (~6 x 29 KB parts) on Gemini due to its composer cap; larger payloads require a login.
  • Gemini typically requires a Google login; anonymous Gemini sessions may be refused or capped by Google. ChatGPT works anonymously.
  • Anonymous Gemini bursts may be throttled even under the cap: sends are accepted but never generate a reply. askweb sends parts back-to-back after each ack, resends the finale once after a 15s cooldown if nothing generates within 45s, and aborts after 90s without progress instead of hanging.
  • Unknown --provider names exit with an error listing the available providers (chatgpt, gemini).

Troubleshooting

# No browser could be launched
#   - Install Chrome, Edge, or Brave
#   - Run: npx playwright install chromium

# Login page keeps reappearing
#   - Run: node index.js --clear-session --login

# Prompt input never appears
#   - Run: node index.js --login
#   - Log in manually within 10 minutes

# Waiting for login message keeps repeating
#   - The active browser profile has no session for the selected provider
#   - Log in inside the opened window, or run: node index.js --clear-session --login

# Gemini prompt never becomes ready / asks to sign in
#   - Gemini typically requires a Google login
#   - Run: node index.js --login --provider gemini (or set it as default via --ai)

# Answer contains no Markdown formatting
#   - The copy button was not found within the polling window
#   - Re-run or refresh the browser page to retry

# Anonymous chat caps out / large prompt is refused
#   - Anonymous chats accept about 293 KB across ~6 parts on ChatGPT
#     (~170 KB on Gemini: ~29 KB parts due to its composer cap)
#   - Run: node index.js --login  and re-send (uploads as one attachment)

# Gemini rate-limited after rapid anonymous sends
#   - "did not start generating within 45s" or "stopped responding":
#     wait a minute and retry (or node index.js --continue),
#     or log in with: node index.js --login --provider gemini

# Unknown provider
#   - Run: node index.js --provider xyz  -> lists available providers (chatgpt, gemini)
#   - Pick one with --provider <name>, or set the default with --ai

# Conversation history not saving
#   - Ensure the project directory is writable
#   - Check that .chatgpt-conversations.json is not locked by another process

Testing

Unit tests cover CLI parsing, provider registry/preferences, and the transmission/answer-detection helpers. No browser is launched:

npm test

See testing.md for the per-file breakdown.

License

ISC