From 5793820a589f9a25d6909cf683cad8a8726fd698 Mon Sep 17 00:00:00 2001
From: prastik
Date: Thu, 25 Dec 2025 10:54:20 +0545
Subject: [PATCH] Added cstm_cmt_msg_rules.md and modified
resources/diffsense.sh.
---
cstm_cmt_msg_rules.md | 46 +++++++++++++++
resources/diffsense.sh | 123 ++++++++++++++++++++++++++++++++++-------
2 files changed, 150 insertions(+), 19 deletions(-)
create mode 100644 cstm_cmt_msg_rules.md
diff --git a/cstm_cmt_msg_rules.md b/cstm_cmt_msg_rules.md
new file mode 100644
index 0000000..7f81def
--- /dev/null
+++ b/cstm_cmt_msg_rules.md
@@ -0,0 +1,46 @@
+# Custom Commit Message Rules
+
+## Format
+- Subject line: imperative verb + what changed (50 chars max)
+- Body: explain WHY, not what (the diff shows what)
+- Use present tense: "Add feature" not "Added feature"
+
+## Structure
+First line: :
+
+Body (if needed):
+- Context: Why was this change necessary?
+- Impact: What does this enable or fix?
+- Notes: Any caveats, side effects, or follow-up needed
+
+## Type Prefixes
+Use one of these tags:
+- feat: New feature or capability
+- fix: Bug fix or correction
+- refactor: Code restructuring without behavior change
+- perf: Performance improvement
+- docs: Documentation only
+- test: Test additions or updates
+- chore: Build, tooling, dependencies
+- style: Formatting, whitespace, naming
+
+## Content Guidelines
+- Be specific: "Fix null pointer in user login" not "Fix bug"
+- Mention affected area: "auth:", "ui:", "api:", etc. when relevant
+- Avoid obvious statements: don't say "update file X" if that's clear from diff
+- Include ticket/issue reference if applicable: "Fixes #123"
+
+## Examples
+Good:
+- feat(auth): Add OAuth2 token refresh logic
+- fix(api): Prevent race condition in cache writes
+- refactor(db): Extract query builder to separate module
+
+Bad:
+- Updated files
+- Changes
+- Fixed stuff
+- WIP
+
+## Output Format
+Plain text only. No markdown formatting (**bold**, `code`, etc.)
\ No newline at end of file
diff --git a/resources/diffsense.sh b/resources/diffsense.sh
index ecac813..8ef57c8 100755
--- a/resources/diffsense.sh
+++ b/resources/diffsense.sh
@@ -149,7 +149,7 @@ set_max_chars_for_model() {
DIFFSENSE_MAX_CHARS=1194000
;;
*)
- DIFFSENSE_MAX_CHARS=10000
+ DIFFSENSE_MAX_CHARS=8000
;;
esac
}
@@ -157,28 +157,32 @@ set_max_chars_for_model() {
# ---------- help ----------
print_help() {
cat <<'EOF'
-Usage: diffsense [MESSAGE STYLE] [AI MODEL] [OPTIONS]
+Usage: diffsense [--byo=] [STYLE] [MODEL] [OPTIONS]
+
+BYO (Bring Your Own Prompt):
+ --byo= Custom prompt file (max 400 chars), relative to current dir.
STYLE:
- default Default style. Works when nothing is specified
- verbose Detailed multi-line commit message
- minimal Single-line, 72-char max subject
+ --default Default style (if nothing specified)
+ --verbose Detailed multi-line commit message
+ --minimal Single-line, 50-char max subject
MODEL:
- afm On-device (LOCAL) model. [DEFAULT MODEL]
- pcc Perplexity (PRIVATE) model
- gpt ChatGPT / OpenAI model
+ --afm On-device (LOCAL) model [DEFAULT]
+ --pcc Perplexity (PRIVATE) model
+ --gpt ChatGPT / OpenAI model
OPTIONS:
--nopopup Disable popup editor in the Shortcut
- -h, --help Show this help message and exit
+ -h, --help Show this help message
Examples:
diffsense
diffsense --verbose
diffsense --verbose --gpt
+ diffsense --byo=.diffsense-prompt --verbose --gpt
+ diffsense --byo=prompts/rules.txt --minimal
diffsense --nopopup
- diffsense --minimal --nopopup
EOF
}
@@ -187,8 +191,15 @@ parse_args() {
local message_style="default"
local ai_model="afm"
local nopopup_suffix=""
+ local byo_path=""
for raw_arg in "$@"; do
+ # Handle --byo=path separately (before stripping --)
+ if [[ "$raw_arg" == --byo=* ]]; then
+ byo_path="${raw_arg#--byo=}"
+ continue
+ fi
+
local arg="${raw_arg#--}"
case "$arg" in
@@ -215,9 +226,11 @@ parse_args() {
gpt) ai_model_internal="CHATGPT" ;;
esac
- echo "$ai_model_internal $message_style $nopopup_suffix"
+ # Use | as delimiter to handle empty fields
+ echo "${ai_model_internal}|${message_style}|${nopopup_suffix}|${byo_path}"
}
+
# ---------- platform ----------
check_platform_and_arch() {
local arch os_major
@@ -268,7 +281,6 @@ check_git_state() {
fi
}
-# ---------- build prompt ----------
# ---------- build prompt ----------
build_prompt() {
case "$1" in
@@ -317,6 +329,67 @@ Constraints:
esac
}
+# ---------- load BYO (bring your own) prompt ----------
+load_byo_prompt() {
+ local path="$1"
+ local max_chars=400
+
+ # No path provided = no BYO
+ if [[ -z "$path" ]]; then
+ return 0
+ fi
+
+ # Trim whitespace/newlines
+ path="${path#"${path%%[![:space:]]*}"}"
+ path="${path%"${path##*[![:space:]]}"}"
+
+ # Resolve path relative to current directory
+ local resolved_path
+ if [[ "$path" == /* ]]; then
+ resolved_path="$path"
+ elif [[ "$path" == ~* ]]; then
+ resolved_path="${path/#\~/$HOME}"
+ else
+ resolved_path="$(pwd)/$path"
+ fi
+
+ # Check file exists
+ if [[ ! -f "$resolved_path" ]]; then
+ echo "⚠️ BYO file not found: $path → Falling back to base prompt." >&2
+ return 0
+ fi
+
+ # Check file is readable
+ if [[ ! -r "$resolved_path" ]]; then
+ echo "⚠️ BYO file unreadable: $path → Falling back to base prompt." >&2
+ return 0
+ fi
+
+ # Read content using cat
+ local content
+ content=$(cat "$resolved_path")
+ if [[ $? -ne 0 ]]; then
+ echo "⚠️ BYO file parse error: $path → Falling back to base prompt." >&2
+ return 0
+ fi
+
+ # Check if empty
+ if [[ -z "$content" ]]; then
+ echo "⚠️ BYO file is empty: $path → Falling back to base prompt." >&2
+ return 0
+ fi
+
+ # Check length
+ if (( ${#content} > max_chars )); then
+ echo "⚠️ BYO exceeds ${max_chars} chars (${#content}) → Falling back to base prompt." >&2
+ return 0
+ fi
+
+ # Success
+ printf '%s' "$content"
+}
+
+
# ---------- build exclude args ----------
build_diff_excludes() {
@@ -557,7 +630,6 @@ build_allocated_diff() {
echo "${preamble}${files_header}${file_summary}${diff_header}${final_diff}"
}
-
# ---------- prepare diff ----------
prepare_diff() {
local header="$1"
@@ -605,8 +677,8 @@ commit_changes() {
# ---------- main ----------
diffsense() {
- local parsed ai_model message_style nopopup_suffix
- local diff header prompt payload commit_msg
+ local parsed ai_model message_style nopopup_suffix byo_path
+ local diff header prompt byo_prompt payload commit_msg
if [[ "$#" -gt 0 ]]; then
case "$1" in
@@ -621,17 +693,28 @@ diffsense() {
exit 1
fi
- ai_model=$(awk '{print $1}' <<< "$parsed")
- message_style=$(awk '{print $2}' <<< "$parsed")
- nopopup_suffix=$(awk '{print $3}' <<< "$parsed")
+ # Parse with | delimiter
+ IFS='|' read -r ai_model message_style nopopup_suffix byo_path <<< "$parsed"
+
+ # DEBUG
set_max_chars_for_model "$ai_model"
check_platform_and_arch || exit 1
check_is_git_repo
check_git_state
+ # Build base prompt
prompt=$(build_prompt "$message_style")
+
+ # Load and append BYO prompt if provided
+ if [[ -n "$byo_path" ]]; then
+ byo_prompt=$(load_byo_prompt "$byo_path")
+ if [[ -n "$byo_prompt" ]]; then
+ prompt="${prompt}"$'\n\n'"Additional Instructions:"$'\n'"${byo_prompt}"
+ fi
+ fi
+
header="@@DIFFSENSE_META=${ai_model}${nopopup_suffix}"
# Main diff strategy
@@ -639,7 +722,7 @@ diffsense() {
payload="${header}"$'\n'"${prompt}"$'\n\n'"${diff}"
- # SAFETY: Final truncation to guarantee we never exceed the limit
+ # SAFETY: Final truncation to guarantee we never exceed the limit
if (( ${#payload} > DIFFSENSE_MAX_CHARS )); then
payload="${payload:0:DIFFSENSE_MAX_CHARS}"
fi
@@ -648,4 +731,6 @@ diffsense() {
commit_changes "$commit_msg"
}
+diffsense "$@"
+
diffsense "$@"
\ No newline at end of file