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

@sunilp-org/jam-cli

v0.3.0

Published

Jam — developer-first AI assistant CLI for the terminal. Ask questions, explain code, review diffs, generate patches, and run agentic tasks powered by Ollama.

Readme

╭───────────────────────────────────╮
│                                   │
│      ██╗  █████╗  ███╗   ███╗     │
│      ██║ ██╔══██╗ ████╗ ████║     │
│      ██║ ███████║ ██╔████╔██║     │
│  ██  ██║ ██╔══██║ ██║╚██╔╝██║     │
│  ╚████╔╝ ██║  ██║ ██║ ╚═╝ ██║     │
│   ╚═══╝  ╚═╝  ╚═╝ ╚═╝     ╚═╝     │
│                                   │
│   developer-first  AI  CLI        │
│                                   │
╰───────────────────────────────────╯

Jam CLI

The developer-first AI assistant for the terminal.

CI License: MIT Node.js 20+ PRs Welcome Conventional Commits

Ask questions • Explain code • Review diffs • Generate patches • Run agentic tasks

All from your command line, powered by Ollama, OpenAI, Groq, or any compatible provider.

Getting Started · Commands · Configuration · Contributing · Security


Why Jam?

Most AI coding tools are built around a single vendor's model, require a browser or IDE plugin, and send your code to a remote server you don't control.

Jam is different by design:

  • It runs entirely on your machine by default — your code never leaves your filesystem
  • It is not tied to any single model or provider — you choose the engine; Jam is the harness
  • It behaves like a proper Unix tool — pipeable, composable, and scriptable
  • It treats code modification as a transaction — validate first, preview always, confirm before applying
  • It is built to be contributed to — clean TypeScript, well-tested, architecture documented below

Highlights

| | Feature | Description | |---|---------|-------------| | ⚡ | Streaming output | Responses begin rendering on the first token | | 💬 | Interactive chat | Multi-turn sessions with history and resume | | 📂 | Repo-aware | Explain files, search code, review diffs with full workspace context | | 🩹 | Patch workflow | Generate unified diffs, validate, preview, and apply with confirmation | | 🤖 | Tool-calling agent | jam run gives the model access to local tools (read, search, diff, apply) | | 🔌 | Pluggable providers | Ollama, OpenAI, Groq, Embedded built-in; adapter pattern for adding any LLM | | 📦 | Embedded inference | [Experimental] Run without Ollama — tiny GGUF model runs directly in-process via node-llama-cpp | | ⚙️ | Layered config | Global → repo → CLI flags; multiple named profiles | | 🔐 | Secure secrets | OS keychain via keytar, env var fallback | | 🐚 | Shell completions | Bash and Zsh | | 🏠 | Privacy-first | Runs locally — your code never leaves your machine |


Design Philosophy

The best developer tools disappear into your workflow. They don't ask you to change how you work — they work the way you already do.

You own the model. Jam's ProviderAdapter is a clean interface — swap the AI engine with a config change, not a rewrite. No vendor lock-in, no model loyalty.

Your code stays private. The default is localhost. Nothing leaves your machine unless you explicitly point Jam at a remote provider. This isn't just a feature — it's the architecture.

Changes are transactions, not actions. jam patch validates with git apply --check before anything is touched, shows a full preview, and waits for explicit confirmation. No "undo" needed — changes never happen without your approval.

Unix composability. jam ask reads stdin, writes stdout, supports --json. It's a pipe stage, not a walled garden.

Security is configuration, not hope. Tool permissions (toolPolicy), allowed operations (toolAllowlist), and log redaction (redactPatterns) are declarative config — committable to .jamrc so your whole team inherits the same guardrails.


Who Is Jam For?

| Situation | Why Jam fits | |-----------|-------------| | You work in a security-sensitive codebase | Local-only by default — nothing leaves your machine | | You want to use different models for different tasks | Named profiles + provider adapter — switch with --profile | | You live in the terminal and resent leaving it | Every command is designed for the shell, not a browser tab | | You're on a corporate network that blocks AI services | Point baseUrl at an internal Ollama instance and you're done | | You want an AI tool that fits into CI/CD scripts | --json output, stdin support, non-zero exit codes on errors | | You want to contribute to an AI tool without fighting vendor APIs | The hard parts (streaming, tool-calling, config) are already built cleanly |


Quick Start

Provider Support

| Provider | Status | Notes | |----------|--------|-------| | Ollama | ✅ Default | Local inference via ollama serve | | OpenAI | ✅ Supported | Requires OPENAI_API_KEY | | Groq | ✅ Supported | Requires GROQ_API_KEY | | Embedded | ⚗️ Experimental | In-process via node-llama-cpp, no server needed |

Prerequisites

  • Node.js 20+
  • One of the following model backends:
    • Ollama running locally (ollama serve) + a pulled model (ollama pull llama3.2)
    • Embedded mode — no server needed! Uses node-llama-cpp to run a tiny GGUF model in-process. Install with: npm install node-llama-cpp (auto-downloads a ~250 MB model on first run)

Install

# Try instantly — no install required
npx @sunilp-org/jam-cli doctor

# Global install from npm
npm install -g @sunilp-org/jam-cli

# Homebrew (macOS / Linux)
brew tap sunilp/tap
brew install jam-cli

# Or run from source
git clone https://github.com/sunilp/jam-cli.git
cd jam-cli
npm install
npm run build
npm link          # makes `jam` available globally

Verify

jam doctor        # checks Node version, config, provider connectivity, ripgrep
jam auth login    # validates connection to Ollama

Commands

jam ask

One-shot question. Streams the response to stdout.

jam ask "What is the difference between TCP and UDP?"

# From stdin
echo "Explain recursion in one paragraph" | jam ask

# From a file
jam ask --file prompt.txt

# JSON output (full response + token usage)
jam ask "What is 2+2?" --json

# Override model
jam ask "Hello" --model codellama

# Use a named profile
jam ask "Hello" --profile work

Options:

| Flag | Description | |------|-------------| | --file <path> | Read prompt from file | | --system <prompt> | Override system prompt | | --json | Machine-readable JSON output | | --model <id> | Override model for this request | | --provider <name> | Override provider | | --base-url <url> | Override provider base URL | | --profile <name> | Use a named config profile | | --no-tools | Disable read-only tool use (file discovery) | | --no-color | Strip ANSI colors from output (global flag) | | -q, --quiet | Suppress all non-essential output (spinners, status lines, decorations) |


jam chat

Interactive multi-turn chat REPL (Ink/React TUI).

jam chat                         # new session
jam chat --name "auth refactor"  # named session
jam chat --resume <sessionId>    # resume a previous session

Keyboard shortcuts inside chat:

| Key | Action | |-----|--------| | Enter | Submit message | | Ctrl-C (once) | Interrupt current generation | | Ctrl-C (twice) | Exit chat |

Sessions are saved automatically to ~/.local/share/jam/sessions/ (macOS: ~/Library/Application Support/jam/sessions/).


jam explain

Read one or more files and ask the model to explain them.

jam explain src/auth/middleware.ts
jam explain src/api/routes.ts src/api/handlers.ts
jam explain src/utils/retry.ts --json

jam search

Search the codebase using ripgrep (falls back to JS if rg is not installed).

jam search "TODO"                          # plain search, prints results
jam search "useEffect" --glob "*.tsx"      # filter by file type
jam search "createServer" --ask            # pipe results to AI for explanation
jam search "error handling" --max-results 50

Options:

| Flag | Description | |------|-------------| | --glob <pattern> | Limit to files matching this glob (e.g. *.ts) | | --max-results <n> | Max results (default: 20) | | --ask | Send results to AI for analysis | | --json | JSON output (with --ask) |


jam diff

Run git diff and optionally review it with AI.

jam diff                    # review working tree changes
jam diff --staged           # review staged changes (ready to commit)
jam diff --path src/api/    # limit to a specific directory
jam diff --no-review        # just print the raw diff, no AI
jam diff --staged --json    # JSON output

jam review

Review a branch or pull request with AI.

jam review                        # review current branch against main
jam review --base develop         # diff against a different base branch
jam review --pr 42                # review a specific PR (requires GitHub CLI)
jam review --json                 # JSON output

Options:

| Flag | Description | |------|-------------| | --base <ref> | Base branch or ref to diff against (default: main) | | --pr <number> | Review a specific PR number (requires gh CLI) | | --json | Machine-readable JSON output |


jam commit

Generate an AI-written commit message from staged changes and commit.

jam commit                 # generate message, confirm, then commit
jam commit --dry           # generate message only, do not commit
jam commit --yes           # skip confirmation prompt
jam commit --amend         # amend the last commit with a new AI message

Options:

| Flag | Description | |------|-------------| | --dry | Generate the message but do not commit | | --yes | Auto-confirm without prompting | | --amend | Amend the last commit with a new AI-generated message |

Messages follow the Conventional Commits specification.


jam patch

Ask the AI to generate a unified diff patch, validate it, and optionally apply it.

jam patch "Add input validation to the login function"
jam patch "Fix the off-by-one error in pagination" --file src/api/paginate.ts
jam patch "Add JSDoc comments to all public methods" --dry   # generate only, don't apply
jam patch "Remove unused imports" --yes                      # auto-confirm apply

Flow:

  1. Collects context (git status, current diff, specified files)
  2. Prompts the model for a unified diff
  3. Validates with git apply --check
  4. Shows the patch preview
  5. Asks for confirmation (unless --yes)
  6. Applies with git apply

jam run

Agentic task workflow — the model can call tools in a loop to accomplish a goal.

jam run "Find all TODO comments and summarize them"
jam run "Check git status and explain what's changed"
jam run "Read src/config.ts and identify any security issues"

Available tools (model-callable):

| Tool | Type | Description | |------|------|-------------| | read_file | Read | Read file contents | | list_dir | Read | List directory contents | | search_text | Read | Search codebase with ripgrep | | git_status | Read | Get git status | | git_diff | Read | Get git diff | | write_file | Write | Write to a file (prompts for confirmation) | | apply_patch | Write | Apply a unified diff (prompts for confirmation) | | run_command | Write | Execute a shell command (dangerous patterns blocked; prompts for confirmation) |

Write tools require confirmation unless toolPolicy is set to allowlist in config.


jam auth

jam auth login    # validate connectivity to the current provider
jam auth logout   # remove stored credentials from keychain

jam config

jam config show            # print merged effective config as JSON
jam config init            # create .jam/config.json in the current directory
jam config init --global   # create ~/.config/jam/config.json

jam context

Manage the JAM.md project context file. This file is auto-read by jam ask and jam chat to give the model awareness of your project's architecture, conventions, and goals.

jam context init           # generate JAM.md at the workspace root
jam context init --force   # overwrite an existing JAM.md
jam context show           # display the current JAM.md contents

jam models list

jam models list            # list models available from the current provider
jam models list --provider ollama --base-url http://localhost:11434

jam history

jam history list           # list all saved chat sessions
jam history show <id>      # show all messages in a session (first 8 chars of ID work)

jam completion install

jam completion install                    # auto-detects shell
jam completion install --shell bash       # bash completion script
jam completion install --shell zsh        # zsh completion script

Follow the printed instructions to add the completion to your shell.


jam doctor

Run system diagnostics:

jam doctor

Checks:

  • Node.js version (≥ 20)
  • Config file is valid
  • Provider connectivity (Ollama reachable)
  • ripgrep availability (optional, JS fallback used if absent)
  • keytar availability (optional, env vars used if absent)

Configuration

Config File Locations

Jam merges config in priority order (highest wins):

1. CLI flags                              (--provider, --model, etc.)
2. .jam/config.json  or  .jamrc           (repo-level)
3. ~/.jam/config.json                     (user home-dir dotfile — preferred)
4. ~/.config/jam/config.json              (XDG user config — fallback)
5. Built-in defaults

Recommended: Use ~/.jam/config.json for your personal settings (provider, API keys, default model).
Use .jam/config.json at the repo root for project-specific overrides (tool policy, redact patterns).

Config Schema

{
  "defaultProfile": "default",
  "profiles": {
    "default": {
      "provider": "ollama",
      "model": "llama3.2",
      "baseUrl": "http://localhost:11434",
      "temperature": 0.7,
      "maxTokens": 4096,
      "systemPrompt": "You are a helpful coding assistant."
    },
    "fast": {
      "provider": "ollama",
      "model": "qwen2.5-coder:1.5b",
      "baseUrl": "http://localhost:11434"
    },
    "embedded": {
      "provider": "embedded",
      "model": "smollm2-360m"
    }
  },
  "toolPolicy": "ask_every_time",
  "toolAllowlist": [],
  "historyEnabled": true,
  "logLevel": "warn",
  "redactPatterns": ["sk-[a-z0-9]+", "Bearer\\s+\\S+"]
}

Config Fields

| Field | Type | Default | Description | |-------|------|---------|-------------| | defaultProfile | string | "default" | Active profile name | | profiles | object | see below | Named provider/model configurations | | toolPolicy | ask_every_time | allowlist | never | ask_every_time | How write tools require confirmation | | toolAllowlist | string[] | [] | Tools that never prompt (when policy is allowlist) | | historyEnabled | boolean | true | Save chat sessions to disk | | logLevel | silent | error | warn | info | debug | warn | Log verbosity | | redactPatterns | string[] | [] | Regex patterns redacted from logs |

Profile Fields

| Field | Type | Description | |-------|------|-------------| | provider | string | Provider name (ollama, openai, groq, embedded) | | model | string | Model ID (e.g. llama3.2, codellama) | | baseUrl | string | Provider API base URL | | apiKey | string | API key (prefer keychain or env vars) | | temperature | number | Sampling temperature (0–2) | | maxTokens | number | Max tokens in response | | systemPrompt | string | Default system prompt |

Initialize Config

# User-level — creates ~/.jam/config.json (recommended)
jam config init --global

# Repo-level — creates .jam/config.json (committed to version control)
jam config init

The global config at ~/.jam/config.json is the best place to set your default provider, model, API keys, and personal preferences. Edit it directly:

# Example: switch default provider to embedded
vim ~/.jam/config.json
{
  "defaultProfile": "default",
  "profiles": {
    "default": {
      "provider": "ollama",
      "model": "llama3.2",
      "baseUrl": "http://localhost:11434"
    },
    "openai": {
      "provider": "openai",
      "model": "gpt-4o-mini",
      "apiKey": "sk-..."
    },
    "offline": {
      "provider": "embedded",
      "model": "smollm2-360m"
    }
  },
  "toolPolicy": "ask_every_time",
  "historyEnabled": true,
  "logLevel": "warn"
}

Using Profiles

# Use a specific profile
jam ask "Hello" --profile fast

# Switch default in config
echo '{"defaultProfile": "fast"}' > .jamrc

Environment Variables

| Variable | Description | |----------|-------------| | JAM_API_KEY | API key fallback (if keytar unavailable) | | JAM_BASE_URL | Override provider base URL | | OPENAI_API_KEY | OpenAI API key (used when provider: openai) | | GROQ_API_KEY | Groq API key (used when provider: groq) |


Embedded Provider — Experimental ⚗️

⚠️ EXPERIMENTAL — The embedded provider is functional but quality is limited by small model sizes. For production workloads, use Ollama or OpenAI.

The embedded provider runs a tiny GGUF model directly in-process via node-llama-cpp. No Ollama installation, no server process, no network calls. Models are only downloaded when you explicitly set provider: "embedded" — it never downloads anything unless you opt in.

Setup

# Install the native dependency (optional — only needed for embedded mode)
npm install node-llama-cpp

# Switch to embedded provider
jam ask "Hello" --provider embedded

# Or set it permanently in your config
jam config init --global   # then edit ~/.jam/config.json

How It Works

  1. On first use, Jam auto-downloads a small model (~250 MB) to ~/.jam/models/
  2. The model loads in-process using llama.cpp bindings — no external server
  3. Streaming, tool-calling, and all standard commands work as usual

Available Models

| Alias | Size (Q4_K_M) | Notes | |-------|---------------|-------| | smollm2-135m | ~100 MB | Ultra-light, very fast, basic quality | | smollm2-360m | ~250 MB | Default — good quality-to-size ratio | | smollm2-1.7b | ~1 GB | Best quality for embedded, needs more RAM |

# Use a specific embedded model alias
jam ask "Explain git rebase" --provider embedded --model smollm2-1.7b

# Or point to any local GGUF file
jam ask "Hello" --provider embedded --model /path/to/custom-model.gguf

# Profile-based setup
# In ~/.jam/config.json:
# {
#   "profiles": {
#     "offline": {
#       "provider": "embedded",
#       "model": "smollm2-1.7b"
#     }
#   }
# }
jam ask "Hello" --profile offline

When to Use Embedded vs Ollama

| Scenario | Recommendation | |----------|---------------| | No Ollama / can't install system software | Embedded | | CI/CD pipeline, Docker container, SSH box | Embedded | | Air-gapped / offline machine | Embedded (after initial model download) | | Want best quality & larger models (7B+) | Ollama | | GPU acceleration needed | Ollama | | Already have Ollama running | Ollama |


Development

npm run dev -- ask "What is 2+2?"   # run from source with tsx
npm run build                         # compile TypeScript to dist/
npm run typecheck                     # tsc --noEmit
npm run lint                          # ESLint
npm test                              # Vitest unit tests
npm run test:watch                    # watch mode
npm run test:coverage                 # coverage report

Project Structure

src/
├── index.ts        # CLI entry point — command registration (Commander)
├── commands/       # One file per command (ask, chat, run, review, commit, …)
├── providers/      # LLM adapter layer — ProviderAdapter interface + Ollama, Embedded impl
├── tools/          # Model-callable tools + registry + permission enforcement
├── config/         # Zod schema, cosmiconfig loader, built-in defaults
├── storage/        # Chat session persistence (JSON files)
├── ui/             # Ink/React TUI (chat REPL) + Markdown/streaming renderer
└── utils/          # Shared helpers: streaming, logger, secrets, agent loop, tokens

Adding a New Provider

  1. Implement ProviderAdapter from src/providers/base.ts:
import type { ProviderAdapter, ProviderInfo, CompletionRequest, StreamChunk } from './base.js';

export class MyProvider implements ProviderAdapter {
  readonly info: ProviderInfo = { name: 'myprovider', supportsStreaming: true };

  async validateCredentials(): Promise<void> { /* ... */ }
  async listModels(): Promise<string[]> { /* ... */ }
  async *streamCompletion(request: CompletionRequest): AsyncIterable<StreamChunk> { /* ... */ }
}
  1. Register in src/providers/factory.ts:
if (provider === 'myprovider') {
  const { MyProvider } = await import('./myprovider.js');
  return new MyProvider({ apiKey: profile.apiKey });
}
  1. Use: jam ask "Hello" --provider myprovider

Contributing

Jam is intentionally built to be easy to extend. The architecture is layered, each concern is isolated, and the three main contribution surfaces — providers, tools, and commands — each have a clean interface to implement.

You don't need to understand the whole codebase to contribute. A new provider is one file. A new tool is one file. The patterns are already established and documented.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feat/amazing-feature)
  3. Commit your changes (git commit -m 'feat: add amazing feature')
  4. Push to the branch (git push origin feat/amazing-feature)
  5. Open a Pull Request

Please read our Contributing Guide for details on our code of conduct, development workflow, and pull request process.

Good First Issues

Look for issues labeled good first issue — these are great starting points for new contributors.

What the Codebase Looks Like

  • Strict TypeScript throughout — no any, no guessing what a function does
  • Tests colocated with sourcefoo.tsfoo.test.ts, using Vitest
  • One file per concern — each command, provider, and tool is self-contained
  • Zod schema validation — config is validated at load time, not at runtime when it's too late
  • Conventional Commits — the git log tells the story of the project

If you can read TypeScript, you can contribute to Jam.


Community


Security Policy

We take security seriously. If you discover a vulnerability, please do not open a public issue. Instead, follow the responsible disclosure process in our Security Policy.


Roadmap

  • [x] OpenAI provider
  • [ ] Azure OpenAI provider
  • [ ] Anthropic Claude provider
  • [x] Groq provider
  • [ ] Plugin system for custom tools
  • [ ] Token usage tracking and budgets
  • [ ] Web UI companion

Probable Enhancements

Ideas and directions under consideration. These range from quick wins to deep architectural changes. Contributions, RFCs, and discussion on any of these are welcome.

🧩 Plugin System

The tool registry (ToolRegistry.register()) already accepts any ToolDefinition, but tool discovery is hardcoded. A proper plugin system would allow external tools without modifying source.

  • Local plugins — load ToolDefinition modules from .jam/plugins/ or ~/.config/jam/plugins/
  • npm plugin packagesjam plugin install @scope/jam-plugin-docker discovers and registers tools at startup
  • Plugin manifest — declarative jam-plugin.json with name, version, tool definitions, required permissions
  • Lifecycle hooksonActivate, onDeactivate, beforeToolCall, afterToolCall for plugin-level middleware
  • Sandboxed execution — plugins run with restricted filesystem/network access based on declared capabilities
jam plugin install jam-plugin-docker
jam plugin list
jam plugin remove jam-plugin-docker

🎯 Skills

Skills are named, composable mini-agents — each with a focused system prompt, a curated tool subset, and a defined output contract. Think of them as recipes the model can invoke.

  • Built-in skillsrefactor, test-writer, documenter, security-audit, dependency-update, migration
  • Skill registry — each skill declares its name, description, required tools, system prompt template, and output schema
  • Composable — skills can call other skills (e.g., refactor invokes test-writer to verify changes)
  • User-defined skills.jam/skills/ directory with YAML/JSON skill definitions
  • Skill marketplace — share and import community skills via npm or a registry
# .jam/skills/api-endpoint.yaml
name: api-endpoint
description: Generate a new REST API endpoint with tests
tools: [read_file, write_file, search_text, run_command]
system: |
  You are an API endpoint generator. Given a resource name and
  fields, generate the route handler, validation, tests, and
  OpenAPI schema following the project's existing patterns.
output:
  type: files
  confirm: true
jam skill run refactor --file src/api/auth.ts
jam skill run test-writer --file src/utils/cache.ts
jam skill list

🤖 Sub-Agents & Task Decomposition

The current agent loop (jam run) is a single monolithic ReAct loop. Sub-agents would enable the planner to decompose complex instructions into specialized child tasks.

  • Planner agent — breaks a complex instruction into an ordered DAG of sub-tasks
  • Specialist delegation — each sub-task dispatched to a purpose-built sub-agent (e.g., "read and understand", "refactor", "write tests", "verify")
  • Result aggregation — parent agent collects sub-agent outputs and synthesizes a final result
  • Parallel sub-agents — independent sub-tasks execute concurrently (e.g., "write tests" and "update docs" in parallel)
  • Scoped context — each sub-agent receives only the context it needs, reducing token waste
  • Fail-and-retry isolation — a failed sub-agent can be retried without restarting the entire task
jam run "Refactor the auth module to use JWT, update all tests, and document the changes"
# Planner decomposes into:
#   1. [understand] Read current auth module and tests
#   2. [refactor]   Rewrite auth module with JWT
#   3. [test]       Update tests for new implementation  (parallel with 4)
#   4. [document]   Update docs and JSDoc comments        (parallel with 3)
#   5. [verify]     Run tests and validate the patch

🔌 Connectors

Connectors are adapters for external services — bringing data in and pushing results out. Currently Jam only understands the local filesystem and git.

  • GitHub — read/create issues, PRs, review comments; jam review --pr 42 already shells out to gh, a connector would be native
  • GitLab / Bitbucket — equivalent PR/MR workflows for non-GitHub teams
  • JIRA / Linear / Shortcut — fetch issue context, update status, attach AI-generated summaries
  • Slack / Discord — post review summaries, commit digests, or search results to channels
  • Database — read schema, run read-only queries, explain query plans
  • REST / GraphQL — generic HTTP connector for internal APIs (jam ask "Why is /api/users slow?" --connector api-prod)
  • Docker / K8s — read container logs, describe pods, inspect images
  • CI/CD — read build logs, trigger pipelines, analyze failures
// .jam/config.json
{
  "connectors": {
    "github": { "token": "env:GITHUB_TOKEN" },
    "jira": { "baseUrl": "https://myorg.atlassian.net", "token": "env:JIRA_TOKEN" },
    "postgres": { "connectionString": "env:DATABASE_URL", "readOnly": true }
  }
}

🧠 MCP (Model Context Protocol) Support

MCP is an open standard for connecting AI models to external tools and data sources. Adding MCP client support would let Jam consume any MCP-compatible server.

  • MCP client — Jam discovers and connects to MCP servers declared in config
  • Tool bridge — MCP tools appear as native Jam tools in the registry, usable by jam run
  • Resource bridge — MCP resources (files, database rows, API responses) injected as context
  • Prompt bridge — MCP prompt templates available as Jam skills
  • Server mode — expose Jam's own tools (read_file, search_text, git_diff, etc.) as an MCP server for other agents
{
  "mcp": {
    "servers": {
      "filesystem": { "command": "npx @modelcontextprotocol/server-filesystem /path/to/dir" },
      "postgres":   { "command": "npx @modelcontextprotocol/server-postgres", "env": { "DATABASE_URL": "..." } }
    }
  }
}

⚡ Parallel Tool Execution

Currently tools execute sequentially within each agent round. When the model requests multiple independent tool calls (e.g., read three files), they could run concurrently.

  • Dependency analysis — detect independent tool calls within a single round
  • Concurrent dispatchPromise.all() for independent read operations
  • Write serialization — write tools always execute sequentially and with confirmation
  • Progress display — show parallel tool execution status in real time

🔗 Middleware & Hooks

A middleware chain around LLM calls and tool executions, enabling cross-cutting concerns without modifying core logic.

  • Pre/post LLM hooks — prompt injection defense, cost tracking, audit logging
  • Pre/post tool hooks — rate limiting, output sanitization, metrics
  • Error interceptors — custom retry logic, fallback providers, graceful degradation
  • Event emitter — structured events (tool:start, tool:end, llm:stream, agent:iteration) for UI decoupling, telemetry, and external integrations
// .jam/middleware/cost-tracker.ts
export default {
  name: 'cost-tracker',
  afterCompletion({ usage, provider, model }) {
    const cost = estimateCost(provider, model, usage);
    appendToLog(`~/.jam/cost.csv`, { timestamp: Date.now(), model, cost });
  }
};

🧭 Embeddings & Vector Search

The current past-session search uses keyword overlap (Jaccard scoring), and the symbol index is regex-based. Optional local embeddings would enable true semantic search.

  • Local embedding model — use Ollama's embedding endpoint (nomic-embed-text, mxbai-embed-large) so nothing leaves your machine
  • Codebase index — vector index of functions, classes, and doc comments stored at .jam/vectors/
  • Semantic code searchjam search "authentication flow" returns semantically relevant code, not just keyword matches
  • Session memory — embed past Q&A pairs for cross-session context recall with relevance decay
  • RAG pipeline — retrieve relevant code chunks before prompting, reducing token usage and improving accuracy

💰 Cost & Token Tracking

TokenUsage is already captured per request but not aggregated or displayed.

  • Session cost estimation — estimate cost based on provider pricing (configurable per-profile)
  • Budget limitsmaxCostPerSession, maxCostPerDay in config; warn or hard-stop when exceeded
  • Usage dashboardjam usage command showing tokens consumed, cost by model, by command, over time
  • Token budget per tool call — prevent runaway context from a single large file read
jam usage                # summary: today, this week, this month
jam usage --detail       # per-session breakdown
jam usage --export csv   # export for expense tracking

📦 Multi-File Transactions

apply_patch and write_file currently operate on single files with no rollback mechanism.

  • Transaction block — group multiple file writes into an atomic operation
  • Git stash checkpoint — auto-stash before a multi-file edit, restore on failure
  • Dry-run preview — show all proposed changes across files before any writes
  • Selective accept — accept/reject individual file changes within a transaction

🔍 Provider Capabilities & Feature Negotiation

The ProviderAdapter interface treats all providers equally, but providers differ in capabilities.

  • Capability flagssupportsToolCalling, supportsVision, supportsStructuredOutput, supportsEmbeddings on ProviderInfo
  • Graceful degradation — if a provider doesn't support tool calling, fall back to prompt-based tool simulation
  • Model capability discovery — query the provider for model-specific features at runtime
  • Auto-routing — route tasks to the best-fit model/provider (e.g., use a fast model for planning, a capable model for generation)

🧠 Persistent Agent Memory

Working memory is currently session-scoped. Cross-session memory would make Jam smarter over time.

  • Workspace knowledge base — facts, patterns, and conventions learned from past sessions, stored per-repo
  • Memory decay — older memories lose relevance weight over time unless reinforced
  • Explicit memoryjam remember "the auth module uses bcrypt, not argon2" for user-declared facts
  • Memory retrieval — automatically surface relevant memories during planning and synthesis
  • Forgettingjam forget to clear or selectively prune memories

🌐 Web UI Companion

A local web interface for sessions that benefit from richer display.

  • Diff viewer — syntax-highlighted side-by-side diffs for jam patch and jam review
  • Session browser — visual history of past chat sessions with search
  • Tool call inspector — expandable timeline of every tool call, its input, output, and duration
  • Markdown preview — rendered Markdown responses with code block copy buttons
  • Served locallyjam ui starts a local server; no external hosting

🧪 Testing & Verification Skills

First-class support for test generation and verification.

  • Test generationjam test generate src/utils/cache.ts generates tests matching project conventions
  • Test-driven patchjam patch can optionally run tests before and after applying changes
  • Coverage-aware context — prioritize uncovered code paths in review and audit workflows
  • Regression detection — track which tests fail after a patch and auto-revert if needed

🐚 Shell Integration & Workflow Automation

Deeper shell integration for power users and CI/CD pipelines.

  • Git hooksjam hooks install sets up pre-commit (auto-lint), prepare-commit-msg (AI message), pre-push (review)
  • Watch modejam watch monitors file changes and provides continuous AI feedback
  • Pipeline mode — structured JSON I/O for chaining Jam commands in shell scripts and CI
  • Makefile/Taskfile recipes — pre-built task definitions for common workflows

Acknowledgments

Built with these excellent open source projects:


License

MIT License — Copyright (c) 2026-present Sunil Prakash. All rights reserved.

See LICENSE for the full license text.


Made with ❤️ by Sunil Prakash

If you find Jam useful, consider giving it a ⭐ on GitHub — it helps others discover the project!