mitsupi 1.0.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.
Files changed (77) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +95 -0
  3. package/TODO.md +11 -0
  4. package/commands/handoff.md +100 -0
  5. package/commands/make-release.md +75 -0
  6. package/commands/pickup.md +30 -0
  7. package/commands/update-changelog.md +78 -0
  8. package/package.json +22 -0
  9. package/pi-extensions/answer.ts +527 -0
  10. package/pi-extensions/codex-tuning.ts +632 -0
  11. package/pi-extensions/commit.ts +248 -0
  12. package/pi-extensions/cwd-history.ts +237 -0
  13. package/pi-extensions/issues.ts +548 -0
  14. package/pi-extensions/loop.ts +446 -0
  15. package/pi-extensions/qna.ts +167 -0
  16. package/pi-extensions/reveal.ts +689 -0
  17. package/pi-extensions/review.ts +807 -0
  18. package/pi-themes/armin.json +81 -0
  19. package/pi-themes/nightowl.json +82 -0
  20. package/skills/anachb/SKILL.md +183 -0
  21. package/skills/anachb/departures.sh +79 -0
  22. package/skills/anachb/disruptions.sh +53 -0
  23. package/skills/anachb/route.sh +87 -0
  24. package/skills/anachb/search.sh +43 -0
  25. package/skills/ghidra/SKILL.md +254 -0
  26. package/skills/ghidra/scripts/find-ghidra.sh +54 -0
  27. package/skills/ghidra/scripts/ghidra-analyze.sh +239 -0
  28. package/skills/ghidra/scripts/ghidra_scripts/ExportAll.java +278 -0
  29. package/skills/ghidra/scripts/ghidra_scripts/ExportCalls.java +148 -0
  30. package/skills/ghidra/scripts/ghidra_scripts/ExportDecompiled.java +84 -0
  31. package/skills/ghidra/scripts/ghidra_scripts/ExportFunctions.java +114 -0
  32. package/skills/ghidra/scripts/ghidra_scripts/ExportStrings.java +123 -0
  33. package/skills/ghidra/scripts/ghidra_scripts/ExportSymbols.java +135 -0
  34. package/skills/github/SKILL.md +47 -0
  35. package/skills/improve-skill/SKILL.md +155 -0
  36. package/skills/improve-skill/scripts/extract-session.js +349 -0
  37. package/skills/oebb-scotty/SKILL.md +429 -0
  38. package/skills/oebb-scotty/arrivals.sh +83 -0
  39. package/skills/oebb-scotty/departures.sh +83 -0
  40. package/skills/oebb-scotty/disruptions.sh +33 -0
  41. package/skills/oebb-scotty/search-station.sh +36 -0
  42. package/skills/oebb-scotty/trip.sh +119 -0
  43. package/skills/openscad/SKILL.md +232 -0
  44. package/skills/openscad/examples/parametric_box.scad +92 -0
  45. package/skills/openscad/examples/phone_stand.scad +95 -0
  46. package/skills/openscad/tools/common.sh +50 -0
  47. package/skills/openscad/tools/export-stl.sh +56 -0
  48. package/skills/openscad/tools/extract-params.sh +147 -0
  49. package/skills/openscad/tools/multi-preview.sh +68 -0
  50. package/skills/openscad/tools/preview.sh +74 -0
  51. package/skills/openscad/tools/render-with-params.sh +91 -0
  52. package/skills/openscad/tools/validate.sh +46 -0
  53. package/skills/pi-share/SKILL.md +105 -0
  54. package/skills/pi-share/fetch-session.mjs +322 -0
  55. package/skills/sentry/SKILL.md +239 -0
  56. package/skills/sentry/lib/auth.js +99 -0
  57. package/skills/sentry/scripts/fetch-event.js +329 -0
  58. package/skills/sentry/scripts/fetch-issue.js +356 -0
  59. package/skills/sentry/scripts/list-issues.js +239 -0
  60. package/skills/sentry/scripts/search-events.js +291 -0
  61. package/skills/sentry/scripts/search-logs.js +240 -0
  62. package/skills/tmux/SKILL.md +105 -0
  63. package/skills/tmux/scripts/find-sessions.sh +112 -0
  64. package/skills/tmux/scripts/wait-for-text.sh +83 -0
  65. package/skills/web-browser/SKILL.md +91 -0
  66. package/skills/web-browser/scripts/cdp.js +210 -0
  67. package/skills/web-browser/scripts/dismiss-cookies.js +373 -0
  68. package/skills/web-browser/scripts/eval.js +68 -0
  69. package/skills/web-browser/scripts/logs-tail.js +69 -0
  70. package/skills/web-browser/scripts/nav.js +65 -0
  71. package/skills/web-browser/scripts/net-summary.js +94 -0
  72. package/skills/web-browser/scripts/package-lock.json +33 -0
  73. package/skills/web-browser/scripts/package.json +6 -0
  74. package/skills/web-browser/scripts/pick.js +165 -0
  75. package/skills/web-browser/scripts/screenshot.js +52 -0
  76. package/skills/web-browser/scripts/start.js +80 -0
  77. package/skills/web-browser/scripts/watch.js +266 -0
@@ -0,0 +1,147 @@
1
+ #!/bin/bash
2
+ # Extract customizable parameters from an OpenSCAD file
3
+ # Usage: extract-params.sh input.scad [--json]
4
+ #
5
+ # Parses parameter declarations with special comments:
6
+ # param = value; // [min:max] Description
7
+ # param = value; // [min:step:max] Description
8
+ # param = value; // [opt1, opt2] Description
9
+ # param = value; // Description only
10
+
11
+ set -e
12
+
13
+ if [ $# -lt 1 ]; then
14
+ echo "Usage: $0 input.scad [--json]"
15
+ exit 1
16
+ fi
17
+
18
+ INPUT="$1"
19
+ JSON_OUTPUT=false
20
+
21
+ if [ "$2" = "--json" ]; then
22
+ JSON_OUTPUT=true
23
+ fi
24
+
25
+ if [ ! -f "$INPUT" ]; then
26
+ echo "Error: File not found: $INPUT"
27
+ exit 1
28
+ fi
29
+
30
+ # Extract parameters using Python for better parsing
31
+ extract_params() {
32
+ python3 -c '
33
+ import sys
34
+ import re
35
+
36
+ filename = sys.argv[1]
37
+ in_block = 0
38
+
39
+ with open(filename, "r") as f:
40
+ for line in f:
41
+ # Track block depth (skip params inside modules/functions)
42
+ in_block += line.count("{") - line.count("}")
43
+ if in_block > 0:
44
+ continue
45
+
46
+ # Match: varname = value; // comment
47
+ match = re.match(r"^\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*([^;]+);\s*(?://\s*(.*))?", line)
48
+ if not match:
49
+ continue
50
+
51
+ var_name = match.group(1)
52
+ value = match.group(2).strip()
53
+ comment = match.group(3) or ""
54
+
55
+ # Determine type
56
+ if value in ("true", "false"):
57
+ var_type = "boolean"
58
+ elif re.match(r"^-?\d+$", value):
59
+ var_type = "integer"
60
+ elif re.match(r"^-?\d*\.?\d+$", value):
61
+ var_type = "number"
62
+ elif value.startswith("\"") and value.endswith("\""):
63
+ var_type = "string"
64
+ value = value[1:-1] # Remove quotes
65
+ elif value.startswith("["):
66
+ var_type = "array"
67
+ else:
68
+ var_type = "expression"
69
+
70
+ # Parse comment for range/options
71
+ range_val = ""
72
+ options_val = ""
73
+ description = comment
74
+
75
+ range_match = re.match(r"\[([^\]]+)\]\s*(.*)", comment)
76
+ if range_match:
77
+ bracket_content = range_match.group(1)
78
+ description = range_match.group(2)
79
+
80
+ # Check if numeric range (contains :) or options (contains ,)
81
+ if ":" in bracket_content and not "," in bracket_content:
82
+ range_val = bracket_content
83
+ else:
84
+ options_val = bracket_content
85
+
86
+ # Output pipe-delimited
87
+ print(f"{var_name}|{value}|{var_type}|{range_val}|{options_val}|{description}")
88
+ ' "$INPUT"
89
+ }
90
+
91
+ if [ "$JSON_OUTPUT" = true ]; then
92
+ echo "["
93
+ first=true
94
+ while IFS='|' read -r name value type range options description; do
95
+ if [ "$first" = true ]; then
96
+ first=false
97
+ else
98
+ echo ","
99
+ fi
100
+
101
+ # Escape quotes in values
102
+ value=$(echo "$value" | sed 's/"/\\"/g')
103
+ description=$(echo "$description" | sed 's/"/\\"/g')
104
+
105
+ # Build JSON object
106
+ printf ' {\n'
107
+ printf ' "name": "%s",\n' "$name"
108
+ printf ' "value": "%s",\n' "$value"
109
+ printf ' "type": "%s"' "$type"
110
+
111
+ if [ -n "$range" ]; then
112
+ printf ',\n "range": "%s"' "$range"
113
+ fi
114
+ if [ -n "$options" ]; then
115
+ printf ',\n "options": "%s"' "$options"
116
+ fi
117
+ if [ -n "$description" ]; then
118
+ printf ',\n "description": "%s"' "$description"
119
+ fi
120
+ printf '\n }'
121
+ done < <(extract_params)
122
+ echo ""
123
+ echo "]"
124
+ else
125
+ echo "Parameters in: $INPUT"
126
+ echo "==============================================="
127
+ printf "%-20s %-15s %-10s %s\n" "NAME" "VALUE" "TYPE" "CONSTRAINT/DESC"
128
+ echo "-----------------------------------------------"
129
+
130
+ while IFS='|' read -r name value type range options description; do
131
+ constraint=""
132
+ if [ -n "$range" ]; then
133
+ constraint="[$range]"
134
+ elif [ -n "$options" ]; then
135
+ constraint="[$options]"
136
+ fi
137
+ if [ -n "$description" ]; then
138
+ if [ -n "$constraint" ]; then
139
+ constraint="$constraint $description"
140
+ else
141
+ constraint="$description"
142
+ fi
143
+ fi
144
+
145
+ printf "%-20s %-15s %-10s %s\n" "$name" "$value" "$type" "$constraint"
146
+ done < <(extract_params)
147
+ fi
@@ -0,0 +1,68 @@
1
+ #!/bin/bash
2
+ # Generate preview images from multiple angles
3
+ # Usage: multi-preview.sh input.scad output_dir/ [-D 'var=value']
4
+
5
+ set -e
6
+
7
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8
+ source "$SCRIPT_DIR/common.sh"
9
+
10
+ check_openscad
11
+
12
+ if [ $# -lt 2 ]; then
13
+ echo "Usage: $0 input.scad output_dir/ [-D 'var=value' ...]"
14
+ exit 1
15
+ fi
16
+
17
+ INPUT="$1"
18
+ OUTPUT_DIR="$2"
19
+ shift 2
20
+
21
+ # Collect -D parameters
22
+ DEFINES=()
23
+ while [ $# -gt 0 ]; do
24
+ case "$1" in
25
+ -D)
26
+ shift
27
+ DEFINES+=("-D" "$1")
28
+ ;;
29
+ esac
30
+ shift
31
+ done
32
+
33
+ mkdir -p "$OUTPUT_DIR"
34
+
35
+ # Get base name without extension
36
+ BASENAME=$(basename "$INPUT" .scad)
37
+
38
+ echo "Generating multi-angle previews for: $INPUT"
39
+ echo "Output directory: $OUTPUT_DIR"
40
+ echo ""
41
+
42
+ # Define angles as name:camera pairs
43
+ # Camera format: translate_x,translate_y,translate_z,rot_x,rot_y,rot_z,distance
44
+ ANGLES="iso:0,0,0,55,0,25,0
45
+ front:0,0,0,90,0,0,0
46
+ back:0,0,0,90,0,180,0
47
+ left:0,0,0,90,0,90,0
48
+ right:0,0,0,90,0,-90,0
49
+ top:0,0,0,0,0,0,0"
50
+
51
+ echo "$ANGLES" | while IFS=: read -r angle camera; do
52
+ output="$OUTPUT_DIR/${BASENAME}_${angle}.png"
53
+
54
+ echo " Rendering $angle view..."
55
+ $OPENSCAD \
56
+ --camera="$camera" \
57
+ --imgsize="800,600" \
58
+ --colorscheme="Tomorrow Night" \
59
+ --autocenter \
60
+ --viewall \
61
+ "${DEFINES[@]}" \
62
+ -o "$output" \
63
+ "$INPUT" 2>/dev/null
64
+ done
65
+
66
+ echo ""
67
+ echo "Generated previews:"
68
+ ls -la "$OUTPUT_DIR"/${BASENAME}_*.png
@@ -0,0 +1,74 @@
1
+ #!/bin/bash
2
+ # Generate a preview PNG from an OpenSCAD file
3
+ # Usage: preview.sh input.scad output.png [options]
4
+ #
5
+ # Options:
6
+ # --camera=x,y,z,rx,ry,rz,dist Camera position
7
+ # --size=WxH Image size (default: 800x600)
8
+ # -D 'var=value' Set parameter value
9
+
10
+ set -e
11
+
12
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
13
+ source "$SCRIPT_DIR/common.sh"
14
+
15
+ check_openscad
16
+
17
+ if [ $# -lt 2 ]; then
18
+ echo "Usage: $0 input.scad output.png [--camera=...] [--size=WxH] [-D 'var=val']"
19
+ echo ""
20
+ echo "Camera format: x,y,z,rotx,roty,rotz,distance"
21
+ echo "Common cameras:"
22
+ echo " Isometric: --camera=0,0,0,55,0,25,200"
23
+ echo " Front: --camera=0,0,0,90,0,0,200"
24
+ echo " Top: --camera=0,0,0,0,0,0,200"
25
+ exit 1
26
+ fi
27
+
28
+ INPUT="$1"
29
+ OUTPUT="$2"
30
+ shift 2
31
+
32
+ # Defaults
33
+ CAMERA="0,0,0,55,0,25,0"
34
+ SIZE="800,600"
35
+ DEFINES=()
36
+
37
+ # Parse options
38
+ while [ $# -gt 0 ]; do
39
+ case "$1" in
40
+ --camera=*)
41
+ CAMERA="${1#--camera=}"
42
+ ;;
43
+ --size=*)
44
+ SIZE="${1#--size=}"
45
+ SIZE="${SIZE/x/,}"
46
+ ;;
47
+ -D)
48
+ shift
49
+ DEFINES+=("-D" "$1")
50
+ ;;
51
+ *)
52
+ echo "Unknown option: $1"
53
+ exit 1
54
+ ;;
55
+ esac
56
+ shift
57
+ done
58
+
59
+ # Ensure output directory exists
60
+ mkdir -p "$(dirname "$OUTPUT")"
61
+
62
+ # Run OpenSCAD
63
+ echo "Rendering preview: $INPUT -> $OUTPUT"
64
+ $OPENSCAD \
65
+ --camera="$CAMERA" \
66
+ --imgsize="${SIZE}" \
67
+ --colorscheme="Tomorrow Night" \
68
+ --autocenter \
69
+ --viewall \
70
+ "${DEFINES[@]}" \
71
+ -o "$OUTPUT" \
72
+ "$INPUT"
73
+
74
+ echo "Preview saved to: $OUTPUT"
@@ -0,0 +1,91 @@
1
+ #!/bin/bash
2
+ # Render OpenSCAD with parameters from a JSON file
3
+ # Usage: render-with-params.sh input.scad params.json output.stl|output.png
4
+
5
+ set -e
6
+
7
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8
+ source "$SCRIPT_DIR/common.sh"
9
+
10
+ check_openscad
11
+
12
+ if [ $# -lt 3 ]; then
13
+ echo "Usage: $0 input.scad params.json output.[stl|png]"
14
+ echo ""
15
+ echo "params.json format:"
16
+ echo ' {"width": 60, "height": 40, "include_lid": true}'
17
+ exit 1
18
+ fi
19
+
20
+ INPUT="$1"
21
+ PARAMS_FILE="$2"
22
+ OUTPUT="$3"
23
+
24
+ if [ ! -f "$INPUT" ]; then
25
+ echo "Error: Input file not found: $INPUT"
26
+ exit 1
27
+ fi
28
+
29
+ if [ ! -f "$PARAMS_FILE" ]; then
30
+ echo "Error: Params file not found: $PARAMS_FILE"
31
+ exit 1
32
+ fi
33
+
34
+ # Build -D arguments from JSON
35
+ DEFINES=()
36
+ while IFS= read -r line; do
37
+ # Parse each key-value pair
38
+ key=$(echo "$line" | cut -d'=' -f1)
39
+ value=$(echo "$line" | cut -d'=' -f2-)
40
+
41
+ if [ -n "$key" ]; then
42
+ DEFINES+=("-D" "$key=$value")
43
+ fi
44
+ done < <(
45
+ # Use python or jq to parse JSON to key=value lines
46
+ if command -v python3 &> /dev/null; then
47
+ python3 -c "
48
+ import json
49
+ with open('$PARAMS_FILE') as f:
50
+ params = json.load(f)
51
+ for k, v in params.items():
52
+ if isinstance(v, bool):
53
+ print(f'{k}={str(v).lower()}')
54
+ elif isinstance(v, str):
55
+ print(f'{k}=\"{v}\"')
56
+ else:
57
+ print(f'{k}={v}')
58
+ "
59
+ elif command -v jq &> /dev/null; then
60
+ jq -r 'to_entries | .[] | "\(.key)=\(.value)"' "$PARAMS_FILE"
61
+ else
62
+ echo "Error: Requires python3 or jq to parse JSON"
63
+ exit 1
64
+ fi
65
+ )
66
+
67
+ echo "Rendering with parameters from: $PARAMS_FILE"
68
+ echo "Parameters: ${DEFINES[*]}"
69
+
70
+ # Determine output type and set appropriate options
71
+ EXT="${OUTPUT##*.}"
72
+ case "$EXT" in
73
+ stl|STL)
74
+ $OPENSCAD "${DEFINES[@]}" -o "$OUTPUT" "$INPUT"
75
+ ;;
76
+ png|PNG)
77
+ $OPENSCAD "${DEFINES[@]}" \
78
+ --camera="0,0,0,55,0,25,0" \
79
+ --imgsize="800,600" \
80
+ --colorscheme="Tomorrow Night" \
81
+ --autocenter --viewall \
82
+ -o "$OUTPUT" "$INPUT"
83
+ ;;
84
+ *)
85
+ echo "Unsupported output format: $EXT"
86
+ echo "Supported: stl, png"
87
+ exit 1
88
+ ;;
89
+ esac
90
+
91
+ echo "Output saved: $OUTPUT"
@@ -0,0 +1,46 @@
1
+ #!/bin/bash
2
+ # Validate an OpenSCAD file for syntax errors
3
+ # Usage: validate.sh input.scad
4
+
5
+ set -e
6
+
7
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8
+ source "$SCRIPT_DIR/common.sh"
9
+
10
+ check_openscad
11
+
12
+ if [ $# -lt 1 ]; then
13
+ echo "Usage: $0 input.scad"
14
+ exit 1
15
+ fi
16
+
17
+ INPUT="$1"
18
+
19
+ if [ ! -f "$INPUT" ]; then
20
+ echo "Error: File not found: $INPUT"
21
+ exit 1
22
+ fi
23
+
24
+ echo "Validating: $INPUT"
25
+
26
+ # Create temp file for output
27
+ TEMP_OUTPUT=$(mktemp /tmp/openscad_validate.XXXXXX.echo)
28
+ trap "rm -f $TEMP_OUTPUT" EXIT
29
+
30
+ # Run OpenSCAD with echo output (fastest way to check syntax)
31
+ # Using --export-format=echo just parses and evaluates without rendering
32
+ if $OPENSCAD -o "$TEMP_OUTPUT" --export-format=echo "$INPUT" 2>&1; then
33
+ echo "✓ Syntax OK"
34
+
35
+ # Check for warnings in stderr
36
+ if [ -s "$TEMP_OUTPUT" ]; then
37
+ echo ""
38
+ echo "Echo output:"
39
+ cat "$TEMP_OUTPUT"
40
+ fi
41
+
42
+ exit 0
43
+ else
44
+ echo "✗ Validation failed"
45
+ exit 1
46
+ fi
@@ -0,0 +1,105 @@
1
+ ---
2
+ name: pi-share
3
+ description: "Load and parse session transcripts from shittycodingagent.ai/buildwithpi.ai/buildwithpi.com (pi-share) URLs. Fetches gists, decodes embedded session data, and extracts conversation history."
4
+ ---
5
+
6
+ # pi-share / buildwithpi Session Loader
7
+
8
+ Load and parse session transcripts from pi-share URLs (shittycodingagent.ai, buildwithpi.ai, buildwithpi.com).
9
+
10
+ ## When to Use
11
+
12
+ **Loading sessions:** Use this skill when the user provides a URL like:
13
+ - `https://shittycodingagent.ai/session/?<gist_id>`
14
+ - `https://buildwithpi.ai/session/?<gist_id>`
15
+ - `https://buildwithpi.com/session/?<gist_id>`
16
+ - Or just a gist ID like `46aee35206aefe99257bc5d5e60c6121`
17
+
18
+ **Human summaries:** Use `--human-summary` when the user asks you to:
19
+ - Summarize what a human did in a pi/coding agent session
20
+ - Understand how a user interacted with an agent
21
+ - Analyze user behavior, steering patterns, or prompting style
22
+ - Get a human-centric view of a session (not what the agent did, but what the human did)
23
+
24
+ The human summary focuses on: initial goals, re-prompts, steering/corrections, interventions, and overall prompting style.
25
+
26
+ ## How It Works
27
+
28
+ 1. Session exports are stored as GitHub Gists
29
+ 2. The URL contains a gist ID after the `?`
30
+ 3. The gist contains a `session.html` file with base64-encoded session data
31
+ 4. The helper script fetches and decodes this to extract the full conversation
32
+
33
+ ## Usage
34
+
35
+ ```bash
36
+ # Get full session data (default)
37
+ node ~/.pi/agent/skills/pi-share/fetch-session.mjs "<url-or-gist-id>"
38
+
39
+ # Get just the header
40
+ node ~/.pi/agent/skills/pi-share/fetch-session.mjs <gist-id> --header
41
+
42
+ # Get entries as JSON lines (one entry per line)
43
+ node ~/.pi/agent/skills/pi-share/fetch-session.mjs <gist-id> --entries
44
+
45
+ # Get the system prompt
46
+ node ~/.pi/agent/skills/pi-share/fetch-session.mjs <gist-id> --system
47
+
48
+ # Get tool definitions
49
+ node ~/.pi/agent/skills/pi-share/fetch-session.mjs <gist-id> --tools
50
+
51
+ # Get human-centric summary (what did the human do in this session?)
52
+ node ~/.pi/agent/skills/pi-share/fetch-session.mjs <gist-id> --human-summary
53
+ ```
54
+
55
+ ## Human Summary
56
+
57
+ The `--human-summary` flag generates a ~300 word summary focused on the human's experience:
58
+ - What was their initial goal?
59
+ - How often did they re-prompt or steer the agent?
60
+ - What kind of interventions did they make? (corrections, clarifications, frustration)
61
+ - How specific or vague were their instructions?
62
+
63
+ This uses claude-haiku-4-5 via `pi -p` to analyze the condensed session transcript.
64
+
65
+ ## Session Data Structure
66
+
67
+ The decoded session contains:
68
+
69
+ ```typescript
70
+ interface SessionData {
71
+ header: {
72
+ type: "session";
73
+ version: number;
74
+ id: string; // Session UUID
75
+ timestamp: string; // ISO timestamp
76
+ cwd: string; // Working directory
77
+ };
78
+ entries: SessionEntry[]; // Conversation entries (JSON lines format)
79
+ leafId: string | null; // Current branch leaf
80
+ systemPrompt?: string; // System prompt text
81
+ tools?: { name: string; description: string }[];
82
+ }
83
+ ```
84
+
85
+ Entry types include:
86
+ - `message` - User/assistant/toolResult messages with content blocks
87
+ - `model_change` - Model switches
88
+ - `thinking_level_change` - Thinking mode changes
89
+ - `compaction` - Context compaction events
90
+
91
+ Message content block types:
92
+ - `text` - Text content
93
+ - `toolCall` - Tool invocation with `toolName` and `args`
94
+ - `thinking` - Model thinking content
95
+ - `image` - Embedded images
96
+
97
+ ## Example: Analyze a Session
98
+
99
+ ```bash
100
+ # Pipe entries through jq to filter
101
+ node ~/.pi/agent/skills/pi-share/fetch-session.mjs "<url>" --entries | jq 'select(.type == "message" and .message.role == "user")'
102
+
103
+ # Count tool calls
104
+ node ~/.pi/agent/skills/pi-share/fetch-session.mjs "<url>" --entries | jq -s '[.[] | select(.type == "message") | .message.content[]? | select(.type == "toolCall")] | length'
105
+ ```