Skip to content

feat: add gitlance init and suggest commands - #16

Draft
panasheMuriro wants to merge 12 commits into
canonical:mainfrom
panasheMuriro:feat/suggest-command
Draft

feat: add gitlance init and suggest commands#16
panasheMuriro wants to merge 12 commits into
canonical:mainfrom
panasheMuriro:feat/suggest-command

Conversation

@panasheMuriro

Copy link
Copy Markdown
Collaborator

Done (dependant on #14 and #15 )

  • Adds gitlance init, which prompts for an OpenRouter API key (hidden input) and stores it via the credential store, overwriting any existing key rather than erroring — there's no login/session concept, just key storage, so there's no separate logout.
  • Adds gitlance suggest [--commit], which resolves the API key from OPENROUTER_API_KEY or the stored credential (never a CLI flag, to avoid leaking secrets via shell history/process args), reads the model from gitlance.toml, generates and validates a commit message against the staged diff, and either prints it or pipes it into git commit -F - with --commit so local hooks still run normally.

gitlance suggest needs to read the currently staged changes (not a commit
range) and the configured git identity, to build an LLM prompt and append
a Signed-off-by trailer. Uses git2 (diff_tree_to_index) for consistency
with the rest of git.rs rather than shelling out to git.

Signed-off-by: Panashe Muriro <panashemuriro2021@gmail.com>
Covers get_staged_diff (nothing staged, staged content present, unborn HEAD) and get_git_identity.

Signed-off-by: Panashe Muriro <panashemuriro2021@gmail.com>
Needed for the credential-store module: keyring for OS-native secret
storage.

Signed-off-by: Panashe Muriro <panashemuriro2021@gmail.com>
Introduces the CredentialStore abstraction (get_name/read_token/write_token/delete_token) and its error type, ahead of adding concrete keyring- and file-backed implementations.

Signed-off-by: Panashe Muriro <panashemuriro2021@gmail.com>
KeyringCredentialStore is the primary store, using the OS-native credential manager (Secret Service/Keychain/Credential Manager) via the keyring crate. Not covered by automated tests since it requires a real OS keyring session.

Signed-off-by: Panashe Muriro <panashemuriro2021@gmail.com>
FileCredentialStore stores the token at $XDG_RUNTIME_DIR/gitlance/application_token with 0600 permissions on Unix, for headless environments without a usable OS keyring session.

Signed-off-by: Panashe Muriro <panashemuriro2021@gmail.com>
CredentialStoreFactory::create_store() tries the keyring store first and falls back to the file store if the keyring is unavailable, returning a Box<dyn CredentialStore> so callers don't need to know which backend is in use.

Signed-off-by: Panashe Muriro <panashemuriro2021@gmail.com>
gitlance suggest needs to know which LLM model to use without requiring
a CLI flag every invocation (keeping the command surface minimal and
config out of shell history). Reads a .gitlance.toml file from the
repository root and falls back to a built-in default model when the
file or the model key is absent.

Signed-off-by: Panashe Muriro <panashemuriro2021@gmail.com>
Introduces the core of 'gitlance suggest': an LlmProvider trait with an
OpenRouter implementation, a prompt builder that encodes the exact rules
enforced by the conventional/wip-fixup/signed-off-by checks, and a
validate_candidate helper that runs a generated message through those
same check_commits() functions. suggest_commit_message() retries with
the specific failure reasons fed back to the model (up to 3 attempts),
so a message is never returned unless it would actually pass gitlance
itself. The provider is behind a trait so other backends/models can be
added later without touching CLI or validation code.

Signed-off-by: Panashe Muriro <panashemuriro2021@gmail.com>
Ties the credential store into a new 'init' subcommand: prompts for an OpenRouter API key (hidden input) and stores it, overwriting any existing key rather than erroring - there is no login/session concept here, just key storage, so there is no separate logout command.

Signed-off-by: Panashe Muriro <panashemuriro2021@gmail.com>
Adds the 'suggest' subcommand: resolves the API key from OPENROUTER_API_KEY or the stored credential (never a CLI flag, to avoid leaking secrets via shell history/process args), reads the model only from .gitlance.toml, generates and validates a commit message against the staged diff, and either prints it or pipes it into 'git commit -F -' with --commit so local hooks still run normally.

Signed-off-by: Panashe Muriro <panashemuriro2021@gmail.com>
Covers the two error paths for 'gitlance suggest' that don't require a
real OpenRouter API call: no staged changes, and no API key resolvable
from any source (env var or credential store). The credential-store
fallback is isolated per-test via a temp XDG_RUNTIME_DIR so a real
developer-machine key doesn't leak into the assertions.

Signed-off-by: Panashe Muriro <panashemuriro2021@gmail.com>
@panasheMuriro panasheMuriro self-assigned this Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant