Compose Conventional Commit messages from a persistent panel — pick a type, scope and subject in any order, see the message as you build it, and commit. It lives wherever suits you: its own sidebar, a section in the Source Control view, or a full editor tab. All three are the same draft, so a change in one shows up in the others.
Existing extensions give you a one-shot modal wizard: pick the wrong type on step one and you start over, and nothing shows you the message you are assembling. This one keeps every field on screen and editable, with a live preview of exactly what will be committed.
Type grid. Every commit type as a card, with an icon and a one-line description. The last card is a text field — type your own if the list doesn't cover it.
Branch-aware scope. On feature/PROJ-123-add-login the panel fills in PROJ-123 for you. Switch
branches and it follows; pick a scope yourself and it stays put.
The current branch is always offered as a chip, whatever it is. What
conventionalCommitPanel.scope.ignoreBranches controls is only whether it gets filled in
automatically — on main or develop the branch name isn't an area of the codebase, and
feat(main): … would be noise that lives in your history forever. So it's one click away rather
than pre-filled. Set that list to [] if you'd rather it always fill in.
Chips also come from your repository config and from scopes you have committed with before. Typing in the field never adds a suggestion — only an actual commit does. Conventional Commit: Clear Recent Scope Suggestions empties the list.
Live validation. A character counter and fill meter against the header limit, with the specific rule you're breaking named underneath. When your repo has commitlint, the rules being checked are the ones parsed from its config.
Live preview. The rendered message with syntax colouring, so there are no surprises in
git log.
Breaking changes. A toggle that adds the ! marker and the BREAKING CHANGE: footer, showing
the resulting release impact — patch, minor or major.
Reads your existing config. Types and scopes come from .cz-config.js, .czrc,
package.json#config.commitizen or a commitlint config, falling back to the standard Conventional
Commits list when there's nothing to read. It parses those files directly — nothing needs to be
installed, and it doesn't shell out to the commitizen or commitlint CLIs.
Guided wizard. Prefer a linear flow? The toolbar button walks the same fields step by step, with a back button. It shares one draft with the panel, so you can switch between them freely.
Three places to work. The panel has its own icon in the Activity Bar, where it is the only view and so gets the whole sidebar height with nothing to resize. It is also a section in the Source Control view, for working right above the Changes list. And Open Composer in Editor puts the same composer in a full editor tab when you want the width. All three share one draft — edit in any and the others follow.
Staging. A Stage all action sits next to the staged count whenever something is unstaged, so staging is one click and does not have to be bundled with committing. It stages exactly the files that count names, new files included, and asks first if any of them have merge conflicts.
Syncing and publishing. The Commit button changes into the branch action when there is nothing
staged, exactly as VS Code's Source Control button does. Sync Changes appears with its
ahead/behind counts once the branch has drifted from its upstream, and hands off to the built-in
git.sync, so git.rebaseWhenSync and git.confirmSync apply and conflicts surface exactly as they
do there. Publish Branch appears when the branch has never been pushed; pushing one with no
upstream also offers to publish it rather than failing with fatal: The current branch has no upstream branch. Publishing uses origin when there is one and asks when there are several, and
nothing reaches a remote until you press the button. Commit keeps the slot whenever anything is
staged, and Cmd/Ctrl Enter only ever commits.
The behind count is only as fresh as the last fetch, so with git.autofetch off it can read zero
while the remote has moved. The ahead count needs no network and is always right, which is what makes
the button appear as soon as you commit.
Reformatting the body. Text pasted from somewhere else usually arrives with line breaks in the
middle of sentences. reformat on the Body field — shown only when there is something to rejoin —
pulls them back into paragraphs and re-wraps at bodyLineLength, so the field ends up showing
exactly what will be committed. Blank lines, list items, block quotes, tables and fenced code are
left as they are, and pressing it twice does nothing the second time.
Your draft survives a window reload, and the panel never overwrites text you typed into the Source Control box by hand.
| Setting | Default | Description |
|---|---|---|
conventionalCommitPanel.liveSync |
true |
Mirror the draft into the commit box as you edit. |
conventionalCommitPanel.headerMaxLength |
100 |
Header limit, matching commitlint's default. Set 72 for the stricter git convention. A commitlint header-max-length rule wins over this. |
conventionalCommitPanel.bodyLineLength |
72 |
Wrap column for the body. 0 disables wrapping. |
conventionalCommitPanel.useEmoji |
false |
Prefix the subject with the type's emoji. |
conventionalCommitPanel.types |
[] |
Custom type list. Empty means repo config, then the built-in list. |
conventionalCommitPanel.defaultType |
feat |
Type pre-selected on a fresh draft. Empty string selects nothing. |
conventionalCommitPanel.scope.ticketPattern |
([A-Z][A-Z0-9]+-\d+) |
Pulls a ticket ID out of the branch name. |
conventionalCommitPanel.scope.branchPrefixes |
feature, feat, fix, … |
Prefixes stripped before the segment fallback. |
conventionalCommitPanel.scope.ignoreBranches |
main, master, develop, dev, trunk |
Branches that suggest no scope. |
conventionalCommitPanel.scope.required |
false |
Treat an empty scope as an error. Off by default — the spec makes scope optional. |
conventionalCommitPanel.showBreakingChange |
true |
Show the breaking-change toggle. |
conventionalCommitPanel.showCustomType |
true |
Show the Custom card at the end of the type grid. |
conventionalCommitPanel.config.allowJsConfig |
false |
Allow executing JS configs from the repository. |
conventionalCommitPanel.body.useEditor |
false |
Always edit the body in an editor tab. |
Nothing commits on its own. The Commit button is the only path to a commit.
JavaScript configs are opt-in. .cz-config.js and commitlint.config.js are code, and loading
them means running code from the repository you just opened. That is off unless you enable
conventionalCommitPanel.config.allowJsConfig, is skipped entirely in untrusted workspaces, and
happens in a short-lived child process rather than inside the extension host. JSON and YAML configs
are parsed, never executed, and always read.
No duplicate file list. VS Code's own Changes section sits directly below the panel and already
does that job well.
Bug reports and pull requests are welcome — see CONTRIBUTING.md for how to build, test and release.
