Compare commits

...

2 Commits

Author SHA1 Message Date
542f1e27c1 Merge pull request 'feat(kugetsu): add --debug flag for real-time output capture' (#13) from feat/kugetsu-debug-flag into main 2026-03-29 18:26:54 +02:00
shokollm
e397a64d27 feat(kugetsu): add --debug flag for real-time output capture
- Add --debug flag to start/resume for verbose opencode output
- Use stdbuf -oL to unbuffer stdout for real-time display
- Capture debug logs to ~/.kugetsu/sessions/<id>/debug.log
- Add --debug to stop/destroy for viewing logs before actions
- Position-agnostic flag parsing (--debug can appear anywhere in args)
2026-03-29 16:23:10 +00:00

View File

@@ -10,28 +10,32 @@ usage() {
kugetsu - OpenCode Session Manager
Usage:
kugetsu start <session_id> <message> Start a new session
kugetsu list [--all] List sessions (default: left only)
kugetsu resume <session_id> [message] Resume a session
kugetsu stop <session_id> Stop a session gracefully
kugetsu destroy <session_id> [-y] Delete a session (prompts confirmation)
kugetsu destroy --all [-y] Delete all sessions (prompts confirmation)
kugetsu help Show this help
kugetsu start <session_id> <message> [--debug] Start a new session
kugetsu list [--all] List sessions (default: left only)
kugetsu resume <session_id> [message] [--debug] Resume a session
kugetsu stop <session_id> [--debug] Stop a session gracefully
kugetsu destroy <session_id> [-y] [--debug] Delete a session (prompts confirmation)
kugetsu destroy --all [-y] Delete all sessions (prompts confirmation)
kugetsu help Show this help
States:
used - Session is active (process running)
idle - Session ended gracefully (not resumable)
left - Session interrupted/crashed (resumable)
used - Session is active (process running)
idle - Session ended gracefully (not resumable)
left - Session interrupted/crashed (resumable)
invalid - Session data missing/corrupt
Options:
--debug Show real-time debug output and capture to debug.log
Examples:
kugetsu start mytask "fix bug #1"
kugetsu start mytask "fix bug #1" --debug
kugetsu list
kugetsu list --all
kugetsu resume mytask
kugetsu resume mytask "continue working"
kugetsu stop mytask
kugetsu destroy mytask
kugetsu resume mytask "continue working" --debug
kugetsu stop mytask --debug
kugetsu destroy mytask --debug
kugetsu destroy mytask -y
kugetsu destroy --all
kugetsu destroy --all -y
@@ -64,6 +68,37 @@ get_state() {
fi
}
DEBUG_MODE=false
set_debug_mode() {
DEBUG_MODE=false
local filtered_args=()
while [ $# -gt 0 ]; do
case "$1" in
--debug)
DEBUG_MODE=true
;;
*)
filtered_args+=("$1")
;;
esac
shift
done
echo "${filtered_args[@]}"
}
show_debug_log() {
local session_dir="$1"
local debug_log="$session_dir/debug.log"
if [ -f "$debug_log" ]; then
echo "=== Debug Log ==="
cat "$debug_log"
echo "=== End Debug Log ==="
else
echo "No debug log found"
fi
}
set_state() {
local session_dir="$1"
local state="$2"
@@ -100,13 +135,30 @@ check_and_update_state() {
}
cmd_start() {
if [ $# -lt 2 ]; then
local session_id=""
local message=""
while [ $# -gt 0 ]; do
case "$1" in
--debug)
DEBUG_MODE=true
;;
*)
if [ -z "$session_id" ]; then
session_id="$1"
elif [ -z "$message" ]; then
message="$1"
fi
;;
esac
shift
done
if [ -z "$session_id" ] || [ -z "$message" ]; then
echo "Error: start requires <session_id> and <message>" >&2
exit 1
fi
local session_id="$1"
local message="$2"
validate_session_id "$session_id"
local session_dir=$(get_session_dir "$session_id")
@@ -137,7 +189,11 @@ cmd_start() {
echo "$message" > "$session_dir/message"
echo "Starting session '$session_id'..."
opencode run --session "$session_id" "$message"
if [ "$DEBUG_MODE" = true ]; then
stdbuf -oL opencode run --print-logs --log-level DEBUG --session "$session_id" "$message" 2>&1 | tee "$session_dir/debug.log"
else
opencode run --session "$session_id" "$message"
fi
local exit_code=$?
if [ $exit_code -eq 0 ]; then
@@ -184,19 +240,32 @@ cmd_list() {
}
cmd_resume() {
if [ $# -lt 1 ]; then
local session_id=""
local message=""
local args=("$@")
for arg in "${args[@]}"; do
case "$arg" in
--debug)
DEBUG_MODE=true
;;
*)
if [ -z "$session_id" ]; then
session_id="$arg"
elif [ -z "$message" ]; then
message="$arg"
fi
;;
esac
done
if [ -z "$session_id" ]; then
echo "Error: resume requires <session_id>" >&2
exit 1
fi
local session_id="$1"
local message=""
validate_session_id "$session_id"
if [ $# -ge 2 ]; then
message="$2"
fi
local session_dir=$(get_session_dir "$session_id")
if [ ! -d "$session_dir" ]; then
@@ -251,7 +320,11 @@ cmd_resume() {
echo "$message" > "$session_dir/message"
echo "Resuming session '$session_id'..."
opencode run --continue --session "$session_id" "$message"
if [ "$DEBUG_MODE" = true ]; then
stdbuf -oL opencode run --print-logs --log-level DEBUG --continue --session "$session_id" "$message" 2>&1 | tee "$session_dir/debug.log"
else
opencode run --continue --session "$session_id" "$message"
fi
local exit_code=$?
if [ $exit_code -eq 0 ]; then
@@ -264,12 +337,27 @@ cmd_resume() {
}
cmd_stop() {
if [ $# -lt 1 ]; then
local session_id=""
while [ $# -gt 0 ]; do
case "$1" in
--debug)
DEBUG_MODE=true
;;
*)
if [ -z "$session_id" ]; then
session_id="$1"
fi
;;
esac
shift
done
if [ -z "$session_id" ]; then
echo "Error: stop requires <session_id>" >&2
exit 1
fi
local session_id="$1"
validate_session_id "$session_id"
local session_dir=$(get_session_dir "$session_id")
@@ -278,6 +366,10 @@ cmd_stop() {
exit 1
fi
if [ "$DEBUG_MODE" = true ]; then
show_debug_log "$session_dir"
fi
local state=$(get_state "$session_dir")
if [ "$state" != "used" ]; then
@@ -322,6 +414,9 @@ cmd_destroy() {
--all)
destroy_all=true
;;
--debug)
DEBUG_MODE=true
;;
-y|--yes)
force=true
;;
@@ -377,6 +472,10 @@ cmd_destroy() {
exit 1
fi
if [ "$DEBUG_MODE" = true ]; then
show_debug_log "$session_dir"
fi
local state=$(get_state "$session_dir")
if [ "$state" = "used" ]; then
echo "Error: session '$session_id' is in use (state=used)" >&2