This repository was archived by the owner on Jun 4, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy path16-ai.rc
More file actions
457 lines (395 loc) · 16.7 KB
/
Copy path16-ai.rc
File metadata and controls
457 lines (395 loc) · 16.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
# shellcheck disable=SC2148 disable=SC1090 shell=bash
# Aliases and functions for AI tools (Note exports are still in 5-exports.rc)
### Aliases ###
# shellcheck disable=SC2139
alias clinerules="code /Users/samm/Library/Mobile\ Documents/com\~apple\~CloudDocs/Documents/Cline"
alias clinerulesd="cd /Users/samm/Library/Mobile\ Documents/com\~apple\~CloudDocs/Documents/Cline"
alias sync_ollama_models="${HOME}/git/sammcj/scripts/ollama/export_ollama_model.py"
alias '???'='copilot-comments'
alias wtf='copilot'
# alias l="OLLAMA_HOST=http://localhost:11434 gollama -l"
alias i="ingest"
alias code2prompt="ingest"
# alias ln="gollama -l"
alias gl="gollama"
alias ol="mods"
alias idf='. $HOME/.espressif/v5.5.2/esp-idf/export.sh'
alias o='tlm explain'
# alias hf="hfdownloader -c 10 -t \$HUGGINGFACE_TOKEN -j"
alias imagesearch="sisi search"
alias gemini="gemini --yolo"
alias q='kiro-cli'
alias kanban="npx -y vibe-kanban"
## Claude Code aliases
alias claude="~/.local/bin/claude"
alias cc='claude'
alias cca='CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 cc'
alias ccd='cc --dangerously-skip-permissions'
alias ccda='CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 ccd'
alias ccc='cc --continue'
alias cccf='ccc --fork-session'
alias ccaac='CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 ccc'
alias cccd='ccc --dangerously-skip-permissions'
alias cccdf='cccd --fork-session'
alias ccaacd='CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 cccd'
alias ccr='cc --resume'
alias ccrf='ccr --fork-session'
alias ccra='CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 ccr'
alias ccrd='ccr --dangerously-skip-permissions'
alias ccrdf='ccrd --fork-session'
alias ccra='CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 ccrd'
alias claude-history='claude-code-viewer' # requires: pnpm install -g @kimuson/claude-code-viewer@latest
alias oc='opencode'
# Claude Code non-interactive functions
alias '??'='claude_helper'
alias '??!'='claude_helper_exec'
## End of Claude Code aliases
### Functions ###
# Command-line helper - provides commands without execution
function claude_helper {
local prompt="$*"
claude \
--system-prompt 'You are a macOS zsh command-line assistant. Provide exact commands to accomplish tasks. Output the command. If the command is highly complex you may provide a concise explanation. You are running non-interactively so you cannot ask questions. You cannot execute commands. Do not add conversational text, questions, or unnecessary detail. Focus on providing the most appropriate and efficient command following current best practices.' \
--disallowed-tools Bash \
--strict-mcp-config \
-p \
"$prompt" | bat --squeeze-blank --language=bash --theme Dracula --style=plain --paging=never
}
# Command-line helper with execution - runs commands when explicitly requested
function claude_helper_exec {
local prompt="$*"
claude \
--system-prompt 'You are a macOS command-line assistant with execution access. Run commands to accomplish the requested task. Do not run unsafe commands that may harm the system or compromise security. You are running non-interactively so you cannot ask questions. If the user asks you to run a command that may delete, edit or overwrite files BEFORE DOING ANYTHING ELSE YOU MUST REFUSE unless they have given you the exact phrase "YES REALLY" at the start or end of their request - you may state this as a condition for executing such commands. Provide concise output keeping explanations brief and focused on the commands being run.' \
--strict-mcp-config \
-p \
"$prompt" | bat --squeeze-blank --language=bash --theme Dracula --style=plain --paging=never
}
copilot-comments () {
# Fetches unresolved GitHub Copilot comments for the current branch's PR, useful for piping to pbcopy and providing to Claude Code etc. The workflow is:
# 1. Open a PR on Github
# 2. Wait for Copilot to review it
# 3. In the repo on your machine run copilot-comments|pbcopy
# 4. Paste into your claude code or whatever session on the repo
local -r current_branch="$(git branch --show-current 2>/dev/null)" || {
printf "Error: Not in a git repository or no current branch\n" >&2
return 1
}
local base_branch pr_num general_reviews inline_comments all_prs owner repo
base_branch="$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name' 2>/dev/null)" || base_branch="main"
pr_num="$(gh pr list --head "${current_branch}" --base "${base_branch}" --json number --jq '.[0].number' 2>/dev/null)" || pr_num=""
if [[ -z "${pr_num}" || "${pr_num}" == "null" ]]
then
printf "No open PR found for current branch %s\n" "${current_branch}"
if all_prs="$(gh pr list --base "${base_branch}" --json number,title,headRefName --jq '.[] | "PR #\(.number): \(.title) (branch: \(.headRefName))"' 2>/dev/null)" && [[ -n "${all_prs}" ]]
then
printf "All open PRs to %s:\n%s\n" "${base_branch}" "${all_prs}"
fi
return 1
fi
# Get owner and repo for GraphQL query
owner="$(gh repo view --json owner --jq '.owner.login' 2>/dev/null)"
repo="$(gh repo view --json name --jq '.name' 2>/dev/null)"
# Fetch general review comments (these don't have resolved status)
general_reviews="$(gh api "repos/:owner/:repo/pulls/${pr_num}/reviews" 2>/dev/null | jq -r '.[] | select(.user.login == "copilot-pull-request-reviewer" or .user.login == "Copilot") | .body' 2>/dev/null || true)"
# Fetch unresolved inline comments using GraphQL
inline_comments="$(gh api graphql -f query='
query($owner: String!, $repo: String!, $pr: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $pr) {
reviewThreads(first: 100) {
nodes {
isResolved
comments(first: 100) {
nodes {
author {
login
}
body
path
line
}
}
}
}
}
}
}
' -F owner="${owner}" -F repo="${repo}" -F pr="${pr_num}" 2>/dev/null | \
jq -r '
.data.repository.pullRequest.reviewThreads.nodes[] |
select(.isResolved == false) |
.comments.nodes[] |
select(.author.login == "copilot-pull-request-reviewer" or .author.login == "Copilot") |
if .line then
"\(.path) (line \(.line))\n\(.body)\n" + ("=" * 50) + "\n"
else
"\(.path)\n\(.body)\n" + ("=" * 50) + "\n"
end
' 2>/dev/null || true)"
if [[ -n "${general_reviews}" || -n "${inline_comments}" ]]
then
printf "I submitted the changes to Github Copilot to review, keep in mind that Github Copilot doesn't use a very strong AI model so it may not be accurate.\n"
printf "🤖 GitHub Copilot comments on PR #%s (unresolved only):\n\n" "${pr_num}"
if [[ -n "${general_reviews}" ]]
then
printf "## Copilot review comments\n"
printf "%s\n\n------\n\n" "${general_reviews}"
fi
if [[ -n "${inline_comments}" ]]
then
printf "## Copilot inline comments\n"
printf "%s\n" "${inline_comments}"
fi
printf "⚠️ Be mindful that GitHub Copilot's comments may be inaccurate. Ignore any invalid or out of context comments. Please review them carefully before applying any changes. Discuss recommendations with me if the path forward is unclear.\n"
else
printf "No unresolved Copilot comments found on PR #%s\n" "${pr_num}"
fi
}
### Claude Code ###
fcs() {
# https://github.com/pchalasani/claude-code-tools#-find-claude-session
# fcs "keyword1,keyword2,keyword3" # Search in current project
# fcs "keywords" -g Search across all Claude projects
# Check if user is asking for help
if [[ "$1" == "--help" ]] || [[ "$1" == "-h" ]]; then
find-claude-session --help
return
fi
# Run find-claude-session in shell mode and evaluate the output
eval "$(find-claude-session --shell "$@" | sed '/^$/d')"
}
function ollama-pull-all() {
local BATCH_SIZE
local PULL_LOCAL_REGISTRY_MODELS
PULL_LOCAL_REGISTRY_MODELS=true
BATCH_SIZE=3
if $PULL_LOCAL_REGISTRY_MODELS; then
echo "pulling all models in batches of ${BATCH_SIZE}..."
ollama list | awk '$1 {print $1}' | while read -r model; do
# pull the modules in parallel batches
batch_count=$(jobs -p | wc -l)
if [ "$batch_count" -ge "$BATCH_SIZE" ]; then
sleep 1
wait -n
fi
echo "Pulling $model"
ollama pull "$model" &
done
else
echo "pulling all models not in the local registry in batches of ${BATCH_SIZE}..."
ollama list | awk '$1 !~ /^${OLLAMA_REGISTRY}/ {print $1}' | while read -r model; do
# pull the modules in parallel batches
batch_count=$(jobs -p | wc -l)
if [ "$batch_count" -ge "$BATCH_SIZE" ]; then
sleep 1
wait -n
fi
echo "Pulling $model"
ollama pull "$model" &
done
fi
# wait for all background jobs to finish
wait
echo "All models pulled"
}
ollama_extend_models() {
local ctx_size=${1:-32768}
# Prompt the user if they want to proceed
read -r -p "This will create longer context (${ctx_size}) models for all ollama models. Do you want to proceed? (y/n): " choice
if [[ $choice != [yY] ]]; then
echo "Aborting..."
return 1
fi
# Run ollama ls and process each line
ollama ls | tail -n +2 | while read -r line; do
# Extract model name
model_name=$(echo "$line" | awk '{print $1}')
# Split model name into base name and variant
base_name=$(echo "$model_name" | cut -d':' -f1)
variant=$(echo "$model_name" | cut -d':' -f2)
# Create Modelfile
cat >"Modelfile-$model_name" <<EOF
FROM $model_name
PARAMETER num_ctx $ctx_size
EOF
# Create extended model
ollama create "$base_name-$ctx_size:$variant" -f "Modelfile-$model_name"
echo "Created extended model: $base_name-$ctx_size:$variant"
done
}
# A function that does an ollama cp of any models that start with sammcj to instead start with registry.domain/ollama/<rest of the tag without sammcj>
# function ollama-cp() {
# local models
# local registry
# registry=$(echo "$OLLAMA_REGISTRY" | sed 's/\//\\\//g')
# # shellcheck disable=SC2207 # array assignment is intentional
# models=($(ollama list | grep sammcj | grep -v grep | awk '{print $1}'))
# # sort by smallest to largest (human readable MB/GB)
# # calulate the total size of the models
# total_size=$(ollama list | grep sammcj | grep -v grep | awk '{print $3}' | paste -sd+ - | bc)
# echo "Total size of models to be considered: ${total_size}GB"
# # shellcheck disable=SC2207
# models=($(echo "${models[@]}" | tr ' ' '\n' | sort -h))
# for model in "${models[@]}"; do
# echo "Model: $model"
# new_model=$(echo "$model" | gsed -e s/sammcj/"$registry"/ | tr '[:upper:]' '[:lower:]')
# # if ollama list | grep -q "$new_model"; then
# # echo "Model $new_model already exists, skipping"
# # continue
# # fi
# echo "Copying $model to $new_model"
# ollama cp "$model" "$new_model" && ollama rm "$model"
# echo "Pushing $new_model"
# ollama push "$new_model"
# done
# }
# generate_commit_msg() {
# # This function generates a commit message using the ollama API
# # Map the function to a keybinding (e.g., gcm) in your .zshrc file:
# # bindkey '^Xg' generate_commit_msg
# local -r model="tinydolphin:1.1b- v2.8-q5_ K_ M"
# local -r prompt=$(git diff --cached --name-only | xargs -I{} echo "Why did you change {}?")
# local -r api_url="http://localhost:11434/api/generate"
# }
# Move a directory and migrate all Claude Code conversation context to the new path.
# Source: https://curiouslychase.com/posts/rescuing-your-claude-conversations-when-you-rename-projects/
function claude-mv() {
if [[ $# -ne 2 ]]; then
printf "Usage: claude-mv <old_directory> <new_directory>\n" >&2
printf "Example: claude-mv ~/old-project ~/new-project\n" >&2
return 1
fi
local old_dir="$1"
local new_dir="$2"
local old_abs new_abs_future new_abs
local old_encoded new_encoded
local claude_dir="${HOME}/.claude"
local already_moved=false
# Resolve paths to absolute using zsh :a modifier (works even if path doesn't exist)
old_abs="${old_dir:a}"
new_abs_future="${new_dir:a}"
if [[ -d "$old_abs" && -e "$new_abs_future" ]]; then
printf "Error: Both old and new paths exist. Unclear which way to move.\n" >&2
return 1
elif [[ ! -d "$old_abs" && -d "$new_abs_future" ]]; then
already_moved=true
printf "Old path no longer exists, new path found. Migrating Claude context only.\n"
elif [[ ! -d "$old_abs" && ! -d "$new_abs_future" ]]; then
printf "Error: Neither old (%s) nor new (%s) directory exists.\n" "$old_abs" "$new_abs_future" >&2
return 1
fi
# Encode paths the way Claude does (replace / and . with -)
old_encoded="${old_abs//[\/.]/-}"
new_encoded="${new_abs_future//[\/.]/-}"
# Check if destination Claude context already exists
local -a existing_context
local subdir
for subdir in projects file-history todos shell-snapshots debug; do
local check_path="${claude_dir}/${subdir}/${new_encoded}"
if [[ -d "$check_path" || -f "$check_path" ]]; then
existing_context+=("$subdir")
fi
done
# If destination context exists, prompt user
if (( ${#existing_context[@]} > 0 )); then
printf "Warning: Claude context already exists for %s:\n" "$new_abs_future"
local item
for item in "${existing_context[@]}"; do
local count_info=""
if [[ "$item" = "projects" && -d "${claude_dir}/${item}/${new_encoded}" ]]; then
local session_count
session_count=$(find "${claude_dir}/${item}/${new_encoded}" -name '*.jsonl' 2>/dev/null | wc -l | tr -d ' ')
count_info=" (${session_count} sessions)"
fi
printf " - %s%s\n" "$item" "$count_info"
done
printf "\nOptions:\n"
printf " [c] Clean out existing context and continue\n"
printf " [m] Merge old context into existing context\n"
printf " [n] Abort (default)\n\n"
local reply
read -k 1 "reply?Choose [c/m/N]: "
printf "\n"
case "$reply" in
[cC])
printf "Cleaning out existing context for %s...\n" "$new_abs_future"
for item in "${existing_context[@]}"; do
rm -rf "${claude_dir}/${item}/${new_encoded}"
printf " Removed %s\n" "$item"
done
printf "\n"
;;
[mM])
printf "Will merge contexts...\n"
;;
*)
printf "Aborted.\n"
return 1
;;
esac
fi
printf "Moving Claude context from:\n %s\n -> %s\n\n" "$old_abs" "$new_abs_future"
local moved=0
# Rename/merge in each location (BEFORE moving directory)
for subdir in projects file-history todos shell-snapshots debug; do
local old_path="${claude_dir}/${subdir}/${old_encoded}"
local new_path="${claude_dir}/${subdir}/${new_encoded}"
if [[ -d "$old_path" ]]; then
if [[ -d "$new_path" ]]; then
printf "Merging %s/%s -> %s/%s\n" "$subdir" "$old_encoded" "$subdir" "$new_encoded"
# (N) glob qualifier prevents zsh "no matches found" error on empty dirs
mv "$old_path"/*(N) "$new_path/" 2>/dev/null || true
rmdir "$old_path" 2>/dev/null || rm -rf "$old_path"
else
printf "Moving %s/%s -> %s/%s\n" "$subdir" "$old_encoded" "$subdir" "$new_encoded"
mv "$old_path" "$new_path"
fi
moved=$((moved + 1))
elif [[ -f "$old_path" ]]; then
printf "Moving %s/%s -> %s/%s\n" "$subdir" "$old_encoded" "$subdir" "$new_encoded"
mv "$old_path" "$new_path"
moved=$((moved + 1))
fi
done
if (( moved == 0 )); then
printf "No Claude context found for %s\n" "$old_abs"
else
printf "Moved %d context location(s)\n" "$moved"
fi
printf "\n"
# Update session file contents to reference new path
if [[ -d "${claude_dir}/projects/${new_encoded}" ]]; then
local session_files
session_files=$(find "${claude_dir}/projects/${new_encoded}" -name '*.jsonl' 2>/dev/null)
if [[ -n "$session_files" ]]; then
printf "Updating session file references...\n"
find "${claude_dir}/projects/${new_encoded}" -name '*.jsonl' -exec sed -i '' "s|${old_abs}|${new_abs_future}|g" {} \;
printf "Updated session files\n\n"
fi
fi
# Move the actual directory AFTER Claude context is moved
if $already_moved; then
new_abs="$new_abs_future"
printf "Directory already at new location, skipping move.\n\n"
else
printf "Moving directory:\n %s\n -> %s\n" "$old_abs" "$new_dir"
if ! mv "$old_abs" "$new_dir"; then
printf "Error: Failed to move directory. Claude context was already moved to the new path.\n" >&2
return 1
fi
new_abs="$(cd "$new_dir" 2>/dev/null && pwd)"
printf "Directory moved\n\n"
fi
# Update history.jsonl to reference new path
local history_file="${claude_dir}/history.jsonl"
if [[ -f "$history_file" ]]; then
printf "Updating history.jsonl references...\n"
cp "$history_file" "${history_file}.backup"
sed -i '' "s|${old_abs}|${new_abs}|g" "$history_file"
printf "Updated history.jsonl (backup: history.jsonl.backup)\n"
fi
}
# Commands that only run within Claude Code sessions
# if [[ -n "$CLAUDECODE" ]]; then
# eval "$(direnv hook zsh)" # https://github.com/direnv/direnv
# fi