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

gsmart

v0.17.0

Published

CLI to generate smart commit messages using AI.

Readme

GSmart

Your changes. A clear commit message.

GSmart is a CLI that turns your Git diff into an AI-generated Conventional Commit. Review the suggestion, edit it, refine it with feedback, copy it, or commit—all from your terminal.

NPM Version Test codecov NPM Downloads License: GPL-3.0-only

Quick start · Everyday workflows · Configuration · Providers · Command reference · Troubleshooting

GSmart banner with Git branching and AI icons

  • Start with your actual changes. Generate a message from your staged diff and branch name, or choose files interactively.
  • Keep the final say. Review each suggestion before committing, or use --yes for a non-interactive workflow.
  • Bring your preferred provider and model. Save defaults for six hosted providers, or connect a local OpenAI-compatible endpoint such as Ollama or LM Studio. OpenAI supports ChatGPT subscription login and API keys.
  • Make it sound like your project. Share repository conventions, save personal writing instructions, and add context for individual commits.

First visit? Follow the quick start below. Already using GSmart? Jump to the workflow recipes, shell completions, or release notes.

Quick start

You'll need Node.js 22.12.0+, Git 2.25+, and either an account with one of the supported providers or a local inference server. Run GSmart inside the Git repository you're working on.

1. Install

Choose your package manager:

npm install -g gsmart
pnpm add -g gsmart
yarn global add gsmart

2. Connect a provider

gsmart login

Select a provider, then follow its sign-in flow:

  • OpenAI: choose ChatGPT subscription to authorize in your browser, or API key to paste a key.
  • Other hosted providers: paste an API key when prompted. See the provider table for links.
  • Custom (OpenAI-compatible): enter your API base URL and model ID. Leave the key blank for a keyless local server.

Credentials are saved locally for future runs. On macOS/Linux, credential files are restricted to your user (0600), including existing files when GSmart starts. You can run gsmart login again to add another provider or update your authentication. If GSmart cannot open a browser for ChatGPT login, open the printed authorization URL manually.

3. Generate and review

Stage the changes you want to describe, then run GSmart. Replace the example path with a file you've changed:

git add src/auth.ts
gsmart

A typical interaction looks like this; the generated message depends on your changes:

$ gsmart
✔ Message generated

Candidate #1 (generated):
feat(auth): add password reset
? What would you like to do?
❯ Commit
  Edit message
  Regenerate with feedback
  Browse / restore candidates
  Copy message to clipboard
  Do nothing

| Action | What happens | | --------------------------- | ---------------------------------------------------------------------------------------- | | Commit | Checks staged content, then creates a local Git commit using the selected message. | | Edit message | Opens the subject and multiline body in your editor, then returns to review. | | Regenerate with feedback | Uses your feedback and current candidate to request a revised message. | | Browse / restore candidates | Compares complete messages and restores an earlier candidate without another AI request. | | Copy message to clipboard | Copies the message so you can use or edit it elsewhere. | | Do nothing | Ends the run, leaving your changes available for later. |

Nothing staged yet? Run gsmart and use the file picker to choose what to stage. If you have multiple providers configured and no saved default or explicit --provider, you'll also be asked which one to use.

How it works

Stage or select changes → Generate a message → Review → Edit, refine, restore, copy, or commit
  1. Read the changes. GSmart uses your staged diff—the changes Git is ready to commit. If that diff is empty, it offers to stage files for you.
  2. Ask your provider. It sends the diff, current branch name, resolved commit conventions, and any custom instructions to the selected AI provider. Recent commit subjects are also sent when you enable history examples.
  3. Choose the next step. You review the message before committing. Commits use git commit, so your Git hooks still run; pushing remains a separate Git step.

Already staged part of a file with git add -p? GSmart uses that staged diff. Other unstaged edits are left out. Files staged through the interactive picker stay staged if you choose Copy or Do nothing.

A quick guide to Conventional Commits

The format makes a project's history easier to scan:

feat(auth): add password reset
│    │     └─ Short description of the change
│    └─────── Optional scope: the area affected
└──────────── Type: the kind of change

Common types include feat for new functionality, fix for a bug fix, docs for documentation, and refactor for restructuring code without changing its behavior. GSmart asks the model to follow this format; review the suggestion for accuracy before committing.

For better suggestions: stage one logical change at a time and use a custom prompt to explain context the diff cannot show.

Everyday workflows

Edit and refine a message

Choose Edit message to change the subject and multiline body in an external editor. The first line is the subject; separate the body with a blank line. Save and close the file to return to review, then select Commit when satisfied.

Choose Regenerate with feedback for targeted changes such as “shorter”, “mention the migration”, or “this fixes a bug”. Submit blank feedback for another version. Refinement reuses the selected provider and model, captured branch and diff, custom instructions, and current candidate—including manual edits.

Example review session:

Candidate #1 (generated):
feat(db): add accounts migration and initialize account records
? What would you like to do? › Regenerate with feedback
? What should change? › shorter; mention the migration
✔ Message generated

Candidate #2 (refined):
feat(db): add accounts migration
? What would you like to do? › Edit message

Candidate #3 (edited):
feat(db): add accounts migration

Preserve existing account IDs during migration.
? What would you like to do? › Commit
✔ Changes committed successfully

Browse / restore candidates previews complete messages alongside the current candidate. Confirm Restore to select one without another AI request. History includes generated, edited, and refined messages and lasts for the current invocation only. Editing, refining, and restoring always return to review.

Press Esc to cancel feedback or candidate browsing. Press Ctrl+C during a refinement request to cancel it and return to the current candidate. Errors and canceled operations preserve the current candidate and never create a commit.

SIGTERM requests shutdown instead of returning to review. GSmart cancels the active editor or refinement operation, finishes cleanup, and exits.

Configure your editor

GSmart uses the first non-empty setting in $VISUAL, then $EDITOR. If neither is set, it uses vi on macOS/Linux or notepad on Windows. Editor arguments and quoted executable paths are supported. Configure GUI editors to wait until you close the message file:

# VS Code (Bash/Zsh)
export VISUAL="code --wait"

# Or use a terminal editor
export EDITOR="nano"
# VS Code (Windows PowerShell)
$env:VISUAL = "code --wait"

To cancel editing, quit the editor without saving (for example, :q! in vi); an unchanged file leaves the current candidate selected. If you already saved changes, restore the earlier candidate from history. Editor failures keep the current candidate and display an error so you can retry. Empty or invalid edits remain selected as drafts: correct them with Edit message, regenerate, or restore an earlier candidate. Temporary editor files are cleaned up afterward.

If staged content changes during review

Before committing, GSmart checks the staged content and its Git base again. If they have changed, it marks the candidate as outdated and offers to generate a fresh message using the same provider. Review that message and select Commit again. Earlier candidates remain available for comparison or copying; restoring or editing one does not bypass this check. Declining or canceling the refresh keeps the current candidate.

Choose a provider for this run

After configuring it with gsmart login:

gsmart --provider anthropic
gsmart --provider anthropic --model claude-haiku-4-5-20251001

Use the exact identifier from the provider table. These options select a provider and model for the current run without changing saved preferences. See provider and model defaults to make the choice persistent.

Preview before committing

Generate a message and list the files in the analyzed diff:

gsmart --dry-run

Dry run still makes an AI request and needs a configured provider (authentication is optional for custom endpoints). It skips committing and the final action menu. If nothing is staged, GSmart temporarily stages your selected files to read their diff, then attempts to unstage them. Existing staged changes stay staged.

Plan coherent commits from mixed changes

Request an advisory split plan for the existing staged diff:

gsmart plan --staged
gsmart plan --staged --provider anthropic --model claude-haiku-4-5-20251001
gsmart plan --staged --context-budget 16384 --show-context

--staged explicitly selects the scope: all staged changes throughout the repository, including when run from a subdirectory. Unstaged and untracked content is not included. Planning, reading the plan, and canceling with Ctrl+C leave HEAD, the index, and working-tree files unchanged. An empty staged diff is an error.

The plan suggests Conventional Commit messages, identifies the files or hunks assigned to each commit, explains the grouping, and lists ordering dependencies and uncertainties. A coherent diff can receive one commit. For example, a dependency update coupled to a retry feature could produce:

Staged commit plan (advisory)
2 proposed commit(s). Scope: captured staged diff only.
Repository unchanged. Review grouping and ordering; independent applicability/builds are not guaranteed.
Mixed concerns within a hunk or whole-file unit require manual splitting; each unit is assigned intact here.

1. [deps] build(deps): update retry library
   Why: Keep the dependency manifest and lockfile in sync.
   - f1.h1: "package.json" — modified, source; @@ -12,3 +12,3 @@
   - f2: "pnpm-lock.yaml" — modified, lockfile; whole file (keep together)

2. [retry] feat(api): retry transient request failures
   Why: Group the retry implementation with its regression tests.
   - f3.h1: "src/request.ts" — modified, source; @@ -20,7 +20,12 @@
   - f4: "test/request.test.ts" — added, source; whole file (keep together)
   Depends on [deps]: Uses the newly introduced retry API.
   Review: Verify retry timing and failure behavior before committing.

Accounting: 4 change unit(s) assigned exactly once; 0 excluded unit(s) listed for manual review.

Change IDs and hunk ranges refer to the captured staged snapshot. Ordinary modified source files are identified by hunk. Renames/copies (including their original paths), additions, deletions, binaries, mode changes, submodule updates, lockfiles, and generated files are kept as whole-file units. A file assigned across several commits is explicitly marked for manual splitting. Mixed concerns inside one hunk or whole-file unit also need manual review; the plan does not provide executable patches. Review dependencies and make the intended staging selections yourself before committing.

Every included unit must appear exactly once. Invalid responses with missing, duplicated, or invented IDs, malformed messages, or invalid dependency ordering fail instead of displaying a partial plan. GSmart also checks the staged snapshot again before displaying the result; if staging, HEAD, or the branch changed during generation, rerun the command.

Planning uses the configured provider, model, repository conventions, language, and optional history examples. Provider selection is prompt-free: explicit --provider, saved default, then the first configured provider. --prompt, --language, --history-examples, and the context options are supported. The human-readable plan goes to stdout; diagnostics, debug output, and --show-context go to stderr. Planning rejects --yes, --dry-run, --stage, --commit, --stdin, --branch, and --output.

Large or excluded changes: the complete ID inventory is retained even when diff context is condensed or summarized, and affected groups receive a review note. Excluded paths and contents are not sent to the provider; those files appear separately as unassigned manual-review items with an explicit accounting total. If all files are excluded, the result lists only manual-review items and makes no AI request; no configured provider, credentials, model, or endpoint is required. This applies to CLI and repository exclusions, and the local result still checks snapshot freshness before display. If the inventory cannot fit, increase --context-budget, shorten instructions/history, or plan a smaller staged scope. If a plan exhausts its output allowance, increase context.outputTokens in .gsmartrc.json (and the total budget if needed), then retry. Plan quality still depends on the available diff evidence and model.

Exit status is 0 for a displayed plan, 1 for a configuration/Git/generation failure, 2 for invalid usage, 130 for SIGINT, and 143 for SIGTERM.

Skip the generation prompts

Use --yes when you're ready to generate and commit in one step:

gsmart --yes --provider openai

A hosted login or custom endpoint must already be configured. GSmart uses an explicit --provider, then your saved default provider, then the first configured provider in the table's order. Provider selection, model resolution, and model-specific context-budget validation happen before file selection or auto-staging.

--yes skips message review and editing. Invalid messages, changed staged content, or an unverifiable staged snapshot stop the command with exit status 1 before committing. Correct the reported issue and rerun GSmart.

Initial generation failures and failed commits also exit with status 1, so automation can detect them. A failed commit displays Git's diagnostic (including hook failures) and attempts to copy the generated message to the clipboard; if copying fails, it prints the message for recovery.

| Command | If a staged diff exists | If nothing is staged | Creates a commit? | | ------------------------ | ----------------------- | --------------------------------------------- | ----------------- | | gsmart | Uses it | Prompts you to select files to stage | If you choose it | | gsmart --dry-run | Uses it | Prompts, temporarily stages, then unstages | No | | gsmart --yes | Uses it | Stages all detected changes | Automatically | | gsmart --yes --dry-run | Uses it | Temporarily stages all changes, then unstages | No |

The staging rule: an existing staged diff always takes priority. --yes only auto-stages all detected changes when that diff is empty. Dry-run cleanup reports a warning if files could not be unstaged.

Scripting, editors, and hooks

Use --output message or --output json for a prompt-free generation workflow. These modes read the existing staged diff by default and leave the index, working tree, and HEAD untouched. An empty index is an error; files are never selected or staged implicitly.

# Capture only the commit message, preserving multiline output
message=$(gsmart --output message) || exit $?
printf '%s\n' "$message"

# Save one machine-readable result, including failures
gsmart --output json > result.json

# Generate from a supplied diff, including outside a Git repository
gsmart --stdin --branch feature/SHOP-142 --output json < changes.patch

# Describe unstaged tracked changes without staging them (Bash/Zsh)
set -o pipefail
git diff --no-ext-diff --no-textconv --no-color | gsmart --stdin

# Explicit staging and committing are independent
gsmart --stage --output message          # Stage all changes and generate only
gsmart --commit --output json            # Generate and commit existing staged changes
gsmart --stage --commit --output json    # Stage all, generate, and commit

--stdin, --branch, --stage, and --commit also select this noninteractive workflow; output defaults to message. These flags apply only to generation, including the compatibility alias gsmart generate.

  • Output: message mode writes only the generated message with a final newline to stdout. On failure stdout is empty. JSON mode writes exactly one JSON object followed by a newline, on success or failure. Diagnostics, configuration-loader logging, and --debug output go to stderr; greetings, update notices, holiday messages, spinners, and menus are suppressed. Explicit --help and --version requests still print their normal text instead of a generation result.
  • Input: --stdin reads UTF-8 until EOF, up to 64 MiB. Empty input and terminal input are errors. It neither requires Git nor infers a branch; --branch supplies optional branch context. Repository conventions and history settings apply when the current directory is inside a repository; otherwise personal/default conventions and CLI overrides apply. It cannot be combined with --stage or --commit.
  • Provider: selection follows explicit --provider → saved default → first configured provider in the provider table. Missing configuration fails immediately with setup guidance. Machine workflows never prompt to select a provider or enlarge the context budget; context failures include retry guidance.
  • Staging: --stage stages all tracked and untracked changes throughout the repository, even when some changes were already partially staged. Configuration is validated first. Explicitly staged changes remain staged if subsequent generation or committing fails.
  • Committing: --commit verifies the original staged snapshot before committing. A changed snapshot stops the operation. Hook and signing failures preserve Git's diagnostic; JSON also retains the generated message. Machine workflows do not use the clipboard.

The existing --yes and --dry-run workflows retain the behavior in the table above. They cannot be combined with machine-workflow flags: use --output message for generation-only operation and explicitly add --stage or --commit as needed. In particular, legacy --yes auto-stages only when the index is empty, whereas explicit --stage always stages all changes.

JSON result contract

The versioned schema is published as schemas/generation-result.schema.json, also available from the npm package at gsmart/schemas/generation-result.schema.json.

Success:

{
  "schemaVersion": 1,
  "ok": true,
  "message": "fix(api): retry failed requests",
  "provider": "custom",
  "model": "local-model",
  "input": { "source": "index", "branch": "main" },
  "staged": false,
  "committed": false
}

input.source is index or stdin; input.branch is null when no branch context is available. staged means explicit staging was performed by this invocation, not that the index contains staged files. --show-context adds the existing per-file context report to the JSON object; in message mode that report goes to stderr.

Failure:

{
  "schemaVersion": 1,
  "ok": false,
  "error": {
    "code": "NO_INPUT",
    "message": "No diff received on stdin. Pipe or redirect a non-empty diff."
  }
}

Stable error.code values are USAGE, CONFIGURATION, AUTHENTICATION, INPUT, NO_INPUT, CONTEXT, GENERATION, VALIDATION, GIT, CANCELED, and INTERNAL. Human-readable error text may change. A failure after generation may include a top-level message for recovery. Validation failures retain the rejected candidate and include error.diagnostics: entries have code, severity (1 warning, 2 error), and message, with optional one-based line, configuration source, and imported rule. Warnings alone permit success and are printed to stderr. Metadata-overflow errors include error.recovery with current/required/maximum budgets and, when possible, suggestedBudgetTokens.

| Exit status | Meaning in machine workflows | | ----------- | ------------------------------------------------------------------------------------- | | 0 | Generation and any requested commit succeeded | | 1 | Configuration, authentication, input, context, generation, Git, or unexpected failure | | 2 | Invalid arguments or incompatible options | | 130 | Canceled by SIGINT (Ctrl+C) | | 143 | Canceled by SIGTERM |

SIGINT/SIGTERM cancel stdin reading or the active AI request and emit a failure result. Completed explicit staging remains in the index. Check exit status and ok before using a message:

if result=$(gsmart --output json); then
  printf '%s\n' "$result" | jq -r '.message'
else
  status=$?
  printf '%s\n' "$result" | jq -r '.error.message' >&2
  exit "$status"
fi

For an optional .git/hooks/prepare-commit-msg integration, generate from the existing index and let Git perform the commit:

#!/bin/sh
# Preserve messages supplied by -m/-F, merges, and other explicit sources.
[ -z "${2:-}" ] || exit 0
message=$(gsmart --output message) || exit $?
printf '%s\n' "$message" > "$1"

Give one commit extra context

Explain the intent behind a change:

gsmart --prompt "This fixes checkout retries after a payment timeout; reference SHOP-142."

This replaces repository or saved personal custom instructions for this run. Structured conventions such as allowed types and length limits still apply. To reuse a style across commits, configure repository conventions or save a default prompt.

Stay up to date

Use the package manager you installed with:

# npm
npm install -g gsmart@latest

# pnpm
pnpm add -g gsmart@latest

Check your installation with gsmart --version. The changelog covers new features, model updates, fixes, and runtime requirement changes.

Configuration

Provider and model defaults

Use the gsmart config menu to save a default provider, choose a model, or configure a custom endpoint. The equivalent flags work without interactive prompts:

gsmart config --default-provider anthropic
gsmart config --provider anthropic --model claude-haiku-4-5-20251001
gsmart config --show

# One invocation; does not change the saved settings
gsmart --provider openai --model gpt-5-codex --dry-run

# Return to automatic provider selection or a built-in model
gsmart config --clear-default-provider
gsmart config --provider anthropic --clear-model

Provider and prompt settings can be updated together. Add --show to inspect the saved result:

gsmart config --default-provider anthropic --add-custom-prompt "Use Spanish" --show

In the Set preferred model menu, the current model is displayed for reference. Submit blank input to clear it, or press Esc to keep it.

Selection precedence is:

| Setting | First choice | Second choice | Fallback | | -------- | --------------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------- | | Provider | Explicit --provider | Saved default provider | One configured provider automatically; a chooser if several exist; first configured provider under --yes | | Model | Explicit --model | Saved model for the selected provider | Built-in model, with a separate ChatGPT OAuth fallback |

An explicit or saved provider must be configured; GSmart reports setup instructions rather than silently choosing another provider. A custom endpoint is configured when it has a valid base URL and a saved model (or a --model override). It does not need a hosted-provider login. Custom endpoints have no built-in model because model IDs depend on the server.

Model IDs are trimmed and must be nonempty. Availability is checked by the provider during generation, so new or private models do not need to be added to GSmart's source code. --model does not change the API operation or authentication mode. Provider and model selection remain the same during refinement and staged-change regeneration.

Local inference and custom endpoints

The custom provider uses OpenAI-compatible Chat Completions (POST <base-url>/chat/completions). Configure the base URL, including /v1 when required, rather than the full operation URL. You can save one custom endpoint per configuration directory; use GSMART_CONFIG_DIR for separate profiles.

Ollama

Install Ollama, start its server (ollama serve, or the desktop app), and download a model. With the server running:

ollama pull llama3.2
gsmart config --provider custom \
  --base-url http://localhost:11434/v1 \
  --model llama3.2 --clear-api-key
gsmart config --default-provider custom

# Run inside a Git repository with staged changes
gsmart --dry-run

The local Ollama server does not require a key. Use the exact installed model ID, including its tag. Ollama's native /api/chat endpoint is not the OpenAI-compatible URL. See Ollama's compatibility documentation.

LM Studio

Download and load a text-generation model in LM Studio, then start the server from its Developer tab. With the default port and authentication disabled:

# Find the model identifier returned by your server
curl http://localhost:1234/v1/models

# Replace MODEL_ID with that identifier
gsmart config --provider custom \
  --base-url http://localhost:1234/v1 \
  --model MODEL_ID --clear-api-key
gsmart config --default-provider custom
gsmart --dry-run

See LM Studio's OpenAI-compatible endpoints. If server authentication is enabled, configure its token instead of --clear-api-key.

Optional authentication and compatibility

# Set the custom server's bearer token; hosted keys are configured through login
gsmart config --provider custom --api-key YOUR_ENDPOINT_KEY

# Remove authentication; requests will contain no Authorization header
gsmart config --provider custom --clear-api-key

# Remove the URL, model, key, and default-provider selection if it points to custom
gsmart config --clear-custom-endpoint

You can also choose Custom (OpenAI-compatible) in gsmart login, or Configure custom / local endpoint in gsmart config, to enter the key through a password prompt. A blank key clears any previous custom key. Custom keys have no hosted-provider prefix or minimum-length requirement. Custom requests use only the custom key; they never inherit OpenAI API keys or ChatGPT tokens.

The server must accept text system/user messages and return a standard Chat Completions response. GSmart's custom integration does not use the Responses API, native Ollama/LM Studio APIs, legacy text completions, or automatic protocol detection. A Responses-only model needs a provider/API integration that supports it. Local models must be downloaded/loaded separately and have enough context for the diff and instructions. Model quality, context limits, and hardware determine results and latency; increase GSMART_TIMEOUT for slow inference.

Save your preferred commit style

Use gsmart config for the interactive menu, or set instructions directly:

gsmart config --add-custom-prompt "Use imperative mood, keep the subject concise, and use directory names as scopes."

# Read your saved prompt
gsmart config --show

# Clear it and return to the built-in instructions
gsmart config --clear-custom-prompt

Custom instructions are selected in this order:

  1. A nonempty --prompt for the current run.
  2. The repository's instructions setting, if present in .gsmartrc.json.
  3. Your saved default prompt.
  4. Built-in instructions alone.

The selected text is added to the resolved Conventional Commits instructions. These custom-instruction sources replace each other rather than concatenate. Repository "instructions": "" explicitly clears inherited personal instructions. config --show displays the saved personal prompt and provider/model preferences, with authentication status but no credential values.

Shared repository conventions

Create and commit .gsmartrc.json at your Git root. GSmart uses that same file from the root or any nested directory, including in Git worktrees. Nested .gsmartrc.json files do not override the root file.

{
  "$schema": "https://raw.githubusercontent.com/ragnarok22/gsmart/main/schemas/gsmartrc.schema.json",
  "types": ["feat", "fix", "docs", "refactor", "test", "chore"],
  "scopes": ["cli", "utils", "deps"],
  "scope": "optional",
  "headerMaxLength": 72,
  "subjectMaxLength": 60,
  "language": "en",
  "tickets": {
    "prefixes": ["APP-"],
    "required": false,
    "placement": "footer",
    "footerToken": "Refs"
  },
  "body": {
    "presence": "optional",
    "maxLineLength": 100,
    "instructions": "Explain why the change is needed when it is not obvious."
  },
  "breakingChanges": {
    "requireFooter": true,
    "instructions": "Describe the impact and any migration steps."
  },
  "instructions": "Use imperative mood and describe observable changes.",
  "commitlint": true,
  "history": { "enabled": false, "limit": 5 }
}

The JSON Schema is included in the npm package as gsmart/schemas/gsmartrc.schema.json. Use the $schema URL for editor support; runtime validation uses the bundled schema without a network request. All settings are optional. Unknown properties, malformed JSON, and invalid values stop generation with the config path and setting to correct, before file selection or auto-staging.

| Setting | Meaning and default | | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | types | Allowed types; defaults to feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert. null allows any Conventional Commit type. | | scopes | Allowed scopes, or null for unrestricted scopes (default). For multiple scopes separated by /, \ or ,, each component must be allowed. | | scope | optional (default), required, or forbidden. | | headerMaxLength | Maximum length of the entire first line, including type and scope. Positive integer or null (default: no limit). | | subjectMaxLength | Maximum length of the description after type(scope): . Positive integer or null (default: no limit). | | language | Output language tag, such as en (default), es, or pt-BR. Type tokens, scopes, ticket IDs and footer labels retain their configured spelling. | | tickets | prefixes (default null, unrestricted), required (default false), placement (subject, body, or default footer), and footerToken (default Refs). Configured prefixes are followed by numeric IDs. Supply IDs in the branch, changes, or prompt; historical IDs must not be reused. | | body | presence (optional, required, forbidden), leadingBlank (default true), maxLineLength (default null; URL-containing lines are exempt), and optional instructions. | | footer.leadingBlank | Separate footers from preceding content with a blank line (default true). | | breakingChanges | requireFooter (default false) requires a BREAKING CHANGE: footer for breaking changes even with a ! header; instructions supplies migration/impact guidance. | | instructions | Additional generation instructions, up to 10,000 characters. Body and breaking-change instructions have the same limit. | | commitlint | Import compatible rules from a root commitlint configuration (default true). Set to false to skip discovery and loading. | | history | enabled (default false) and limit (1–20, default 5). | | context | Request budgets, context exclusions, generated-file patterns, and opt-in AI summarization. See Large diffs and AI context. |

Configuration is merged per setting, from highest to lowest priority:

  1. Explicit CLI options (--prompt, --language, --history-examples, and context overrides).
  2. .gsmartrc.json settings.
  3. Compatible rules imported from the repository's commitlint configuration.
  4. User settings (currently the saved default prompt).
  5. Built-in defaults.

Nested objects merge by individual field; arrays replace rather than concatenate. Explicit false, null where allowed, and empty instruction strings override inherited values. CLI options override their corresponding settings, not the entire repository configuration. Structured conventions take precedence over conflicting free-text instructions or refinement feedback. The resolved settings are reused throughout generation, refinement, and staged-change regeneration.

Inspect the effective configuration, including source paths, imported rule severity, and compatibility diagnostics:

gsmart config --show-effective
gsmart config --show-effective --language es --history-examples 0

Run --show-effective separately from flags that save or clear settings. Conflicting update options are rejected before any settings are saved.

Conventions guide AI generation and deterministic message validation. Review the result for accuracy; Git hooks still run and can enforce additional project rules.

Repository configuration accepts no API keys, OAuth tokens, or provider credentials. Login continues to use the active user-level store selected by GSMART_CONFIG_DIR; gsmart reset clears that store. Repository files are maintained through Git.

Commitlint compatibility

GSmart uses @commitlint/load to resolve presets and synchronous/asynchronous rule factories. Referenced presets and plugins must be installed in your repository. JavaScript and TypeScript configuration executes through the standard loader when integration is enabled.

Discovery is limited to the Git root, in this order: the commitlint field in package.json; .commitlintrc, .commitlintrc.json, .commitlintrc.yaml, .commitlintrc.yml; .commitlintrc.{js,cjs,mjs}; commitlint.config.{js,cjs,mjs}; .commitlintrc.{ts,cts,mts}; commitlint.config.{ts,cts,mts}. Parent/global and nested configurations are not searched. package.yaml manifests are not a discovery source.

| Rule | Supported form | GSmart setting | | ---------------------- | --------------------------------------------------------------------------------- | ------------------------------------------- | | type-enum | always with a string array | types | | scope-enum | always with a string array, using commitlint's default /, \, , delimiters | scopes | | scope-empty | always / never | scope: "forbidden" / "required" | | header-max-length | always with a positive integer or Infinity | headerMaxLength | | subject-max-length | always with a positive integer or Infinity | subjectMaxLength | | body-empty | always / never | body.presence: "forbidden" / "required" | | body-leading-blank | always / never | body.leadingBlank: true / false | | body-max-line-length | always with a positive integer or Infinity | body.maxLineLength | | footer-leading-blank | always / never | footer.leadingBlank: true / false |

Severity 0 disables import of that rule; severities 1 and 2 supply generation conventions and retain warning/error metadata for validation. Empty enum arrays map to null (unrestricted), and Infinity removes a length limit. Disabled rules contribute no override. Explicit .gsmartrc.json values replace mapped rules, including their severity metadata.

Imported values must also fit the schema's bounds (for example, up to 100 enum entries with 100 characters per name). Other rules, inverted enum/length rules, and object-form scope-enum values are not translated. Their active rule names appear in config --show-effective diagnostics and --debug logs. Custom parser formats, plugin behavior, and commitlint ignore predicates do not change GSmart's Conventional Commit format. Invalid config or missing presets produce an actionable load error.

Output language and history examples

# Language override for a single run
gsmart --language es
gsmart --language pt-BR

# Use five recent subjects as style examples
gsmart --history-examples 5

# Disable examples even when the repository enables them
gsmart --history-examples 0

Language changes generated commit prose, while CLI help and documentation remain in their existing language.

History is opt-in. When enabled, GSmart reads recent non-merge commit subjects reachable from HEAD, bounded to 20 subjects, 200 characters each, and 4,000 subject characters total. It excludes bodies, labels the subjects as style examples, and sends them to the selected provider alongside the diff. Explicit conventions override historical style. A repository without commits contributes no examples, and disabling history skips the history read entirely.

Message validation

Generated, edited, refined, and restored candidates use the same offline validator before they can be committed. It checks:

  • Nonempty Conventional Commit headers, optional scopes, and ! breaking markers.
  • Recognizable output wrappers at the start of the output (quotes, JSON, Markdown fences around the whole message, and common model preambles before the header) and control characters.
  • Effective allowed types/scopes, scope presence, header/description lengths, body presence and line lengths, and body/footer blank-line rules.
  • Configured ticket references and breaking-change footer requirements. Both BREAKING CHANGE: and BREAKING-CHANGE: are supported, including multiline values and adjacent trailers.

Schema-valid punctuation in an explicitly configured type (for example, [bot], <release>, or **meta) is accepted when the parsed header type matches exactly. This exception does not apply to types: null or to wrappers around a configured header; all other validation rules still apply.

Multiline bodies and Markdown code examples inside bodies are supported. After a valid header, body and footer prose such as “The commit message uses the configured format.” or “Let me know if…” is treated as message content, not rejected as a wrapper; it still must satisfy the configured body/footer rules. CRLF/CR line endings become LF and terminal newlines are removed consistently; meaningful whitespace and content are retained. GSmart passes --cleanup=verbatim to Git so cleanup settings cannot strip a validated body or Markdown hard breaks; Git hooks still run. Length limits count JavaScript UTF-16 units, matching commitlint.

Footer parsing recognizes unindented Token: value or Token #reference lines outside fenced code at section boundaries. Generic colon-prefixed prose within a body paragraph stays in the body. Recognizable reference, breaking-change, and sign-off/review trailers are checked even when their required blank separator is missing. With footer.leadingBlank: false, trailers may follow body text directly. Subsequent lines continue a footer until another trailer starts. Trailer values must contain non-whitespace content, which can begin on a continuation line. A footer does not satisfy a required body, and breaking markers require the colon-space separator. Bare BREAKING CHANGE/BREAKING-CHANGE tokens and incorrectly spaced colons are invalid markers. Ordinary prose such as BREAKING CHANGE handling is documented below. remains body text or a footer continuation: it does not satisfy a required breaking footer and remains subject to the rules for its section.

Ticket recognition covers configured literal prefixes followed by digits (for example, "APP-" recognizes APP-42) and common #42 references. Bare uppercase PROJ-42 shapes are recognized in reference footers, or in an explicitly required subject/body ticket section when prefixes are unrestricted. This avoids treating ordinary prose such as UTF-8 or SHA-256 as tickets by default. Recognized tickets must use an allowed prefix when configured, the configured placement, and the configured footer label. Ticket IDs inside backtick- or tilde-fenced examples, including fence info strings and footer continuations, are ignored: they neither satisfy required tickets nor trigger ticket-rule errors. References after a closing fence are checked normally; an unclosed fence keeps the remaining lines excluded from ticket checks. Fenced body examples still count toward body presence and line-length rules. For other ticket formats, configure their literal prefix. Validation cannot prove an ID was supplied by the diff or branch, detect an unmarked breaking change, or determine semantic accuracy, language quality, or arbitrary free-text instructions. Review those against the diff; the evaluation guide provides a repeatable rubric. Syntactically valid prose is not proof of a faithful message.

Rule precedence matches generation. Imported commitlint severity 1 produces a visible warning; severity 2, built-in syntax failures, and explicit repository rules block committing. An explicit setting replaces the imported rule's severity. Unsupported commitlint rules remain covered by the compatibility contract, rather than being silently treated as enforced.

In interactive review, invalid drafts stay available for Edit message, Regenerate with feedback, and candidate history. Commit is disabled until the candidate passes. For example:

Candidate #1 (generated):
Added accounts
Invalid commit message:
error [header] line 1: Use <type>[optional scope][!]: <description>, for example: feat(api): add pagination.
Edit the message or regenerate with feedback before committing. ...
? What would you like to do? › Edit message

Candidate #2 (edited):
feat(accounts): add account creation
? What would you like to do? › Commit
✔ Changes committed successfully

Automation never silently accepts invalid output: --yes exits 1 without committing; --dry-run labels the invalid preview and exits 1; machine message output leaves stdout empty, while JSON output returns ok: false with error.code: "VALIDATION". Invalid candidates in a non-TTY session exit without a recovery prompt. Correct the message interactively or adjust the instructions/conventions and rerun. Validation does not undo files already staged by an explicitly requested staging operation.

Large diffs and AI context

GSmart budgets the complete request: system instructions, branch, changes, custom instructions, history examples, refinement feedback, an output reserve, and request overhead. Small diffs that fit keep their full content and use one generation request.

Oversized diffs are reduced locally by default. Each included file keeps its path, change type, line counts, rename origin, and relevant mode/binary metadata. Small patches stay intact where possible; larger patches receive representative excerpts. Lockfiles and generated files receive at most 1 KiB of excerpts so they cannot dominate source changes. Excerpts are incomplete evidence, and the prompt tells the model not to infer unseen details. Lockfile-only, binary, rename-only, and deletion changes remain usable context.

AI summarization is opt-in. --summarize allows extra requests for oversized source files. Each chunk request is independently budgeted and uses the selected model, authentication, timeout, cancellation, and retry policy. Summaries are composed within the final budget. The default limit is eight summary attempts including retries, in addition to final-generation attempts. If a file requires more chunks than its share of the limit, chunks are sampled across the file and its report marks the summary as partial. Large combined summaries can also be shortened for the final request. Lockfiles and generated files continue to use local compaction.

# Generate and inspect per-file context treatment without committing
gsmart --dry-run --show-context

# Set a total request budget and exclude paths from AI context
gsmart --dry-run --context-budget 16384 --context-exclude 'vendor/**' '*.map'

# Allow additional AI calls for this run
gsmart --dry-run --summarize --show-context

# Override repository opt-in; only local reduction is used
gsmart --dry-run --no-summarize

# Inspect configuration overrides and their sources
gsmart config --show-effective --context-budget 16384 --no-summarize

--show-context prints a JSON report with the resolved budget and its source, input estimate, output/overhead reserves, summary-attempt count, and each file's treatment (full, condensed, summarized, or excluded), reason, byte sizes, and partial-coverage flag. A brief notice appears whenever files are reduced or excluded. This report describes the final context; it does not print source contents. --dry-run still makes the final AI request and any opted-in summary requests.

Add a context section to the root .gsmartrc.json to share settings:

{
  "context": {
    "budgetTokens": 16384,
    "outputTokens": 1024,
    "summarize": false,
    "maxSummaryRequests": 8,
    "exclude": ["vendor/**"],
    "generated": [
      "**/*.min.js",
      "**/*.min.css",
      "**/*.map",
      "**/*.generated.*",
      "**/generated/**",
      "**/dist/**"
    ]
  }
}

| Setting | Default and behavior | | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | budgetTokens | null: resolve from the selected provider/model. An explicit integer from 1,024 to 1,048,576 overrides it; it must leave room for instructions and exceed output plus overhead. Known model windows are upper bounds. | | outputTokens | 1024: reserved output tokens, also passed to the provider as its output limit; configurable from 256 to 32,768. Increase it if a model exhausts its output/reasoning allowance. | | summarize | false: use local reduction only. true permits additional AI calls when needed. | | maxSummaryRequests | 8: maximum summary attempts per generation/refinement, including retries; range 1–64. | | exclude | []: omit matching files entirely from AI context, including summary requests. For renames/copies, both original and destination paths are checked. | | generated | The six patterns shown above. Recognized generated-code markers also trigger compaction. Setting [] disables pattern matching, but retains marker and lockfile detection. |

Patterns match complete repository-relative paths using / separators: * matches within a component, ** crosses directories, **/ also matches the root, and ? matches one non-separator character. Other characters are literal; negation, brace expansion, and character classes are not supported. Quote CLI patterns to prevent shell expansion. Arrays replace inherited values. CLI context settings override their corresponding repository fields; config accepts these flags with --show-effective for inspection.

Model budgets and conservative accounting

Known exact provider/model pairs use a default total budget of 32,768, below their advertised windows:

| Provider | Model | Known window | | --------- | ------------------------------------ | ------------ | | OpenAI | gpt-4o, gpt-4o-mini | 128,000 | | OpenAI | gpt-5-codex | 400,000 | | Anthropic | claude-haiku-4-5-20251001 | 200,000 | | Google | gemini-2.5-flash, gemini-2.5-pro | 1,048,576 |

All other IDs, including unlisted built-in defaults and every custom endpoint, use an 8,192 total fallback unless overridden. A local server may configure a smaller window than the model supports; set --context-budget to that effective limit.

With an automatic budget, an output reserve plus framing overhead that reaches or exceeds the 32,768-token automatic cap is rejected while loading configuration, before file selection or auto-staging. Larger output reserves require an explicit larger budgetTokens. Model-specific limits are checked after model selection; valid model-dependent settings retain budgetTokens: null in the effective configuration.

GSmart conservatively counts one token per UTF-8 byte of request text, plus 512 tokens for request framing, then reserves outputTokens. This intentionally overestimates typical token usage instead of assuming four characters per token. The report is an accounting estimate, not provider billing. Custom tokenizers or server-added templates can differ; account for their overhead with a smaller configured budget.

Context exclusions and reduction never unstage files or change working-tree contents. All selected changes still belong to the commit; only their AI representation changes. Existing staging and dry-run selection rules still apply. Git capture supports complete diffs up to 64 MiB and returns an explicit error above that limit or on read failure.

If even the file metadata cannot fit, GSmart shows the current budget and the minimum total needed, including instructions/history, output reserve, and request overhead. In an interactive terminal, it offers to increase the budget for the current session and retry the captured changes. Accepting keeps that budget for subsequent candidates without saving it to configuration. With --yes or noninteractive input/output, GSmart exits with a concrete --context-budget <number> recommendation to use with the same command.

Recommendations respect known model windows and GSmart's maximum budget. If the minimum exceeds those limits, reduce context instead: use --history-examples 0, shorten instructions/feedback, add --context-exclude 'path/to/exclude/**', or stage fewer files. For unknown models and custom endpoints, check the model/server's actual capacity before accepting an increase. The minimum budget fits metadata; additional room allows more diff excerpts. --summarize cannot fix metadata overflow.

If all usable context is excluded, instructions cannot fit, or an attempted summary is empty, fails, or exhausts retries, generation stops with a clear error. Increase the relevant limit, shorten instructions/history/feedback, adjust exclusions, or use --no-summarize to retry with local reduction. GSmart does not silently continue after a failed summary.

Environment variables

| Variable | Purpose | Default | | ------------------- | ---------------------------------------------- | ----------------------------------------- | | GSMART_TIMEOUT | Timeout per AI generation attempt, in ms | 30000 (30 seconds) | | GSMART_CONFIG_DIR | Directory for GSmart's local configuration | Your OS's user configuration location | | VISUAL | Preferred editor command for message editing | Unset | | EDITOR | Editor command when VISUAL is unset or blank | vi on macOS/Linux; notepad on Windows |

For example, allow up to 60 seconds per generation attempt in Bash or Zsh:

GSMART_TIMEOUT=60000 gsmart

Invalid or nonpositive timeout values fall back to 30 seconds. GSmart retries transient failures, including network errors, rate limits, and server errors, so a complete run can take longer than one timeout period.

ChatGPT streaming responses must complete successfully before becoming commit candidates. Timeouts and interrupted connections discard partial text before retrying. Explicit cancellation stops retries; responses cut short by output limits or content filtering return an error.

GSmart stores API keys, ChatGPT login tokens, provider/model preferences, the custom endpoint, and your default prompt in a local, user-level configuration file managed by conf. These settings are shared across repositories when you use the same configuration directory. Provider preferences and endpoint credentials are not read from .gsmartrc.json.

To keep a separate configuration, set GSMART_CONFIG_DIR consistently for login and generation. For example, in Bash or Zsh:

export GSMART_CONFIG_DIR="$HOME/.config/gsmart-work"
gsmart login
gsmart

To clear the active configuration:

gsmart reset

This asks for confirmation, then clears all settings in that configuration store, including provider credentials, ChatGPT login tokens, provider/model defaults, the custom endpoint, and the saved prompt. gsmart reset --force skips the confirmation. Resetting clears local settings; credential revocation is managed through your provider.

Providers

Run gsmart login to configure any of these providers:

| Provider | --provider value | Authentication | | -------------- | ------------------ | --------------------------------------------------------------------------------------- | | OpenAI | openai | ChatGPT subscription login or API key | | Anthropic | anthropic | API key | | Google Gemini | google | API key | | Mistral | mistral | API key | | Fireworks AI | fireworks | API key | | PlataformIA | plataformia | API key | | Custom / local | custom | Optional bearer token; configure URL and model |

An explicit --provider takes precedence over your saved default. Without either, GSmart selects a single configured provider automatically or offers a chooser when several exist. --yes uses the first configured entry in the order above when no explicit or saved choice exists.

Using ChatGPT? Choose OpenAI → ChatGPT subscription during login. GSmart prints an authorization URL and attempts to open it in your browser. Complete authorization on the machine running the CLI so the local callback can finish. Tokens refresh automatically; if the login expires, run gsmart login again.

ChatGPT login uses the Codex Responses endpoint with streaming and storage disabled. Its model access differs from the public OpenAI API. Saved OpenAI models and --model overrides must be supported by the active authentication mode; use API-key login for API-only models. Fireworks and PlataformIA use Chat Completions, while OpenAI API-key requests use Responses.

When neither --model nor a saved model is set, the built-in fallbacks are:

| Provider | Model ID | | -------------------- | ------------------------------------------------------- | | OpenAI API key | gpt-5.6-luna | | OpenAI ChatGPT OAuth | gpt-5-codex | | Anthropic | claude-haiku-4-5-20251001 | | Google | gemini-3.5-flash-lite | | Mistral | mistral-large-latest | | Fireworks AI | accounts/fireworks/models/deepseek-v4-flash | | PlataformIA | radiance | | Custom / local | No fallback; configure a model available on your server |

Use gsmart config --provider <provider> --model <model> to save another model, or --model <model> for one run. gsmart config --show identifies saved and built-in models. Availability depends on the provider account, authentication mode, and API operation. Consult your provider's model catalog; an unsupported model produces guidance for selecting another model.

Command reference

Run gsmart to generate a commit message. gsmart --help shows generation options and the available subcommands.

| Command | Purpose | | ---------------------------- | ------------------------------------------------------------- | | gsmart | Generate a message and choose what to do with it | | gsmart plan --staged | Suggest coherent commits for the existing staged diff | | gsmart login | Configure a provider's authentication | | gsmart config | Manage prompts, provider/model defaults, and custom endpoints | | gsmart reset | Clear the active local configuration after confirmation | | gsmart completions <shell> | Print a completion script for bash, zsh, or fish | | gsmart help [command] | Show help for a command |

Generation options — use directly with gsmart:

| Option | Short | Purpose | | --------------------------------- | ----- | --------------------------------------------------------------------- | | --provider <provider> | -P | Choose an already-configured provider | | --model <model> | | Override the selected provider's saved or built-in model for this run | | --prompt <prompt> | -p | Supply cust