An open API service indexing awesome lists of open source software.

https://github.com/jimmy-guzman/gitzy

🪄 An interactive conventional commits cli
https://github.com/jimmy-guzman/gitzy

cli conventional-commits

Last synced: about 2 months ago
JSON representation

🪄 An interactive conventional commits cli

Awesome Lists containing this project

README

          

# gitzy 🪄

> Interactive [conventional commits][conventional-commits] CLI with branch name generation and commitlint integration.


Gitzy CLI screenshot

Recorded with termsvg (glyphs look better IRL)

![actions][actions-badge]
[![version][version-badge]][package]
[![downloads][downloads-badge]][npmtrends]
[![Install Size][install-size-badge]][packagephobia]
[![License][license-badge]][license]
[![Code Coverage][coverage-badge]][coverage]

## Table of Contents

- [Features](#features)
- [Usage](#usage)
- [Subcommands](#subcommands)
- [Configuration](#configuration)
- [Config Options](#config-options)

## Features

- Interactive conventional commit flow (`type`, `scope`, `subject`, `body`, `breaking`, `issues`)
- Branch name generation from conventional commit prompts
- Partial commitlint configuration support
- Config validation via schema
- Multiple breaking-change formats (`!`, `footer`, `both`)
- Flexible emoji control (`emoji.enabled` config or `GITZY_NO_EMOJI` env var)
- Customizable type descriptions and emojis
- Dynamic scopes and types (string shorthand or full `{ name, description }` objects)
- Jira and GitHub issue reference patterns
- Co-author support via `--co-author`
- Retry (`--retry`), dry-run (`--dry-run`), amend (`--amend`), and hook (`--hook`) modes
- JSON output (`--json`) for scripting and CI
- `--no-emoji` flag (precedence: `--no-emoji` > `GITZY_NO_EMOJI` env > `emoji.enabled` config)
- `--stdin` for piping answers as JSON (both `commit` and `branch`)
- ⚡ [Lightweight (~170 kB install)][packagephobia]

## Usage

```sh-session
npx gitzy
# or
npm install -g gitzy
gitzy
gitzy commit --type feat -m "add dark mode"
gitzy branch --type feat -m "add dark mode" --scope ui
```

## Subcommands

`gitzy` is the same as `gitzy commit`. Explicit subcommands:

| Subcommand | Description |
| -------------- | ------------------------------------------------------------------------------ |
| `gitzy` | Alias for `gitzy commit` |
| `gitzy commit` | Interactive conventional commit flow (default) |
| `gitzy branch` | Generate a branch name from a conventional commit prompt |
| `gitzy init` | Generate a starter `.gitzyrc.json` in the current dir (`--force` to overwrite) |
| `gitzy config` | Display the resolved config as JSON |

### `gitzy commit` flags

| Flag | Alias | Description |
| --------------------------- | ----- | --------------------------------------------------------------- |
| `--type ` | | set type inline (with `--subject`, skips all prompts) |
| `--scope ` | | set scope inline |
| `--subject ` | `-m` | set subject inline (with `--type`, skips all prompts) |
| `--body ` | | set body inline |
| `--breaking [breaking]` | | mark as breaking; add message for `footer`/`both` formats |
| `--issue ` | | set issues inline (repeatable: `--issue '#123' --issue '#456'`) |
| `--dry-run` | `-D` | show commit message without committing |
| `--retry` | | retry last commit and skip prompts |
| `--amend` | `-a` | amend the previous commit (pre-fills prompts from HEAD) |
| `--no-verify` | `-n` | skip git hooks |
| `--json` | | output structured JSON (see shape below) |
| `--no-emoji` | | disable emoji in commit message |
| `--co-author ` | | add co-authors (repeatable: `--co-author "Name "`) |
| `--hook` | | enable running inside a git hook (e.g. `pre-commit`) |
| `--stdin` | | read answers from stdin as JSON (CLI flags take priority) |
| `--version` | `-v` | display version number |
| `--help` | `-h` | display help for command |

#### `commit --json` output shape

```json
{
"header": "feat: ✨ add dark mode",
"body": "",
"footer": "",
"message": "feat: ✨ add dark mode",
"parts": {
"type": "feat",
"scope": "",
"subject": "add dark mode",
"body": "",
"breaking": "",
"issues": [],
"coAuthors": []
}
}
```

### `gitzy branch` flags

| Flag | Alias | Description |
| --------------------- | ----- | --------------------------------------------------------- |
| `--type ` | | set type inline (with `--subject`, skips all prompts) |
| `--scope ` | | set scope inline |
| `--subject ` | `-m` | set subject inline (with `--type`, skips all prompts) |
| `--issue ` | | set issue reference inline (e.g. `#42` or `PROJ-123`) |
| `--from ` | | create the branch from a base branch |
| `--amend` | `-a` | rename the current branch instead of creating a new one |
| `--no-checkout` | | do not checkout the new branch after creating it |
| `--dry-run` | `-D` | show branch name without creating it |
| `--json` | | output result as JSON (see shape below) |
| `--stdin` | | read answers from stdin as JSON (CLI flags take priority) |
| `--help` | `-h` | display help for command |

#### `branch --json` output shape

```json
{ "branchName": "feat/add-dark-mode", "dryRun": false }
```

When used with `--amend`, also includes the previous branch name:

```json
{
"branchName": "feat/add-dark-mode",
"dryRun": false,
"oldName": "feat/dark-mode"
}
```

## Configuration

By default, `gitzy` works out of the box. You can configure it via a `gitzy` key in `package.json`, or one of the following files:

`.gitzyrc`, `.gitzyrc.json`, `.gitzyrc.js`, `.gitzyrc.cjs`, `.gitzyrc.mjs`,
`gitzy.config.js`, `gitzy.config.cjs`, `gitzy.config.mjs`, `gitzy.config.ts`, `gitzy.config.mts`

> [!NOTE]
> All of these files can also live under a `.config/` directory. TypeScript config files (`.ts`/`.mts`) require Node >=22.12.0 (built-in TypeScript stripping, no flag needed). Use a `.js`, `.cjs`, or `.mjs` config file if you are on an older Node version.

Use `defineConfig` for editor autocomplete:

```js
// gitzy.config.js
import { defineConfig } from "gitzy";

export default defineConfig({
// see options below
});
```

Use `gitzy config` to see all available config file locations and the resolved config.

## Config Options

### `types`

List of commit types. Accepts strings (looked up from builtins) or full objects.

```js
types: ["feat", "fix", "chore", "docs", "refactor", "test", "style", "ci"];
// or with custom descriptions/emojis:
types: [
{ name: "feat", description: "A new feature", emoji: "✨" },
{ name: "fix", description: "Fix a bug", emoji: "🐛" },
];
```

**Built-in types:** `chore`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `release`, `revert`, `style`, `test`

### `scopes`

List of scopes to choose from. Enables the `scope` prompt when non-empty.

```js
scopes: ["api", "ui", "cli"];
// or with descriptions:
scopes: [{ name: "api", description: "Public API surface" }, { name: "ui" }];
```

### `prompts`

Controls which prompts are shown and in what order.

```js
// Default:
prompts: ["type", "scope", "subject", "body", "breaking", "issues"];

// All available prompts (add "coAuthors" to enable co-author prompt):
prompts: [
"type",
"scope",
"subject",
"body",
"breaking",
"issues",
"coAuthors",
];
```

### `header`

Controls the commit header length validation.

```js
header: {
max: 50, // default
min: 5, // default
}
```

### `body`

Controls the commit body length validation. The body prompt is optional — press **Enter** twice (submit an empty line) to skip it.

```js
body: {
max: 70, // default
min: 5, // default
}
```

### `breaking`

Controls the breaking change prompt behavior.

- `"!"` — append `!` to the type/scope, ask yes/no
- `"footer"` — prompt for a description, add a `BREAKING CHANGE` footer (default)
- `"both"` — add both `!` and a footer

```js
breaking: {
format: "footer", // "!", "footer", or "both"
}
```

#### Examples

```sh
# "!" format
feat!: send an email to the customer when a product is shipped

# "footer" format
feat: allow provided config object to extend other configs

BREAKING CHANGE: `extends` key in config file is now used for extending other config files

# "both" format
chore!: drop support for Node 6

BREAKING CHANGE: use JavaScript features not available in Node 6.
```

### `emoji`

Controls emoji rendering.

```js
emoji: {
enabled: true, // default; set to false or use GITZY_NO_EMOJI env var to disable
breaking: "💥", // emoji prepended to breaking change footer
issues: "🏁", // emoji prepended to issue references
}
```

> [!NOTE]
> Set the `GITZY_NO_EMOJI` environment variable or pass `--no-emoji` to disable all emojis. Precedence: `--no-emoji` flag > `GITZY_NO_EMOJI` env > `emoji.enabled` config.

### `issues`

Controls the issues prompt behavior.

```js
issues: {
pattern: "github", // "github" (default) or "jira"
prefix: "closes", // "close" | "closes" | "closed" | "fix" | "fixes" | "fixed" | "resolve" | "resolves" | "resolved"
hint: "#123, #456, resolves #789, org/repo#100",
}
```

> [!TIP]
> Specify multiple issues separated by commas: `#123, #456`, or with keywords: `resolves #123, fixes #456`, or cross-repo: `org/repo#123`. Use `pattern: "jira"` for Jira-style keys like `PROJ-123`.

### `branch`

Controls branch name generation.

```js
branch: {
pattern: "{type}/{scope}/{issue}-{subject}", // default
separator: "/", // separator used within each slugified segment (type, scope, subject)
max: 72, // max branch name length
checkout: true, // auto-checkout after creation
}
```

**Pattern tokens:** `{type}`, `{scope}`, `{issue}`, `{subject}` — any token that has no value is omitted along with its surrounding separators.

#### Branch name examples

| type | scope | issue | subject | output |
| ------- | ------ | -------- | ----------------- | ---------------------------- |
| `feat` | `ui` | | `add dark mode` | `feat/ui/add/dark/mode` |
| `fix` | | `#42` | `login crash` | `fix/#42-login/crash` |
| `chore` | `deps` | | `bump typescript` | `chore/deps/bump/typescript` |
| `feat` | | `PROJ-1` | `new dashboard` | `feat/PROJ-1-new/dashboard` |

### commitlint integration

gitzy always auto-detects a local commitlint config file and merges its rules as a base. Any values set in your gitzy config take priority. Use `gitzy config` to inspect the resolved configuration.

## Credits

- [git-cz](https://github.com/streamich/git-cz) by [streamich](https://github.com/streamich)

[actions-badge]: https://img.shields.io/github/actions/workflow/status/jimmy-guzman/gitzy/release.yml?branch=main&style=flat-square&logo=github
[version-badge]: https://img.shields.io/npm/v/gitzy?style=flat-square&logo=npm
[package]: https://npmx.dev/package/gitzy
[downloads-badge]: https://img.shields.io/npm/dm/gitzy?style=flat-square&logo=npm
[npmtrends]: https://www.npmtrends.com/gitzy
[license]: https://github.com/jimmy-guzman/gitzy/blob/master/LICENSE
[license-badge]: https://img.shields.io/github/license/jimmy-guzman/gitzy?style=flat-square&logo=open-source-initiative
[conventional-commits]: https://www.conventionalcommits.org/
[coverage-badge]: https://img.shields.io/codecov/c/github/jimmy-guzman/gitzy?style=flat-square&logo=codecov
[coverage]: https://codecov.io/github/jimmy-guzman/gitzy
[packagephobia]: https://packagephobia.com/result?p=gitzy
[install-size-badge]: https://img.shields.io/badge/dynamic/json?url=https://packagephobia.com/v2/api.json%3Fp=gitzy&query=$.install.pretty&label=install%20size&style=flat-square&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDggMTA4Ij48ZGVmcz48bGluZWFyR3JhZGllbnQgaWQ9ImEiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iIzAwNjgzOCIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzMyZGU4NSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxwYXRoIGZpbGw9InVybCgjYSkiIGQ9Ik0yMS42NjcgNzMuODA5VjMzLjg2N2wyOC4zMy0xNi4xODggMjguMzM3IDE2LjE4OFY2Ni4xM0w0OS45OTcgODIuMzIxIDM1IDczLjc1VjQxLjYwNGwxNC45OTctOC41N0w2NSA0MS42MDR2MTYuNzg4bC0xNS4wMDMgOC41NzEtMS42NjMtLjk1di0xNi42NzJsOC4zODItNC43OTItNi43MTktMy44MzgtOC4zMyA0Ljc2M1Y2OS44OGw4LjMzIDQuNzYyIDIxLjY3LTEyLjM4M1YzNy43MzdsLTIxLjY3LTEyLjM3OS0yMS42NjMgMTIuMzc5djM5Ljg4TDQ5Ljk5NyA5MCA4NSA3MFYzMEw0OS45OTcgMTAgMTUgMzB2NDB6Ii8+PC9zdmc+