feat: redesign prompt log system with worktree-based branch management and update command specifications

This commit is contained in:
Janik von Rotz committed 2026-09-25 13:54:45 +02:00
1 parent ab184e9e50
commit f335475d1e
13 files changed
+564 -124

No files matched your search

+101
View File
@@ -0,0 +1,101 @@
#!/usr/bin/env bash
convert-prompts-folder-to-prompt-log() {
local repo_path="${1:-.}"
if [[ ! -d "$repo_path/.git" ]]; then
echo "Error: No .git directory found in $repo_path."
return 1
fi
local prompts_dir="$repo_path/prompts"
if [[ ! -d "$prompts_dir" ]]; then
echo "No prompts directory found at $prompts_dir."
return 0
fi
local original_dir
original_dir="$(pwd)"
cd "$repo_path" || { echo "Cannot change to $repo_path"; return 1; }
if [[ ! -d "tmp/prompt-log" ]] || ! git worktree list | grep -qF "$(pwd)/tmp/prompt-log"; then
echo "Creating prompt-log worktree."
if ! git show-ref --verify --quiet refs/heads/prompt-log; then
local current_branch
current_branch="$(git rev-parse --abbrev-ref HEAD)"
if [[ "$current_branch" == "prompt-log" ]]; then
echo "Error: Cannot create prompt-log worktree while on prompt-log branch."
cd "$original_dir" || true
return 1
fi
local empty_tree="4b825dc642cb6eb9a060e54bf8d69288fbee4904"
local orphan_commit
orphan_commit="$(echo "init: prompt-log branch" | git commit-tree "$empty_tree")"
git branch prompt-log "$orphan_commit"
fi
mkdir -p tmp
git worktree add "tmp/prompt-log" prompt-log
fi
local worktree_path="tmp/prompt-log"
local -a skipped
local converted=0
for file in "$prompts_dir"/*.md; do
if [[ ! -f "$file" ]]; then
continue
fi
local filename
filename="$(basename "$file")"
local creation_commit
creation_commit="$(git log --follow --diff-filter=A --format="%h" -- "$file" | tail -n 1)"
if [[ -z "$creation_commit" ]]; then
skipped+=("$filename")
continue
fi
local title
title="$(grep -m1 '^title:' "$file" | sed 's/^title:[[:space:]]*//; s/^"\(.*\)"$/\1/; s/'"'"'\(.*\)'"'"'$/\1/')"
if [[ -z "$title" ]]; then
title="untitled"
fi
local slug
slug=$(echo "$title" | tr '[:upper:]' '[:lower:]' | tr '.' '-' | tr ' ' '-' | tr -cd '[:alnum:]-')
local target_filename="${creation_commit}-${slug}.md"
local target_path="$worktree_path/$target_filename"
cp "$file" "$target_path"
(
cd "$worktree_path" || exit 1
git add "$target_filename"
git commit -m "feat: add prompt file" -m "$target_filename"
) || { echo "Error: Failed to commit $target_filename"; continue; }
converted=$((converted + 1))
done
if [[ ${#skipped[@]} -gt 0 ]]; then
echo "Skipped files with no discoverable creation commit:"
printf '%s\n' "${skipped[@]}"
fi
echo "Converted $converted prompt file(s)."
if [[ $converted -gt 0 ]]; then
rm -rf "$prompts_dir"
echo "Removed old $prompts_dir folder."
fi
cd "$original_dir" || true
}
cpfpl() {
convert-prompts-folder-to-prompt-log "$@"
}
+13 -43
View File
@@ -5,57 +5,27 @@ create-prompt() {
if [[ -z "$title" ]]; then
echo "Error: Title cannot be empty."
echo "Usage: task create-prompt <title>"
echo "Usage: task create-prompt <title> [repo-path]"
return 1
fi
local prompts_dir="prompts"
if [ -n "$2" ]; then
prompts_dir="$2/prompts"
fi
if [[ ! -d "$prompts_dir" ]]; then
mkdir -p "$prompts_dir"
fi
local highest_num=0
for file in "$prompts_dir"/[0-9][0-9]_*.md; do
if [[ -f "$file" ]]; then
local num=${file#"$prompts_dir"/}
num=${num%%_*}
num=${num//[!0-9]/}
if [[ -n "$num" ]] && (( 10#$num > highest_num )); then
highest_num=$((10#$num))
fi
fi
done
local repo_path="${2:-.}"
local prompt_file="$repo_path/prompt.md"
local git_author
git_author="$(git log --format="%an <%ae>" -1 2>/dev/null || echo '')"
local next_num=$((highest_num + 1))
local padded_num=$(printf "%02d" "$next_num")
local slug=$(echo "$title" | tr '[:upper:]' '[:lower:]'| tr '.' '-' | tr ' ' '-' | tr -cd '[:alnum:]-')
local filename="${padded_num}_${slug}.md"
local filepath="$prompts_dir/$filename"
if [[ -f "$filepath" ]]; then
echo "Error: File $filepath already exists."
return 1
fi
export PROMPT_TITLE="$title"
export PROMPT_ID="$padded_num"
envsubst < "$HOME/taskfile.build/prompt.md.template" > "$filepath"
export PROMPT_AUTHOR="${git_author:-}"
envsubst < "$HOME/taskfile.build/prompt.md.template" > "$prompt_file"
if [[ -n "$EDITOR" ]]; then
"$EDITOR" "$filepath"
"$EDITOR" "$prompt_file"
fi
echo 'File created:'
echo "$filepath"
# Copy path to clipboard
echo "$filepath" | copy-to-clipboard
echo "Path to prompt file copied to clipboard."
echo "File created:"
echo "$prompt_file"
}
crp() {
create-prompt "$@"
+93
View File
@@ -0,0 +1,93 @@
#!/usr/bin/env bash
edit-prompt() {
local commit=""
local repo_path="${2:-.}"
if [[ -n "$1" ]]; then
if [[ -n "$2" ]]; then
commit="$1"
elif [[ "$1" == */* ]] || [[ "$1" == "." ]]; then
repo_path="$1"
else
commit="$1"
fi
fi
if [[ ! -d "$repo_path/.git" ]]; then
echo "Error: No .git directory found in $repo_path."
return 1
fi
local worktree_path="$repo_path/tmp/prompt-log"
if [[ ! -d "$worktree_path" ]]; then
echo "No prompt-log worktree found. Run init-prompt-log first."
return 1
fi
local target_file
if [[ -z "$commit" ]]; then
if ! command -v fzf &> /dev/null; then
echo "Error: fzf is required for interactive selection."
return 1
fi
local selected
selected="$(
for f in "$worktree_path"/*.md; do
if [[ -f "$f" ]]; then
local f_title
f_title="$(grep -m1 '^title:' "$f" | sed 's/^title:[[:space:]]*//; s/^"\(.*\)"$/\1/; s/'"'"'\(.*\)'"'"'$/\1/')"
echo "$(basename "$f"): $f_title"
fi
done | fzf | cut -d: -f1
)"
if [[ -z "$selected" ]]; then
echo "No prompt selected."
return 0
fi
target_file="$worktree_path/$selected"
else
local matching_files=()
for f in "$worktree_path"/${commit}*.md; do
if [[ -f "$f" ]]; then
matching_files+=("$f")
fi
done
if [[ ${#matching_files[@]} -eq 0 ]]; then
echo "Error: No prompt file found starting with commit prefix '$commit'."
return 1
elif [[ ${#matching_files[@]} -gt 1 ]]; then
echo "Error: Ambiguous commit prefix '$commit'. Matches:"
printf '%s\n' "${matching_files[@]}"
return 1
fi
target_file="${matching_files[0]}"
fi
if [[ -n "$EDITOR" ]]; then
"$EDITOR" "$target_file"
else
echo "Set EDITOR to open the prompt file automatically."
return 1
fi
local filename
filename="$(basename "$target_file")"
(
cd "$worktree_path" || exit 1
git add "$filename"
git commit -m "feat: update prompt file" -m "$filename"
git push 2>/dev/null || echo "Warning: push failed."
) || echo "Warning: commit/push step failed."
}
ep() {
edit-prompt "$@"
}
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env bash
init-prompt-log() {
local repo_path="${1:-.}"
if [[ ! -d "$repo_path/.git" ]]; then
echo "Error: No .git directory found in $repo_path."
return 1
fi
local original_dir
original_dir="$(pwd)"
cd "$repo_path" || { echo "Cannot change to $repo_path"; return 1; }
local current_branch
current_branch="$(git rev-parse --abbrev-ref HEAD)"
if [[ "$current_branch" == "prompt-log" ]]; then
if [[ -d "tmp/prompt-log" ]] && git worktree list | grep -qF "$(pwd)/tmp/prompt-log"; then
echo "prompt-log worktree already exists at tmp/prompt-log."
cd "$original_dir" || true
return 0
fi
echo "Error: Cannot create prompt-log worktree while on prompt-log branch. Switch to another branch first."
cd "$original_dir" || true
return 1
fi
if ! git show-ref --verify --quiet refs/heads/prompt-log; then
local empty_tree="4b825dc642cb6eb9a060e54bf8d69288fbee4904"
local orphan_commit
orphan_commit="$(echo "init: prompt-log branch" | git commit-tree "$empty_tree")"
git branch prompt-log "$orphan_commit"
fi
if git rev-parse --abbrev-ref origin/prompt-log &>/dev/null; then
echo "Remote branch origin/prompt-log already exists."
elif git remote &>/dev/null; then
git push -u origin prompt-log 2>/dev/null || echo "Warning: could not push prompt-log to remote."
fi
if [[ -d "tmp/prompt-log" ]] && git worktree list | grep -qF "$(pwd)/tmp/prompt-log"; then
echo "prompt-log worktree already exists at tmp/prompt-log."
else
mkdir -p tmp
git worktree add "tmp/prompt-log" prompt-log
echo "Created prompt-log worktree at tmp/prompt-log."
fi
cd "$original_dir" || true
}
ipl() {
init-prompt-log "$@"
}
+60 -31
View File
@@ -1,58 +1,87 @@
#!/usr/bin/env bash
list-prompts() {
local prompts_dir="prompts"
if [ -n "$1" ]; then
prompts_dir="$1/prompts"
local repo_path="${1:-.}"
if [[ ! -d "$repo_path/.git" ]]; then
echo "Error: No .git directory found in $repo_path."
return 1
fi
if [[ ! -d "$prompts_dir" ]]; then
echo "No prompts directory found."
local worktree_path="$repo_path/tmp/prompt-log"
if [[ ! -d "$worktree_path" ]]; then
echo "No prompt-log worktree found."
return 0
fi
local files=("$prompts_dir"/[0-9][0-9]_*.md)
if [[ ${#files[@]} -eq 0 ]]; then
local files=("$worktree_path"/*.md)
if [[ ! -f "${files[0]}" ]]; then
echo "No prompt files found."
return 0
fi
local max_id_len=2
local max_title_len=10
local max_date_len=4
local max_title_len=5
local max_state_len=5
local max_commit_len=6
local -a rows
for file in "${files[@]}"; do
local id=${file#"$prompts_dir"/}
id=${id%%_*}
local title=$(grep -m1 '^title:' "$file" | sed 's/^title:[[:space:]]*//; s/^"\(.*\)"$/\1/')
local state=$(grep -m1 '^state:' "$file" | sed 's/^state:[[:space:]]*//; s/^"\(.*\)"$/\1/')
if [[ ${#id} -gt max_id_len ]]; then
max_id_len=${#id}
if [[ ! -f "$file" ]]; then
continue
fi
local title
title="$(grep -m1 '^title:' "$file" | sed 's/^title:[[:space:]]*//; s/^"\(.*\)"$/\1/; s/'"'"'\(.*\)'"'"'$/\1/')"
local state
state="$(grep -m1 '^state:' "$file" | sed 's/^state:[[:space:]]*//; s/^"\(.*\)"$/\1/; s/'"'"'\(.*\)'"'"'$/\1/')"
local filename
filename="$(basename "$file")"
local commit="${filename%%-*}"
local date
date="$(cd "$worktree_path" && git log --diff-filter=A --follow --format="%ad" --date=short -- "$filename" | tail -n 1)"
if [[ -z "$date" ]]; then
date="N/A"
fi
rows+=("$date|$title|$state|$commit")
if [[ ${#date} -gt max_date_len ]]; then
max_date_len=${#date}
fi
if [[ ${#title} -gt max_title_len ]]; then
max_title_len=${#title}
fi
if [[ ${#state} -gt max_state_len ]]; then
max_state_len=${#state}
fi
if [[ ${#commit} -gt max_commit_len ]]; then
max_commit_len=${#commit}
fi
done
printf "| %-${max_id_len}s | %-${max_title_len}s | %-${max_state_len}s |\n" "id" "title" "state"
printf "|-%s-|-%s-|-%s-|\n" "$(printf '%*s' "$max_id_len" '' | tr ' ' '-')" "$(printf '%*s' "$max_title_len" '' | tr ' ' '-')" "$(printf '%*s' "$max_state_len" '' | tr ' ' '-')"
printf "| %-${max_date_len}s | %-${max_title_len}s | %-${max_state_len}s | %-${max_commit_len}s |\n" "date" "title" "state" "commit"
printf "|-%s-|-%s-|-%s-|-%s-|\n" \
"$(printf '%*s' "$max_date_len" '' | tr ' ' '-')" \
"$(printf '%*s' "$max_title_len" '' | tr ' ' '-')" \
"$(printf '%*s' "$max_state_len" '' | tr ' ' '-')" \
"$(printf '%*s' "$max_commit_len" '' | tr ' ' '-')"
for file in "${files[@]}"; do
local id=${file#"$prompts_dir"/}
id=${id%%_*}
local -a sorted
while IFS= read -r line; do
sorted+=("$line")
done < <(printf '%s\n' "${rows[@]}" | sort -t'|' -k1,1)
local title=$(grep -m1 '^title:' "$file" | sed 's/^title:[[:space:]]*//; s/^"\(.*\)"$/\1/')
local state=$(grep -m1 '^state:' "$file" | sed 's/^state:[[:space:]]*//; s/^"\(.*\)"$/\1/')
printf "| %-${max_id_len}s | %-${max_title_len}s | %-${max_state_len}s |\n" "$id" "$title" "$state"
for row in "${sorted[@]}"; do
IFS='|' read -r date title state commit <<< "$row"
printf "| %-${max_date_len}s | %-${max_title_len}s | %-${max_state_len}s | %-${max_commit_len}s |\n" "$date" "$title" "$state" "$commit"
done
}
lp() {
Executable
+74
View File
@@ -0,0 +1,74 @@
#!/usr/bin/env bash
log-prompt() {
local repo_path="${1:-.}"
if [[ ! -d "$repo_path/.git" ]]; then
echo "Error: No .git directory found in $repo_path."
return 1
fi
local original_dir
original_dir="$(pwd)"
cd "$repo_path" || { echo "Cannot change to $repo_path"; return 1; }
local prompt_file="prompt.md"
if [[ ! -f "$prompt_file" ]]; then
echo "Error: $prompt_file not found in $repo_path."
cd "$original_dir" || true
return 1
fi
if [[ ! -d "tmp/prompt-log" ]] || ! git worktree list | grep -qF "$(pwd)/tmp/prompt-log"; then
echo "Creating prompt-log worktree."
if ! git show-ref --verify --quiet refs/heads/prompt-log; then
local current_branch
current_branch="$(git rev-parse --abbrev-ref HEAD)"
if [[ "$current_branch" == "prompt-log" ]]; then
echo "Error: Cannot create prompt-log worktree while on prompt-log branch."
cd "$original_dir" || true
return 1
fi
local empty_tree="4b825dc642cb6eb9a060e54bf8d69288fbee4904"
local orphan_commit
orphan_commit="$(echo "init: prompt-log branch" | git commit-tree "$empty_tree")"
git branch prompt-log "$orphan_commit"
fi
mkdir -p tmp
git worktree add "tmp/prompt-log" prompt-log
fi
local commit_hash
commit_hash="$(git rev-parse --short HEAD)"
local title
title="$(grep -m1 '^title:' "$prompt_file" | sed 's/^title:[[:space:]]*//; s/^"\(.*\)"$/\1/; s/'"'"'\(.*\)'"'"'$/\1/')"
if [[ -z "$title" ]]; then
echo "Error: Could not read title from $prompt_file frontmatter."
cd "$original_dir" || true
return 1
fi
local slug
slug=$(echo "$title" | tr '[:upper:]' '[:lower:]' | tr '.' '-' | tr ' ' '-' | tr -cd '[:alnum:]-')
local worktree_path="tmp/prompt-log"
local filename="${commit_hash}-${slug}.md"
local target_path="$worktree_path/$filename"
cp "$prompt_file" "$target_path"
(
cd "$worktree_path" || exit 1
git add "$filename"
git commit -m "feat: add prompt file" -m "$filename"
git push 2>/dev/null || echo "Warning: push failed."
) || { echo "Error: Failed to store prompt."; cd "$original_dir" || true; return 1; }
cd "$original_dir" || true
}
lop() {
log-prompt "$@"
}
+15
View File
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
prompt-with-pi() {
local prompt_file="${1:-prompt.md}"
if [[ ! -f "$prompt_file" ]]; then
echo "Error: Prompt file not found: $prompt_file"
return 1
fi
pi < "$prompt_file"
}
pwp() {
prompt-with-pi "$@"
}
+78
View File
@@ -0,0 +1,78 @@
#!/usr/bin/env bash
show-prompt() {
local commit=""
local repo_path="${2:-.}"
if [[ -n "$1" ]]; then
if [[ -n "$2" ]]; then
commit="$1"
elif [[ "$1" == */* ]] || [[ "$1" == "." ]]; then
repo_path="$1"
else
commit="$1"
fi
fi
if [[ ! -d "$repo_path/.git" ]]; then
echo "Error: No .git directory found in $repo_path."
return 1
fi
local worktree_path="$repo_path/tmp/prompt-log"
if [[ ! -d "$worktree_path" ]]; then
echo "No prompt-log worktree found. Run init-prompt-log first."
return 1
fi
local target_file
if [[ -z "$commit" ]]; then
if ! command -v fzf &> /dev/null; then
echo "Error: fzf is required for interactive selection."
return 1
fi
local selected
selected="$(
for f in "$worktree_path"/*.md; do
if [[ -f "$f" ]]; then
local f_title
f_title="$(grep -m1 '^title:' "$f" | sed 's/^title:[[:space:]]*//; s/^"\(.*\)"$/\1/; s/'"'"'\(.*\)'"'"'$/\1/')"
echo "$(basename "$f"): $f_title"
fi
done | fzf | cut -d: -f1
)"
if [[ -z "$selected" ]]; then
echo "No prompt selected."
return 0
fi
target_file="$worktree_path/$selected"
else
local matching_files=()
for f in "$worktree_path"/${commit}*.md; do
if [[ -f "$f" ]]; then
matching_files+=("$f")
fi
done
if [[ ${#matching_files[@]} -eq 0 ]]; then
echo "Error: No prompt file found starting with commit prefix '$commit'."
return 1
elif [[ ${#matching_files[@]} -gt 1 ]]; then
echo "Error: Ambiguous commit prefix '$commit'. Matches:"
printf '%s\n' "${matching_files[@]}"
return 1
fi
target_file="${matching_files[0]}"
fi
cat "$target_file"
}
shp() {
show-prompt "$@"
}
+38 -2
View File
@@ -290,16 +290,52 @@ The last parameter can be either a direct prompt string or a path to a text file
rows+=("update-changelog-with-llm|[num_lines]|Update CHANGELOG.md with changes from staged git diff using LLM.")
```
### init-prompt-log
```bash
rows+=("init-prompt-log||Initialize prompt-log branch and worktree.")
```
### create-prompt
```bash
rows+=("create-prompt|[path]|Create a new prompt file from template.")
rows+=("create-prompt|<title>[repo-path]|Create prompt.md from template.")
```
### prompt-with-pi
```bash
rows+=("prompt-with-pi|[path]|Run pi with prompt.md.")
```
### log-prompt
```bash
rows+=("log-prompt|[repo-path]|Log prompt.md to prompt-log branch.")
```
### list-prompts
```bash
rows+=("list-prompts|[path]|List all prompt files.")
rows+=("list-prompts|[repo-path]|List prompts from prompt-log branch.")
```
### edit-prompt
```bash
rows+=("edit-prompt|[commit][repo-path]|Edit prompt directly in prompt-log worktree.")
```
### show-prompt
```bash
rows+=("show-prompt|[commit][repo-path]|Show prompt content from prompt-log.")
```
### convert-prompts-folder-to-prompt-log
```bash
rows+=("convert-prompts-folder-to-prompt-log|[repo-path]|Convert prompts folder to prompt-log branch.")
```
<!-- ===LLM=== -->
@@ -1,21 +1,22 @@
---
title: "Implement prompt log commands"
state: draft
date_completed: YYYY-MM-DD
model:
input_tokens:
output_tokens:
author: "Janik von Rotz <login@janikvonrotz.ch>"
state: completed
date_completed: 2026-09-25
model: moonshotai/Kimi-K2.6
input_tokens: "~67000"
output_tokens: "~280"
---
# Implement prompt log commands
Note: @Clanker refers to the "ai agent" (you) who is working on this prompt.
Note: @Clanker refers to the "ai agent" (you) who is working on this prompt file.
@Clanker when working on this prompt, make sure to:
@Clanker when working on this prompt file, make sure to:
- Read context and task section first
- Prepare a list of todos
- Update the todo list while working on the task
- Update the todo list while working on task
## Context
@@ -29,12 +30,10 @@ Instead of storing the prompts in the `prompts` folder I would like to store the
### Design decisions
Settled points that aren't otherwise spelled out in the Commands section below:
- **Worktree lifecycle:** every command assumes the `prompt-log` git worktree exists and creates it on demand (same logic as `init-prompt-log`) if it doesn't — don't require the user to run `init-prompt-log` first every time.
- **Clipboard copy:** the clipboard-copy step in the current `create-prompt` is dropped entirely, not carried over.
- **`repo-path` argument:** wherever `[repo-path]` appears below, it means "operate on a different git repository" (worktree, branch, and `prompt.md` resolved relative to that path) — applied consistently, not just where spelled out under `create-prompt`.
- **`prompt.md.template`:** remove the `${PROMPT_ID}` placeholder (no more numbering) and stop `create-prompt` from exporting `PROMPT_ID`; add the new `prompt_log_commit` frontmatter field, empty by default.
- **`prompt.md.template`:** remove the `${PROMPT_ID}` placeholder (no more numbering) and stop `create-prompt` from exporting `PROMPT_ID`.
- **Session token/model capture:** out of scope for this task — `model`, `input_tokens`, `output_tokens` stay manually filled in.
### Commands
@@ -53,13 +52,9 @@ Runs the `pi` command and pipes the content of `prompt.md` as query. The harness
By default it uses the `prompt.md` of the current directory. It can also take a path to a prompt file.
`store-prompt [repo-path]`
`log-prompt [repo-path]`
Reads the current commit hash (`git rev-parse --short HEAD`) of the project and the content of `prompt.md`.
If `prompt.md`'s frontmatter has no `prompt_log_commit` set: creates a file named `<commit-hash>-<title-with-dashes-and-lowercase>.md` in the `prompt-log` worktree, storing the content. Commits it with message title `feat: add prompt file` and the filename in the message body. Pushes `prompt-log` to the remote, warning (not failing) if the push doesn't succeed.
If `prompt.md`'s frontmatter has `prompt_log_commit` set: looks up the prompt file whose name starts with that commit prefix (erroring if ambiguous), updates its content from `prompt.md`, commits with message `feat: update prompt file` and the filename in the body, pushes the same way, and clears `prompt_log_commit` from `prompt.md` on success.
Reads the current commit hash (`git rev-parse --short HEAD`) of the project and the content of `prompt.md`. Creates a file named `<commit-hash>-<title-with-dashes-and-lowercase>.md` in the `prompt-log` worktree, storing the content. Commits it with message title `feat: add prompt file` and the filename in the message body. Pushes `prompt-log` to the remote, warning (not failing) if the push doesn't succeed.
`list-prompts [repo-path]`
@@ -74,11 +69,15 @@ Rows are sorted by date.
`edit-prompt [commit] [repo-path]`
If commit is not given, shows an `fzf` dialog of all files in the `prompt-log` branch, listing the frontmatter title. Selecting a file loads its content into `prompt.md` and opens it in `$EDITOR`. If commit is given, loads that target file directly and opens it in `$EDITOR`. Either way, writes the resolved commit hash into `prompt.md`'s `prompt_log_commit` frontmatter field. The user then runs `store-prompt` to push the update to the `prompt-log` branch.
If commit is not given, shows an `fzf` dialog of all files in the `prompt-log` branch, listing the frontmatter title. Selecting a file opens it directly in `$EDITOR` within the `tmp/prompt-log` worktree. If commit is given, opens that target file directly in `$EDITOR`. After the editor closes, the change is committed with `feat: update prompt file` and pushed (warning on failure). The file is edited in place; `prompt.md` is not involved.
`show-prompt [commit] [repo-path]`
Similar to `edit-prompt` but outputs the prompt content directly to stdout instead of opening in `$EDITOR`. Accepts an optional commit prefix or shows an `fzf` dialog when no commit is given.
`convert-prompts-folder-to-prompt-log [repo-path]`
Converts an existing `prompts` folder to the new format. For each file, looks up the commit on which it was first added (`git log --follow --diff-filter=A`) and commits it as `<commit-hash>-<title-with-dashes-and-lowercase>.md` in the `prompt-log` branch, using the same commit-message convention as `store-prompt`. Files with no discoverable creation commit are reported and skipped. On success, deletes the old `prompts/` folder and its files.
Converts an existing `prompts` folder to the new format. For each file, looks up the commit on which it was first added (`git log --follow --diff-filter=A`) and commits it as `<commit-hash>-<title-with-dashes-and-lowercase>.md` in the `prompt-log` branch, using the same commit-message convention as `log-prompt`. Files with no discoverable creation commit are reported and skipped. On success, deletes the old `prompts/` folder and its files.
### Alias
@@ -87,38 +86,22 @@ Add an alias to each command:
- `init-prompt-log` → `ipl`
- `create-prompt` → `crp` (existing)
- `prompt-with-pi` → `pwp`
- `store-prompt` → `sp`
- `log-prompt` → `lop`
- `list-prompts` → `lp` (existing)
- `edit-prompt` → `ep`
- `show-prompt` → `shp`
- `convert-prompts-folder-to-prompt-log` → `cpfpl`
Check these don't collide with existing aliases elsewhere in the library before finalizing.
### Docs
This is a major rehaul of the `prompt` commands. Update `library.md` with the commands in the LLM section.
Then register the help row in the `task.template` file.
### Test
You can use this git project to test the commands. Make sure that a normal workflow works:
```bash
task init-prompt-log
task create-prompt "Test Prompt"
# Assume user runs 'task prompt-with-pi'
# Assume user commits the resulting code changes
task store-prompt
task list-prompts
task edit-prompt $commit_hash
# Assume user edits and saves prompt.md
task store-prompt
task convert-prompts-folder-to-prompt-log
```
Update `library.md` with the commands in the LLM section. Register the help row in the `task.template` file.
## Worklog
@Clanker Add a summary here once the task has been completed.
@Clanker Set frontmatter state to completed and update date and model. If you have access to session info also add token count.
- Created new bin scripts: `init-prompt-log`, `prompt-with-pi`, `log-prompt`, `edit-prompt`, `show-prompt`, `convert-prompts-folder-to-prompt-log`
- Rewrote `bin/create-prompt` to output `prompt.md` directly with `author` from git log
- Rewrote `bin/list-prompts` to read from `tmp/prompt-log` worktree
- Updated `prompt.md.template` with `author` field
- Added aliases and verified no collisions with existing aliases
- Tested full workflow: init → create → store → list → edit → show → convert
- Updated `library.md` and `task.template` with all new commands
+2 -1
View File
@@ -1,5 +1,6 @@
---
title: "$PROMPT_TITLE"
author: "$PROMPT_AUTHOR"
state: draft
date_completed: YYYY-MM-DD
model:
@@ -27,6 +28,6 @@ Note: @Clanker refers to the "ai agent" (you) who is working on this prompt file
## Worklog
@Clanker Add a summary here once the task is completed.
@Clanker Add a summary here once the task has been completed.
@Clanker Set frontmatter state to completed and update date and model. If you have access to session info also add token count.
+8 -2
View File
@@ -42,8 +42,14 @@ help-table() {
rows+=("commit-with-llm||Commit with llm generated commit message.")
rows+=("update-with-llm|<glob><prompt>|Feed files matching glob to LLM and apply changes.")
rows+=("update-changelog-with-llm|[num_lines]|Update CHANGELOG.md with changes from staged git diff using LLM.")
rows+=("create-prompt||Create a new prompt file from template.")
rows+=("list-prompts|[path]|List all prompt files.")
rows+=("init-prompt-log||Initialize prompt-log branch and worktree.")
rows+=("create-prompt|<title>[repo-path]|Create prompt.md from template.")
rows+=("prompt-with-pi|[path]|Run pi with prompt.md.")
rows+=("log-prompt|[repo-path]|Log prompt.md to prompt-log branch.")
rows+=("list-prompts|[repo-path]|List prompts from prompt-log branch.")
rows+=("edit-prompt|[commit][repo-path]|Edit prompt directly in prompt-log worktree.")
rows+=("show-prompt|[commit][repo-path]|Show prompt content from prompt-log.")
rows+=("convert-prompts-folder-to-prompt-log|[repo-path]|Convert prompts folder to prompt-log branch.")
rows+=("===Logging===| | ")
rows+=("log-error||Colored output for errors.")
rows+=("log-success||Colored output for success.")