@letta-ai/letta-code 0.28.17 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/types/types/protocol_v2.d.ts +10 -0
- package/dist/types/types/protocol_v2.d.ts.map +1 -1
- package/letta.js +27360 -40161
- package/package.json +3 -2
- package/scripts/source-file-size-baseline.json +17 -17
- package/skills/dispatching-coding-agents/SKILL.md +14 -20
- package/skills/initializing-memory/SKILL.md +91 -87
- package/skills/initializing-memory/scripts/detect-history.sh +0 -113
- package/skills/initializing-memory/scripts/list-sessions.sh +0 -87
- package/skills/initializing-memory/scripts/search-history.sh +0 -137
- package/skills/initializing-memory/scripts/view-session.sh +0 -110
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# List sessions for a project from Claude Code or Codex
|
|
3
|
-
# Usage: ./list-sessions.sh <claude|codex> [project-path]
|
|
4
|
-
|
|
5
|
-
set -e
|
|
6
|
-
|
|
7
|
-
SOURCE="${1:-claude}"
|
|
8
|
-
PROJECT_PATH="${2:-$(pwd)}"
|
|
9
|
-
|
|
10
|
-
if [[ "$SOURCE" == "claude" ]]; then
|
|
11
|
-
ENCODED=$(echo "$PROJECT_PATH" | sed 's|/|-|g')
|
|
12
|
-
PROJECT_DIR="$HOME/.claude/projects/$ENCODED"
|
|
13
|
-
|
|
14
|
-
echo "=== Claude Code Sessions ==="
|
|
15
|
-
echo "Project: $PROJECT_PATH"
|
|
16
|
-
echo ""
|
|
17
|
-
|
|
18
|
-
if [[ -d "$PROJECT_DIR" ]]; then
|
|
19
|
-
# Session files exist - use them
|
|
20
|
-
echo "Source: Session files"
|
|
21
|
-
echo ""
|
|
22
|
-
|
|
23
|
-
# Use sessions-index.json if available (faster)
|
|
24
|
-
if [[ -f "$PROJECT_DIR/sessions-index.json" ]]; then
|
|
25
|
-
jq -r '.entries | sort_by(.modified) | reverse | .[] | "\(.modified[0:19]) msgs:\(.messageCount|tostring|.[0:4]) \(.firstPrompt[0:70])..."' \
|
|
26
|
-
"$PROJECT_DIR/sessions-index.json"
|
|
27
|
-
else
|
|
28
|
-
# Fall back to parsing each file
|
|
29
|
-
for f in "$PROJECT_DIR"/*.jsonl; do
|
|
30
|
-
[[ -f "$f" ]] || continue
|
|
31
|
-
BASENAME=$(basename "$f")
|
|
32
|
-
FIRST_PROMPT=$(jq -r 'select(.type == "user") | .message.content | if type == "string" then . else .[0].text // .[0].content // "?" end' "$f" 2>/dev/null | head -1 | cut -c1-70)
|
|
33
|
-
MSG_COUNT=$(grep -c '"type"' "$f" 2>/dev/null || echo "?")
|
|
34
|
-
MTIME=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$f" 2>/dev/null || stat -c "%y" "$f" 2>/dev/null | cut -c1-16)
|
|
35
|
-
echo "$MTIME msgs:$MSG_COUNT $FIRST_PROMPT..."
|
|
36
|
-
echo " -> $BASENAME"
|
|
37
|
-
done
|
|
38
|
-
fi
|
|
39
|
-
else
|
|
40
|
-
# No session files - fall back to history.jsonl
|
|
41
|
-
echo "Source: history.jsonl (session files not found)"
|
|
42
|
-
echo "Note: Only prompts available, not full conversations"
|
|
43
|
-
echo ""
|
|
44
|
-
|
|
45
|
-
if [[ -f "$HOME/.claude/history.jsonl" ]]; then
|
|
46
|
-
MATCHES=$(jq -r --arg proj "$PROJECT_PATH" '
|
|
47
|
-
select(.project == $proj) |
|
|
48
|
-
"\(.timestamp / 1000 | strftime("%Y-%m-%d %H:%M")) \(.display[0:70])..."
|
|
49
|
-
' "$HOME/.claude/history.jsonl" 2>/dev/null)
|
|
50
|
-
|
|
51
|
-
if [[ -n "$MATCHES" ]]; then
|
|
52
|
-
echo "$MATCHES"
|
|
53
|
-
else
|
|
54
|
-
echo "No prompts found for this exact project path."
|
|
55
|
-
echo "Try searching with a partial match:"
|
|
56
|
-
echo " cat ~/.claude/history.jsonl | jq 'select(.project | contains(\"$(basename "$PROJECT_PATH")\"))'"
|
|
57
|
-
fi
|
|
58
|
-
else
|
|
59
|
-
echo "No history.jsonl found"
|
|
60
|
-
fi
|
|
61
|
-
fi
|
|
62
|
-
|
|
63
|
-
elif [[ "$SOURCE" == "codex" ]]; then
|
|
64
|
-
echo "=== Codex Sessions ==="
|
|
65
|
-
echo "Project: $PROJECT_PATH"
|
|
66
|
-
echo ""
|
|
67
|
-
|
|
68
|
-
FOUND=0
|
|
69
|
-
for f in $(find "$HOME/.codex/sessions" -name "*.jsonl" 2>/dev/null | sort -r); do
|
|
70
|
-
CWD=$(head -1 "$f" | jq -r '.payload.cwd // empty' 2>/dev/null)
|
|
71
|
-
if [[ "$CWD" == "$PROJECT_PATH"* ]]; then
|
|
72
|
-
((FOUND++)) || true
|
|
73
|
-
BASENAME=$(basename "$f")
|
|
74
|
-
FIRST_PROMPT=$(jq -r 'select(.type == "event_msg" and .payload.type == "user_message") | .payload.message' "$f" 2>/dev/null | head -1 | cut -c1-70)
|
|
75
|
-
TIMESTAMP=$(echo "$BASENAME" | sed 's/rollout-//' | cut -c1-19 | tr 'T' ' ')
|
|
76
|
-
echo "$TIMESTAMP $FIRST_PROMPT..."
|
|
77
|
-
echo " -> $f"
|
|
78
|
-
fi
|
|
79
|
-
done
|
|
80
|
-
|
|
81
|
-
if [[ $FOUND -eq 0 ]]; then
|
|
82
|
-
echo "No Codex sessions found for: $PROJECT_PATH"
|
|
83
|
-
fi
|
|
84
|
-
else
|
|
85
|
-
echo "Usage: ./list-sessions.sh <claude|codex> [project-path]"
|
|
86
|
-
exit 1
|
|
87
|
-
fi
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Search across Claude Code and Codex history
|
|
3
|
-
# Usage: ./search.sh <keyword> [--claude|--codex|--both] [--project path]
|
|
4
|
-
|
|
5
|
-
set -e
|
|
6
|
-
|
|
7
|
-
KEYWORD=""
|
|
8
|
-
SOURCE="both"
|
|
9
|
-
PROJECT_FILTER=""
|
|
10
|
-
|
|
11
|
-
# Parse arguments
|
|
12
|
-
while [[ $# -gt 0 ]]; do
|
|
13
|
-
case $1 in
|
|
14
|
-
--claude) SOURCE="claude"; shift ;;
|
|
15
|
-
--codex) SOURCE="codex"; shift ;;
|
|
16
|
-
--both) SOURCE="both"; shift ;;
|
|
17
|
-
--project) PROJECT_FILTER="$2"; shift 2 ;;
|
|
18
|
-
-*) echo "Unknown option: $1"; exit 1 ;;
|
|
19
|
-
*) KEYWORD="$1"; shift ;;
|
|
20
|
-
esac
|
|
21
|
-
done
|
|
22
|
-
|
|
23
|
-
if [[ -z "$KEYWORD" ]]; then
|
|
24
|
-
echo "Usage: ./search.sh <keyword> [--claude|--codex|--both] [--project path]"
|
|
25
|
-
echo ""
|
|
26
|
-
echo "Examples:"
|
|
27
|
-
echo " ./search.sh 'database migration'"
|
|
28
|
-
echo " ./search.sh 'test' --claude"
|
|
29
|
-
echo " ./search.sh 'auth' --project /path/to/project"
|
|
30
|
-
exit 1
|
|
31
|
-
fi
|
|
32
|
-
|
|
33
|
-
echo "=== Searching for: $KEYWORD ==="
|
|
34
|
-
echo ""
|
|
35
|
-
|
|
36
|
-
# Search Claude Code
|
|
37
|
-
if [[ "$SOURCE" == "claude" || "$SOURCE" == "both" ]] && [[ -d "$HOME/.claude" ]]; then
|
|
38
|
-
echo "--- Claude Code Results ---"
|
|
39
|
-
|
|
40
|
-
# Search global history (always available, even when session files are deleted)
|
|
41
|
-
if [[ -f "$HOME/.claude/history.jsonl" ]]; then
|
|
42
|
-
echo "Prompt history (history.jsonl):"
|
|
43
|
-
if [[ -n "$PROJECT_FILTER" ]]; then
|
|
44
|
-
RESULTS=$(jq -r --arg kw "$KEYWORD" --arg proj "$PROJECT_FILTER" '
|
|
45
|
-
select((.display | test($kw; "i")) and (.project | startswith($proj))) |
|
|
46
|
-
"\(.timestamp / 1000 | strftime("%Y-%m-%d %H:%M")) \(.display[0:80])..."
|
|
47
|
-
' "$HOME/.claude/history.jsonl" 2>/dev/null | head -30)
|
|
48
|
-
else
|
|
49
|
-
RESULTS=$(jq -r --arg kw "$KEYWORD" '
|
|
50
|
-
select(.display | test($kw; "i")) |
|
|
51
|
-
"\(.timestamp / 1000 | strftime("%Y-%m-%d %H:%M")) \(.project | split("/") | .[-1]): \(.display[0:70])..."
|
|
52
|
-
' "$HOME/.claude/history.jsonl" 2>/dev/null | head -30)
|
|
53
|
-
fi
|
|
54
|
-
if [[ -n "$RESULTS" ]]; then
|
|
55
|
-
echo "$RESULTS"
|
|
56
|
-
else
|
|
57
|
-
echo " No matches in prompt history"
|
|
58
|
-
fi
|
|
59
|
-
echo ""
|
|
60
|
-
fi
|
|
61
|
-
|
|
62
|
-
# Search session files
|
|
63
|
-
echo ""
|
|
64
|
-
echo "Session matches:"
|
|
65
|
-
for PROJECT_DIR in "$HOME/.claude/projects"/*; do
|
|
66
|
-
[[ -d "$PROJECT_DIR" ]] || continue
|
|
67
|
-
|
|
68
|
-
# Apply project filter if specified
|
|
69
|
-
if [[ -n "$PROJECT_FILTER" ]]; then
|
|
70
|
-
DECODED=$(basename "$PROJECT_DIR" | sed 's/-/\//g')
|
|
71
|
-
[[ "$DECODED" == "$PROJECT_FILTER"* ]] || continue
|
|
72
|
-
fi
|
|
73
|
-
|
|
74
|
-
for f in "$PROJECT_DIR"/*.jsonl; do
|
|
75
|
-
[[ -f "$f" ]] || continue
|
|
76
|
-
[[ "$(basename "$f")" == "sessions-index.json" ]] && continue
|
|
77
|
-
|
|
78
|
-
# Search user messages (string content only)
|
|
79
|
-
MATCHES=$(jq -r --arg kw "$KEYWORD" '
|
|
80
|
-
select(.type == "user" and (.message.content | type == "string")) |
|
|
81
|
-
.message.content |
|
|
82
|
-
select(test($kw; "i"))
|
|
83
|
-
' "$f" 2>/dev/null | head -3)
|
|
84
|
-
|
|
85
|
-
if [[ -n "$MATCHES" ]]; then
|
|
86
|
-
PROJECT_NAME=$(basename "$PROJECT_DIR" | sed 's/-/\//g' | rev | cut -c1-50 | rev)
|
|
87
|
-
echo ""
|
|
88
|
-
echo " Project: ...$PROJECT_NAME"
|
|
89
|
-
echo " Session: $(basename "$f")"
|
|
90
|
-
echo "$MATCHES" | while read -r line; do
|
|
91
|
-
echo " > ${line:0:80}..."
|
|
92
|
-
done
|
|
93
|
-
fi
|
|
94
|
-
done
|
|
95
|
-
done
|
|
96
|
-
echo ""
|
|
97
|
-
fi
|
|
98
|
-
|
|
99
|
-
# Search Codex
|
|
100
|
-
if [[ "$SOURCE" == "codex" || "$SOURCE" == "both" ]] && [[ -d "$HOME/.codex" ]]; then
|
|
101
|
-
echo "--- Codex Results ---"
|
|
102
|
-
|
|
103
|
-
# Search global history
|
|
104
|
-
if [[ -f "$HOME/.codex/history.jsonl" ]]; then
|
|
105
|
-
RESULTS=$(jq -r --arg kw "$KEYWORD" 'select(.text | test($kw; "i")) | "\(.ts | strftime("%Y-%m-%d %H:%M")) \(.text[0:100])...\n"' "$HOME/.codex/history.jsonl" 2>/dev/null | head -20)
|
|
106
|
-
if [[ -n "$RESULTS" ]]; then
|
|
107
|
-
echo "Global history matches:"
|
|
108
|
-
echo "$RESULTS"
|
|
109
|
-
fi
|
|
110
|
-
fi
|
|
111
|
-
|
|
112
|
-
# Search session files
|
|
113
|
-
echo "Session matches:"
|
|
114
|
-
for f in $(find "$HOME/.codex/sessions" -name "*.jsonl" 2>/dev/null); do
|
|
115
|
-
# Apply project filter if specified
|
|
116
|
-
if [[ -n "$PROJECT_FILTER" ]]; then
|
|
117
|
-
CWD=$(head -1 "$f" | jq -r '.payload.cwd // empty' 2>/dev/null)
|
|
118
|
-
[[ "$CWD" == "$PROJECT_FILTER"* ]] || continue
|
|
119
|
-
fi
|
|
120
|
-
|
|
121
|
-
MATCHES=$(jq -r --arg kw "$KEYWORD" '
|
|
122
|
-
select(.type == "event_msg" and .payload.type == "user_message") |
|
|
123
|
-
.payload.message |
|
|
124
|
-
select(test($kw; "i"))
|
|
125
|
-
' "$f" 2>/dev/null | head -3)
|
|
126
|
-
|
|
127
|
-
if [[ -n "$MATCHES" ]]; then
|
|
128
|
-
echo ""
|
|
129
|
-
echo " File: $(basename "$f")"
|
|
130
|
-
CWD=$(head -1 "$f" | jq -r '.payload.cwd // "?"' 2>/dev/null)
|
|
131
|
-
echo " Project: $CWD"
|
|
132
|
-
echo "$MATCHES" | while read -r line; do
|
|
133
|
-
echo " ${line:0:100}..."
|
|
134
|
-
done
|
|
135
|
-
fi
|
|
136
|
-
done
|
|
137
|
-
fi
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# View a session file in readable format
|
|
3
|
-
# Usage: ./view-session.sh <session-file> [--tools] [--thinking]
|
|
4
|
-
|
|
5
|
-
set -e
|
|
6
|
-
|
|
7
|
-
SESSION_FILE="$1"
|
|
8
|
-
SHOW_TOOLS=false
|
|
9
|
-
SHOW_THINKING=false
|
|
10
|
-
|
|
11
|
-
# Parse flags
|
|
12
|
-
shift || true
|
|
13
|
-
while [[ $# -gt 0 ]]; do
|
|
14
|
-
case $1 in
|
|
15
|
-
--tools) SHOW_TOOLS=true; shift ;;
|
|
16
|
-
--thinking) SHOW_THINKING=true; shift ;;
|
|
17
|
-
*) shift ;;
|
|
18
|
-
esac
|
|
19
|
-
done
|
|
20
|
-
|
|
21
|
-
if [[ -z "$SESSION_FILE" || ! -f "$SESSION_FILE" ]]; then
|
|
22
|
-
echo "Usage: ./view-session.sh <session-file> [--tools] [--thinking]"
|
|
23
|
-
echo ""
|
|
24
|
-
echo "Options:"
|
|
25
|
-
echo " --tools Show tool calls and results"
|
|
26
|
-
echo " --thinking Show assistant thinking/reasoning"
|
|
27
|
-
exit 1
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
# Detect format (Claude vs Codex)
|
|
31
|
-
FIRST_LINE=$(head -1 "$SESSION_FILE")
|
|
32
|
-
if echo "$FIRST_LINE" | jq -e '.type == "session_meta"' > /dev/null 2>&1; then
|
|
33
|
-
FORMAT="codex"
|
|
34
|
-
elif echo "$FIRST_LINE" | jq -e '.type' > /dev/null 2>&1; then
|
|
35
|
-
FORMAT="claude"
|
|
36
|
-
else
|
|
37
|
-
echo "Unknown session format"
|
|
38
|
-
exit 1
|
|
39
|
-
fi
|
|
40
|
-
|
|
41
|
-
echo "=== Session Viewer ==="
|
|
42
|
-
echo "File: $SESSION_FILE"
|
|
43
|
-
echo "Format: $FORMAT"
|
|
44
|
-
echo ""
|
|
45
|
-
|
|
46
|
-
if [[ "$FORMAT" == "claude" ]]; then
|
|
47
|
-
# Claude format
|
|
48
|
-
jq -r --argjson tools "$SHOW_TOOLS" --argjson thinking "$SHOW_THINKING" '
|
|
49
|
-
if .type == "user" then
|
|
50
|
-
.message.content |
|
|
51
|
-
if type == "string" then
|
|
52
|
-
">>> USER:\n\(.)\n"
|
|
53
|
-
elif .[0].type == "tool_result" then
|
|
54
|
-
if $tools then
|
|
55
|
-
">>> TOOL RESULT (\(.[0].tool_use_id[0:20])):\n\(.[0].content[0:500])...\n"
|
|
56
|
-
else
|
|
57
|
-
empty
|
|
58
|
-
end
|
|
59
|
-
else
|
|
60
|
-
">>> USER:\n\(.[0].text // .[0].content // "?")\n"
|
|
61
|
-
end
|
|
62
|
-
elif .type == "assistant" then
|
|
63
|
-
.message.content | map(
|
|
64
|
-
if .type == "text" then
|
|
65
|
-
"<<< ASSISTANT:\n\(.text)\n"
|
|
66
|
-
elif .type == "thinking" and $thinking then
|
|
67
|
-
"<<< THINKING:\n\(.thinking[0:300])...\n"
|
|
68
|
-
elif .type == "tool_use" and $tools then
|
|
69
|
-
"<<< TOOL: \(.name)\n\(.input | tostring[0:200])...\n"
|
|
70
|
-
else
|
|
71
|
-
empty
|
|
72
|
-
end
|
|
73
|
-
) | join("\n")
|
|
74
|
-
elif .type == "summary" then
|
|
75
|
-
"=== SUMMARY: \(.summary) ===\n"
|
|
76
|
-
else
|
|
77
|
-
empty
|
|
78
|
-
end
|
|
79
|
-
' "$SESSION_FILE"
|
|
80
|
-
|
|
81
|
-
elif [[ "$FORMAT" == "codex" ]]; then
|
|
82
|
-
# Codex format
|
|
83
|
-
|
|
84
|
-
# Show session metadata
|
|
85
|
-
jq -r 'select(.type == "session_meta") | "Project: \(.payload.cwd)\nModel: \(.payload.model_provider // "?")\nBranch: \(.payload.git.branch // "?")\n"' "$SESSION_FILE" | head -5
|
|
86
|
-
echo "---"
|
|
87
|
-
echo ""
|
|
88
|
-
|
|
89
|
-
jq -r --argjson tools "$SHOW_TOOLS" --argjson thinking "$SHOW_THINKING" '
|
|
90
|
-
if .type == "event_msg" and .payload.type == "user_message" then
|
|
91
|
-
">>> USER:\n\(.payload.message)\n"
|
|
92
|
-
elif .type == "response_item" and .payload.type == "message" and .payload.role == "assistant" then
|
|
93
|
-
.payload.content | map(
|
|
94
|
-
if .type == "output_text" then
|
|
95
|
-
"<<< ASSISTANT:\n\(.text)\n"
|
|
96
|
-
else
|
|
97
|
-
empty
|
|
98
|
-
end
|
|
99
|
-
) | join("\n")
|
|
100
|
-
elif .type == "event_msg" and .payload.type == "agent_reasoning" and $thinking then
|
|
101
|
-
"<<< THINKING:\n\(.payload.text[0:300])...\n"
|
|
102
|
-
elif .type == "response_item" and .payload.type == "function_call" and $tools then
|
|
103
|
-
"<<< TOOL: \(.payload.name)\n\(.payload.arguments[0:200])...\n"
|
|
104
|
-
elif .type == "response_item" and .payload.type == "function_call_output" and $tools then
|
|
105
|
-
">>> TOOL RESULT:\n\(.payload.output[0:500])...\n"
|
|
106
|
-
else
|
|
107
|
-
empty
|
|
108
|
-
end
|
|
109
|
-
' "$SESSION_FILE"
|
|
110
|
-
fi
|