feat: add gitlance init and suggest commands - #16
Draft
panasheMuriro wants to merge 12 commits into
Draft
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Done (dependant on #14 and #15 )
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 separatelogout.gitlance suggest [--commit], which resolves the API key fromOPENROUTER_API_KEYor 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 intogit commit -F -with--commitso local hooks still run normally.