11 KiB
| name | description | allowed-tools | argument-hint |
|---|---|---|---|
| analyze-logs | Analyze Tangem app user logs — extract device info, navigation path, errors, and key events timeline. Use when user provides a log file for bug investigation. | Read, Grep | /path/to/logfile.txt [/path/to/logs.rtf] [--no-secrets-audit] |
Analyze the Tangem app user log file at path: $ARGUMENTS
File Input
The user provides one or two file paths:
- Log file (
.txt) — main application log, always required - User info file (
.rtfor.txt) — optional, contains card/device/error info from the user's feedback email
If two paths are provided, the first is the log file and the second is the user info file.
If only the log file is provided, ask the user if they have a user info file (logs.rtf or logs.txt). If they don't have it or don't respond, fill Device Context, Card Info, and Transaction Context sections from the log file data (Steps 2+3). Mark fields that could not be determined as "N/A".
User Info File (logs.rtf / logs.txt)
If a user info file is provided, Read it and extract the plain text fields. The file contains structured key-value pairs like:
Card ID: AF36000002151580
Firmware version: 6.33r
Linked cards count: 2
Has seed phrase: true
Signed hashes [secp256k1]: 0
----------
Blockchain: Polygon
Explorer link: https://polygonscan.com/address/0x...
Derivation path: m/44'/60'/0'/0/0
Host: https://rpc-mainnet.matic.quiknode.pro/
Token: USDC
Error: Could not construct a recoverable key.
----------
Source address: 0x...
Destination address: 0x...
Amount: 11.319684
Fee: 0.004973
----------
Phone model: SM-S921B
OS version: 36
App version: 5.34.1
Extract all fields and include them in the Device Context, Card Info, and Analysis Summary sections of the report. If the RTF contains an Error: field, treat it as a key clue for the investigation.
Note: RTF files contain formatting markup (\cb3, \cf4, {\field{...}}). Ignore all RTF tags — only extract the plain text values after each colon.
Log Format
Each line follows the pattern:
DD.MM HH:MM:SS.mmm: TAG Message
- Date format:
DD.MM(day.month), no year — infer from context - Multi-line entries (JSON bodies, stack traces) continue without the timestamp prefix
- Sensitive data is masked with
****** - Continuation lines may start with
|for structured data:|- Duration millis: 300000
Analysis Steps
Use head_limit on every Grep call to protect context from overload.
Step 1: Setup
- Log time range: Read the first and last lines with dates (format
DD.MM) - Ask the user (report time range, then ask):
- Date range to focus on (or "all" for the full file)
- Focus area:
Wallet,WalletConnect,Express (Onramp/Buy, Offramp/Sell, Swap/Exchange),TangemPay,Feed,Markets,Settings,Referral,Staking,Onboarding,Send/Transactions,NFT, orall - Remember the chosen area as FOCUS_AREA
- Determine line range (skip if "all"):
- Parse input into
DD.MMpatterns (10-13.03→ start10.03, end13.03;last day→ last date;last 3 days→ 3 days before last) - Find START_LINE: Grep
^START_DATE(head_limit: 1, -n: true) - Find END_LINE: Grep
^NEXT_DATE(head_limit: 1, -n: true). If not found, END_LINE = end of file - Report: "Focusing on lines START_LINE–END_LINE covering DD.MM–DD.MM"
- Parse input into
Steps 2+3+4+5+6: Main Analysis (all in parallel)
Launch ALL Grep calls below in parallel. Steps 2+3 search the full file (device info may be before the date range). Steps 4+5+6 use offset: START_LINE to stay within the date range.
Device Context (full file):
PATCH.*user-wallets/applications(head_limit: 5, -A 10) — Read JSON body to extractsystemVersion,version,language,timezoneip_address(head_limit: 5, -A 20) — extractalpha2,country,isBuyAllowed,isSellAllowed
Card Info (full file):
CardSDK_Tlv.*TAG_Firmware(head_limit: 20)CardSDK_Tlv.*TAG_SettingsMask(head_limit: 20)CardSDK_Tlv.*TAG_IsActivated(head_limit: 20)CardSDK_Tlv.*TAG_ManufacturerName(head_limit: 20)
Navigation (offset: START_LINE):
AppRouter(head_limit: 200) — if FOCUS_AREA isallor navigation-heavy (Wallet, Onboarding, Send/Transactions), also Read.claude/docs/navigation-graph.mdto cross-reference routes
Errors (offset: START_LINE, head_limit: 50 each, -n: true):
- HTTP errors:
<-- [45]\d{2} - Domain errors:
DomainError - App exceptions:
\bException\b - Biometric errors:
onAuthenticationError - Tangem Pay errors:
Failed checkCustomerWallet
Session timeline (offset: START_LINE, head_limit: 50 each):
MainActivity.*onCreate— app session startMainActivity.*Splash screen— splash screen installed/dismissedMainActivity.*onNewIntent— deep link or push notificationCardSDK_Session.*start card session— NFC session starts
Secrets & PII Audit (full file, head_limit: 20 each, -n: true):
Skip this entire group if --no-secrets-audit is in arguments.
- API key leak in URL:
[?&](api[_-]?key|apiKey|access_token|token|secret)=(?!\*+)[^&\s]{8,} - Bearer token:
Bearer\s+[A-Za-z0-9._\-]{20,} - JWT:
eyJ[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+\.[A-Za-z0-9_\-]+ - Authorization header:
(?i)authorization:\s*\S+ - Critical PII in JSON:
"(privateKey|mnemonic|seedPhrase|private_key|seed_phrase)"\s*:\s*"[^"]+" - card_public_key in JSON:
"card_public_key"\s*:\s*"[^"]{40,}" - FCM push token:
:APA91[A-Za-z0-9_\-]{100,} - xprv/tprv extended private key:
\b[xytzuv]prv[A-Za-z0-9]{100,} - Suspicious long hex in URL path:
https?://[^?\s]+/[A-Fa-f0-9]{32,}\b - Masking health check: count of
\*{6,}— if 0 in a build that should mask, flag pipeline broken
Error filtering: When processing error results, skip these noisy matches:
java.io.IOException: Canceled— normal request cancellationHttpException(code=304— HTTP "Not Modified"- Bare stacktrace lines starting with
\tat <-- HTTP FAILED: java.io.IOException: Canceled
Step 6.5: Masking Consistency Check
Skip if --no-secrets-audit in arguments. Run sequentially after the parallel batch (needs results from the masked-endpoint grep).
- Grep
https?://[^/\s]+/[^\s*]*\*{6,}(full file, head_limit: 50) — collect all URLs where a path segment is masked - For each unique
host + path-prefix-before-mask, derive the prefix string - For each prefix, Grep the prefix followed by a non-
*character (<prefix>[^*\s], head_limit: 20)- If hits found → masking inconsistency: same endpoint has both masked and unmasked variants
- Record the prefix, count of masked hits, count of unmasked hits, first unmasked line number
Step 7: Deep Dive
For each significant error found above:
- Note the error's line number from Grep output (
-n: true) - Use Read with
offset: ERROR_LINE - 100, limit: 200to get ~200 lines of context - In that context, look for navigation events, API calls, and redux actions
Key Tags Reference
| Tag | Purpose |
|---|---|
MainActivity |
Activity lifecycle, splash screen, onNewIntent |
AppRouter |
Navigation: Push, Pop, Replace |
NetworkLogs |
HTTP requests/responses (OkHttp) |
BlockchainSDK_NETWORK |
Blockchain RPC calls |
CardSDK_Tlv |
NFC card data (firmware, settings) |
CardSDK_Session |
NFC session lifecycle |
CardSDK_Biometric |
Biometric authentication |
Common Error Patterns
| Pattern | Meaning |
|---|---|
HttpException(code=4xx/5xx, errorBody={...}) |
API error with structured body |
DomainError(description=...) |
App-level domain error |
<-- HTTP FAILED: java.io.IOException: Canceled |
Cancelled network request (noise) |
<-- 429 |
Rate limiting |
onAuthenticationError |
Biometric auth failure |
Output Template
Structure your report EXACTLY as follows:
# Log Analysis Report
## Device Context
| Parameter | Value |
|-----------|-------|
| App version | ... |
| Android version | ... |
| Phone model | ... (from logs.rtf if available) |
| Language | ... |
| Timezone | ... |
| Country | ... |
| Log time range | DD.MM HH:MM — DD.MM HH:MM |
## Card Info
| Parameter | Value |
|-----------|-------|
| Card ID | ... (from logs.rtf if available) |
| Firmware | ... |
| Manufacturer | ... |
| Is activated | ... |
| Linked cards | ... (from logs.rtf if available) |
| Has seed phrase | ... (from logs.rtf if available) |
## Transaction Context (from logs.rtf, if available)
| Parameter | Value |
|-----------|-------|
| Blockchain | ... |
| Token | ... |
| Source address | ... |
| Destination address | ... |
| Amount | ... |
| Fee | ... |
| Error | ... |
## Navigation Path
1. [HH:MM:SS] Screen (Push/Pop/Replace)
2. ...
**Summary:** Brief description of the user's journey.
## Errors Found
### HTTP Errors
| Time | URL | Status | Details |
|------|-----|--------|---------|
### Domain Errors
| Time | Component | Error |
|------|-----------|-------|
### Other Errors
| Time | Type | Details |
|------|------|---------|
## Key Events Timeline
| Time | Event | Details |
|------|-------|---------|
(chronological: app starts, card sessions, navigation, errors, notable API calls)
## Secrets & PII Audit
Omit this section entirely if `--no-secrets-audit` was passed.
### Health Check
- Total masked tokens (`******`) in log: **N**
- If N = 0 in a build expected to mask, flag: "masking pipeline may be broken"
### Confirmed Leaks (CRITICAL / HIGH)
| Line | Severity | Type | Matched (first 16 chars + `…`) | Context |
|------|----------|------|--------------------------------|---------|
### Masking Inconsistencies
| Endpoint Prefix | Masked Hits | Unmasked Hits | First Unmasked Line |
|-----------------|-------------|---------------|---------------------|
### Suspected Leaks (MEDIUM / LOW)
| Line | Severity | Type | Pattern Matched | Why Suspect |
|------|----------|------|-----------------|-------------|
**Severity legend:**
- **CRITICAL** — private key / mnemonic / xprv in clear text
- **HIGH** — API key / bearer / JWT / card_public_key visible
- **MEDIUM** — push token, card_id, persistent identifiers
- **LOW** — heuristic patterns that may be false positives (tx hash, content hash)
**Output rules:**
- Never include the full matched value — always truncate to 16 chars + `…`
- For LOW severity, add a "Why Suspect" column explaining typical false positives
- Skip matches from these known-public Tangem endpoints: `/v1/coins/settings`, `/v1/geo`, `/v1/currencies`, `/v1/hot_crypto`
## Analysis Summary
(2-3 paragraphs: what the user was doing, what broke, probable cause, recommendations.
If FOCUS_AREA was specified, emphasize errors, navigation, and API calls related to that area.)
If a section has no data, write "None found" instead of omitting it.