litclaude-ai 0.2.2
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/CHANGELOG.md +155 -0
- package/LICENSE +21 -0
- package/README.md +369 -0
- package/README_ko-KR.md +374 -0
- package/RELEASE_CHECKLIST.md +165 -0
- package/bin/litclaude-ai.js +643 -0
- package/cover.png +0 -0
- package/docs/agents.md +67 -0
- package/docs/hooks.md +134 -0
- package/docs/lsp.md +40 -0
- package/docs/migration.md +209 -0
- package/docs/workflow-compatibility-audit.md +119 -0
- package/generate_cover.py +123 -0
- package/package.json +48 -0
- package/plugins/litclaude/.claude-plugin/plugin.json +25 -0
- package/plugins/litclaude/.lsp.json +13 -0
- package/plugins/litclaude/.mcp.json +9 -0
- package/plugins/litclaude/agents/boulder-executor.md +12 -0
- package/plugins/litclaude/agents/librarian-researcher.md +15 -0
- package/plugins/litclaude/agents/oracle-verifier.md +16 -0
- package/plugins/litclaude/agents/prometheus-planner.md +13 -0
- package/plugins/litclaude/agents/qa-runner.md +16 -0
- package/plugins/litclaude/agents/quality-reviewer.md +17 -0
- package/plugins/litclaude/bin/litclaude-hook.js +110 -0
- package/plugins/litclaude/bin/litclaude-hud.js +271 -0
- package/plugins/litclaude/bin/litclaude-lsp-doctor.js +15 -0
- package/plugins/litclaude/bin/litclaude-mcp.js +70 -0
- package/plugins/litclaude/commands/deep-interview.md +21 -0
- package/plugins/litclaude/commands/dynamic-workflow.md +36 -0
- package/plugins/litclaude/commands/lit-loop.md +40 -0
- package/plugins/litclaude/commands/lit-plan.md +35 -0
- package/plugins/litclaude/commands/litgoal.md +30 -0
- package/plugins/litclaude/commands/review-work.md +35 -0
- package/plugins/litclaude/commands/start-work.md +36 -0
- package/plugins/litclaude/hooks/hooks.json +54 -0
- package/plugins/litclaude/lib/context-pressure.mjs +25 -0
- package/plugins/litclaude/lib/hud-accent-palette.mjs +58 -0
- package/plugins/litclaude/lib/litgoal/cli.mjs +266 -0
- package/plugins/litclaude/lib/litgoal/ledger.mjs +16 -0
- package/plugins/litclaude/lib/litgoal/paths.mjs +7 -0
- package/plugins/litclaude/lib/litgoal/state.mjs +67 -0
- package/plugins/litclaude/lib/mutated-file-paths.mjs +63 -0
- package/plugins/litclaude/lib/start-work-continuation.mjs +99 -0
- package/plugins/litclaude/lib/workflow-check.mjs +83 -0
- package/plugins/litclaude/skills/ai-slop-remover/SKILL.md +142 -0
- package/plugins/litclaude/skills/comment-checker/SKILL.md +55 -0
- package/plugins/litclaude/skills/debugging/SKILL.md +70 -0
- package/plugins/litclaude/skills/debugging/references/methodology/00-setup.md +108 -0
- package/plugins/litclaude/skills/debugging/references/methodology/02-investigate.md +126 -0
- package/plugins/litclaude/skills/debugging/references/methodology/04-oracle-triple.md +106 -0
- package/plugins/litclaude/skills/debugging/references/methodology/05-escalate.md +69 -0
- package/plugins/litclaude/skills/debugging/references/methodology/06-fix.md +116 -0
- package/plugins/litclaude/skills/debugging/references/methodology/08-qa.md +94 -0
- package/plugins/litclaude/skills/debugging/references/methodology/09-cleanup.md +164 -0
- package/plugins/litclaude/skills/debugging/references/methodology/partial-runtime-evidence.md +228 -0
- package/plugins/litclaude/skills/debugging/references/runtimes/bundled-js-binary.md +415 -0
- package/plugins/litclaude/skills/debugging/references/runtimes/go.md +252 -0
- package/plugins/litclaude/skills/debugging/references/runtimes/native-binary.md +484 -0
- package/plugins/litclaude/skills/debugging/references/runtimes/node.md +260 -0
- package/plugins/litclaude/skills/debugging/references/runtimes/python.md +248 -0
- package/plugins/litclaude/skills/debugging/references/runtimes/rust.md +234 -0
- package/plugins/litclaude/skills/debugging/references/tools/ghidra.md +212 -0
- package/plugins/litclaude/skills/debugging/references/tools/playwright-cli.md +194 -0
- package/plugins/litclaude/skills/debugging/references/tools/pwndbg.md +263 -0
- package/plugins/litclaude/skills/debugging/references/tools/pwntools.md +265 -0
- package/plugins/litclaude/skills/deep-interview/SKILL.md +323 -0
- package/plugins/litclaude/skills/deep-interview/scripts/render_progress.py +193 -0
- package/plugins/litclaude/skills/frontend-ui-ux/SKILL.md +62 -0
- package/plugins/litclaude/skills/lit-loop/SKILL.md +144 -0
- package/plugins/litclaude/skills/lit-plan/SKILL.md +125 -0
- package/plugins/litclaude/skills/litgoal/SKILL.md +219 -0
- package/plugins/litclaude/skills/lsp/SKILL.md +63 -0
- package/plugins/litclaude/skills/programming/SKILL.md +106 -0
- package/plugins/litclaude/skills/programming/references/go/README.md +90 -0
- package/plugins/litclaude/skills/programming/references/go/backend-stack.md +641 -0
- package/plugins/litclaude/skills/programming/references/go/bootstrap.md +328 -0
- package/plugins/litclaude/skills/programming/references/go/bubbletea-v2.md +360 -0
- package/plugins/litclaude/skills/programming/references/go/cobra-stack.md +468 -0
- package/plugins/litclaude/skills/programming/references/go/concurrency.md +362 -0
- package/plugins/litclaude/skills/programming/references/go/data-modeling.md +329 -0
- package/plugins/litclaude/skills/programming/references/go/error-handling.md +359 -0
- package/plugins/litclaude/skills/programming/references/go/golangci-strict.md +236 -0
- package/plugins/litclaude/skills/programming/references/go/grpc-connect.md +375 -0
- package/plugins/litclaude/skills/programming/references/go/libraries.md +337 -0
- package/plugins/litclaude/skills/programming/references/go/one-liners.md +202 -0
- package/plugins/litclaude/skills/programming/references/go/sqlc-pgx.md +471 -0
- package/plugins/litclaude/skills/programming/references/go/testing.md +467 -0
- package/plugins/litclaude/skills/programming/references/go/type-patterns.md +298 -0
- package/plugins/litclaude/skills/programming/references/python/README.md +314 -0
- package/plugins/litclaude/skills/programming/references/python/async-anyio.md +442 -0
- package/plugins/litclaude/skills/programming/references/python/data-modeling.md +233 -0
- package/plugins/litclaude/skills/programming/references/python/data-processing.md +133 -0
- package/plugins/litclaude/skills/programming/references/python/error-handling.md +218 -0
- package/plugins/litclaude/skills/programming/references/python/fastapi-stack.md +316 -0
- package/plugins/litclaude/skills/programming/references/python/httpx2-optimization.md +360 -0
- package/plugins/litclaude/skills/programming/references/python/libraries.md +307 -0
- package/plugins/litclaude/skills/programming/references/python/one-liners.md +268 -0
- package/plugins/litclaude/skills/programming/references/python/orjson-stack.md +378 -0
- package/plugins/litclaude/skills/programming/references/python/pydantic-ai.md +285 -0
- package/plugins/litclaude/skills/programming/references/python/pyproject-strict.md +232 -0
- package/plugins/litclaude/skills/programming/references/python/textual-tui.md +201 -0
- package/plugins/litclaude/skills/programming/references/python/type-patterns.md +176 -0
- package/plugins/litclaude/skills/programming/references/rust/README.md +317 -0
- package/plugins/litclaude/skills/programming/references/rust/async-tokio.md +299 -0
- package/plugins/litclaude/skills/programming/references/rust/axum-stack.md +467 -0
- package/plugins/litclaude/skills/programming/references/rust/cargo-strict.md +317 -0
- package/plugins/litclaude/skills/programming/references/rust/clap-stack.md +409 -0
- package/plugins/litclaude/skills/programming/references/rust/concurrency.md +375 -0
- package/plugins/litclaude/skills/programming/references/rust/libraries.md +439 -0
- package/plugins/litclaude/skills/programming/references/rust/one-liners.md +291 -0
- package/plugins/litclaude/skills/programming/references/rust/proptest-insta.md +429 -0
- package/plugins/litclaude/skills/programming/references/rust/type-state.md +354 -0
- package/plugins/litclaude/skills/programming/references/rust/unsafe-discipline.md +250 -0
- package/plugins/litclaude/skills/programming/references/rust/zero-cost-safety.md +527 -0
- package/plugins/litclaude/skills/programming/references/rust-ub/README.md +289 -0
- package/plugins/litclaude/skills/programming/references/rust-ub/miri-sanitizers-loom.md +411 -0
- package/plugins/litclaude/skills/programming/references/rust-ub/ub-taxonomy.md +269 -0
- package/plugins/litclaude/skills/programming/references/typescript/README.md +195 -0
- package/plugins/litclaude/skills/programming/references/typescript/backend-hono.md +672 -0
- package/plugins/litclaude/skills/programming/references/typescript/bootstrap.md +199 -0
- package/plugins/litclaude/skills/programming/references/typescript/data-modeling.md +202 -0
- package/plugins/litclaude/skills/programming/references/typescript/error-handling.md +169 -0
- package/plugins/litclaude/skills/programming/references/typescript/tsconfig-strict.md +152 -0
- package/plugins/litclaude/skills/programming/references/typescript/type-patterns.md +196 -0
- package/plugins/litclaude/skills/programming/scripts/go/check-no-excuse-rules.sh +173 -0
- package/plugins/litclaude/skills/programming/scripts/go/new-project.py +138 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/.editorconfig +13 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/.golangci.yml +95 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/AGENTS.md.tmpl +24 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/README.md.tmpl +12 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/Taskfile.yml +40 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/ci.yml +37 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/config.go +24 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/gitignore +15 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/main.go.tmpl +22 -0
- package/plugins/litclaude/skills/programming/scripts/go/templates/run.go +15 -0
- package/plugins/litclaude/skills/programming/scripts/python/check-no-excuse-rules.py +687 -0
- package/plugins/litclaude/skills/programming/scripts/python/new-project.py +172 -0
- package/plugins/litclaude/skills/programming/scripts/python/new-script.py +116 -0
- package/plugins/litclaude/skills/programming/scripts/rust/check-no-excuse-rules.py +296 -0
- package/plugins/litclaude/skills/programming/scripts/rust/check-no-excuse-rules.sh +158 -0
- package/plugins/litclaude/skills/programming/scripts/rust/new-project.py +175 -0
- package/plugins/litclaude/skills/programming/scripts/typescript/check-no-excuse-rules.ts +282 -0
- package/plugins/litclaude/skills/programming/scripts/typescript/new-project.ts +177 -0
- package/plugins/litclaude/skills/refactor/SKILL.md +73 -0
- package/plugins/litclaude/skills/remove-ai-slops/SKILL.md +52 -0
- package/plugins/litclaude/skills/review-work/SKILL.md +331 -0
- package/plugins/litclaude/skills/rules/SKILL.md +66 -0
- package/plugins/litclaude/skills/start-work/SKILL.md +132 -0
- package/scripts/audit-plan-checkboxes.mjs +37 -0
- package/scripts/doctor.mjs +41 -0
- package/scripts/inspect-agent-tools.mjs +27 -0
- package/scripts/postinstall.mjs +50 -0
- package/scripts/qa-claude-plugin-smoke.sh +60 -0
- package/scripts/qa-portable-install.sh +136 -0
- package/scripts/validate-plugin.mjs +72 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# Rust Debugging
|
|
2
|
+
|
|
3
|
+
Covers `cargo`, `tokio`, panics, and the fact that you usually don't actually need a debugger — Rust's type system, `dbg!`, and logging cover 80% of sessions faster than gdb would.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Environment detection (Phase 0)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cargo --version
|
|
11
|
+
rustc --version
|
|
12
|
+
cat rust-toolchain.toml rust-toolchain 2>/dev/null
|
|
13
|
+
cat Cargo.toml | head -30
|
|
14
|
+
|
|
15
|
+
# Debuggers available
|
|
16
|
+
which rust-gdb
|
|
17
|
+
which rust-lldb
|
|
18
|
+
which lldb
|
|
19
|
+
|
|
20
|
+
# Async infrastructure
|
|
21
|
+
grep -E '"(tokio|async-std|smol)"' Cargo.toml
|
|
22
|
+
|
|
23
|
+
# Profile flags
|
|
24
|
+
grep -E '^\[profile' Cargo.toml
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**The default `cargo run` builds with `dev` profile** which includes debug symbols. `cargo run --release` strips them. For debugging, stay in dev unless the bug only manifests under optimization.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## The Rust debugging hierarchy (use in this order)
|
|
32
|
+
|
|
33
|
+
Rust's ecosystem has a specific order that's faster than reaching for gdb first:
|
|
34
|
+
|
|
35
|
+
1. **`dbg!(expr)` macro** — for a single value at a specific spot. Prints file:line + value, returns the value unchanged so you can inline it. Faster than a debugger for 60% of bugs.
|
|
36
|
+
2. **`RUST_LOG=trace` with `tracing` / `env_logger`** — for flow and state across an operation. Zero code change in dev-time.
|
|
37
|
+
3. **`RUST_BACKTRACE=1` / `=full`** — for crashes. Almost always sufficient; you rarely need a live debugger for a panic.
|
|
38
|
+
4. **`rust-gdb` / `rust-lldb`** — when you need to pause execution and inspect memory, especially for unsafe code or FFI.
|
|
39
|
+
5. **`tokio-console`** — for async deadlocks, stuck tasks, hot loops.
|
|
40
|
+
6. **`cargo-expand`** — when a macro is doing something weird.
|
|
41
|
+
|
|
42
|
+
Reach for the lightest tool that answers the hypothesis.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## `dbg!` — the underused macro
|
|
47
|
+
|
|
48
|
+
```rust
|
|
49
|
+
let x = 5;
|
|
50
|
+
let y = dbg!(x * 2); // prints: [src/main.rs:2] x * 2 = 10
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Inside a complex expression:
|
|
54
|
+
```rust
|
|
55
|
+
let total = items.iter().filter(|i| i.active).map(|i| dbg!(i.cost)).sum::<u64>();
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Multiple values at once:
|
|
59
|
+
```rust
|
|
60
|
+
dbg!(&user, &request, elapsed.as_millis());
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`dbg!` writes to stderr, so it won't corrupt stdout-based pipelines. **Journal each `dbg!` you add**; revert at Phase 9.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## `RUST_LOG` for flow-level debugging
|
|
68
|
+
|
|
69
|
+
If the codebase uses `tracing` or `env_logger`:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
RUST_LOG=debug cargo run
|
|
73
|
+
RUST_LOG=trace cargo run # very verbose
|
|
74
|
+
RUST_LOG=my_crate=trace,hyper=info cargo run # per-module level
|
|
75
|
+
RUST_LOG=debug,tokio=off cargo run # silence noisy crates
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
For `tracing`-based apps, instrument with spans:
|
|
79
|
+
```rust
|
|
80
|
+
#[tracing::instrument]
|
|
81
|
+
fn handle_request(req: &Request) -> Response { ... }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
This gives you structured per-call entry/exit logs with args and timing, zero additional code in the body.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## `RUST_BACKTRACE` for panics
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
RUST_BACKTRACE=1 cargo run # backtrace on panic
|
|
92
|
+
RUST_BACKTRACE=full cargo run # include libstd/tokio frames
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The panic itself usually tells you the file:line. The backtrace tells you how it got there. Between the two, most crash bugs are solved without a debugger.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## rust-gdb / rust-lldb
|
|
100
|
+
|
|
101
|
+
### Launch
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Build with debug symbols (default dev profile)
|
|
105
|
+
cargo build
|
|
106
|
+
|
|
107
|
+
# Attach gdb wrapper (applies Rust type pretty-printers)
|
|
108
|
+
rust-gdb ./target/debug/my_binary
|
|
109
|
+
# Or lldb:
|
|
110
|
+
rust-lldb ./target/debug/my_binary
|
|
111
|
+
|
|
112
|
+
# With args
|
|
113
|
+
rust-gdb --args ./target/debug/my_binary arg1 arg2
|
|
114
|
+
|
|
115
|
+
# Attach to running process
|
|
116
|
+
rust-gdb -p $(pgrep my_binary)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Breakpoints
|
|
120
|
+
|
|
121
|
+
Rust symbols are mangled. Use either:
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
(gdb) b main # main function
|
|
125
|
+
(gdb) b my_crate::module::function # canonical path
|
|
126
|
+
(gdb) b src/handler.rs:42 # file:line
|
|
127
|
+
(gdb) info functions my_function # find mangled name
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### State inspection
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
(gdb) p x # print value (uses Rust pretty-printer for Vec, Option, HashMap, etc.)
|
|
134
|
+
(gdb) p *ptr # deref
|
|
135
|
+
(gdb) info locals # all locals in current frame
|
|
136
|
+
(gdb) info args # function args
|
|
137
|
+
(gdb) bt # backtrace
|
|
138
|
+
(gdb) frame <n> # switch to stack frame n
|
|
139
|
+
(gdb) watch my_var # stop when my_var changes
|
|
140
|
+
(gdb) rbreak regex # breakpoint all functions matching regex
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Pair with pwndbg** for better layout on native bugs — see [tools/pwndbg.md](../tools/pwndbg.md). Pwndbg works with rust-gdb too.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## tokio-console — async task debugging
|
|
148
|
+
|
|
149
|
+
For tokio-based async apps, this is essential when tasks are stuck or leaking.
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# Add tokio-console instrumentation to the target binary
|
|
153
|
+
# In Cargo.toml:
|
|
154
|
+
# [dependencies]
|
|
155
|
+
# console-subscriber = "0.2"
|
|
156
|
+
|
|
157
|
+
# In main.rs:
|
|
158
|
+
# console_subscriber::init();
|
|
159
|
+
|
|
160
|
+
# Build with tokio_unstable:
|
|
161
|
+
RUSTFLAGS="--cfg tokio_unstable" cargo run
|
|
162
|
+
|
|
163
|
+
# In another terminal:
|
|
164
|
+
tokio-console # connects to default port 6669
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Shows live tasks, their state, wake counts, poll durations, parent tasks. The single fastest way to find "why is my async thing stuck".
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## cargo-expand — when a macro is suspect
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
cargo install cargo-expand
|
|
175
|
+
cargo expand # expand all macros in the crate
|
|
176
|
+
cargo expand my::module::path # scope to one item
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
If you suspect a macro (especially `#[derive]`, `#[tokio::main]`, `#[async_trait]`) is generating code that doesn't match your mental model, this shows you exactly what the compiler sees.
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Release-build gotcha
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
cargo build --release # no debug symbols by default
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
If the bug only shows up in `--release`:
|
|
190
|
+
|
|
191
|
+
```toml
|
|
192
|
+
# Cargo.toml
|
|
193
|
+
[profile.release]
|
|
194
|
+
debug = true # add symbols, keep optimizations
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Now `rust-gdb ./target/release/my_binary` works on release builds. This is required when optimization-enabled codegen bugs (inlining, LLVM folding) are suspected.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Silent-failure patterns in Rust
|
|
202
|
+
|
|
203
|
+
| Pattern | Why it's silent |
|
|
204
|
+
|---|---|
|
|
205
|
+
| `.unwrap_or_default()` | Masks errors as the zero value |
|
|
206
|
+
| `.unwrap_or(fallback)` | Same, with a specific fallback |
|
|
207
|
+
| `let _ = fallible_operation()` | Explicitly discards the Result, no compiler warning |
|
|
208
|
+
| `if let Ok(x) = ... { use(x); } // no else` | Silent on Err |
|
|
209
|
+
| `.ok()` chaining | Converts Result to Option, throwing the error away |
|
|
210
|
+
| Panic inside a tokio task not `.await`ed | Task dies silently; runtime usually logs but it's quiet if logs are off |
|
|
211
|
+
| `eprintln!` that goes to a redirected-null stderr | Looks like nothing happened |
|
|
212
|
+
| `Drop` impl that panics under specific condition | Double-panic aborts process silently if no logging configured |
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Phase 9 cleanup specifics
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
# Revert dbg! macro additions
|
|
220
|
+
git diff | grep -E 'dbg!\('
|
|
221
|
+
# For any file with dbg! additions:
|
|
222
|
+
git checkout <file>
|
|
223
|
+
|
|
224
|
+
# Unset env vars
|
|
225
|
+
unset RUST_LOG RUST_BACKTRACE
|
|
226
|
+
|
|
227
|
+
# Kill any rust-gdb/lldb sessions
|
|
228
|
+
pkill -f 'rust-gdb' || true
|
|
229
|
+
pkill -f 'rust-lldb' || true
|
|
230
|
+
pkill -f '^lldb ' || true
|
|
231
|
+
|
|
232
|
+
# tokio-console binds 6669 by default
|
|
233
|
+
lsof -iTCP:6669 -sTCP:LISTEN -nP 2>/dev/null
|
|
234
|
+
```
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# Ghidra — Decompile Binaries Into Readable C
|
|
2
|
+
|
|
3
|
+
**https://github.com/NationalSecurityAgency/ghidra**
|
|
4
|
+
|
|
5
|
+
Ghidra is the NSA's open-source reverse-engineering suite. Its defining feature is a **decompiler** that turns machine code back into readable C. For any binary you don't have source for, this is the correct starting point — not `strings`, not hex-staring, not `objdump -d`.
|
|
6
|
+
|
|
7
|
+
**Use Ghidra when**: third-party closed-source libs, malware analysis, vendored binaries whose behavior contradicts docs, CTF challenges, firmware, any time you need to read compiled code.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# macOS
|
|
15
|
+
brew install --cask ghidra
|
|
16
|
+
# OR download the release ZIP from the repo and ./ghidraRun
|
|
17
|
+
|
|
18
|
+
# Linux
|
|
19
|
+
# Download from https://github.com/NationalSecurityAgency/ghidra/releases
|
|
20
|
+
# Requires JDK 21+
|
|
21
|
+
./ghidraRun
|
|
22
|
+
|
|
23
|
+
# Dependency
|
|
24
|
+
java -version # must be 21+
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Ghidra is a Java Swing app. Looks dated, works well.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## First-time workflow (memorize this — it's not obvious)
|
|
32
|
+
|
|
33
|
+
1. **Start Ghidra**: `ghidraRun`
|
|
34
|
+
2. **Create a project**: File → New Project → Non-Shared → name it `debug-<binary-name>` (journal this path so you can rm it at Phase 9 if disposable).
|
|
35
|
+
3. **Import the binary**: File → Import File → pick your target. Accept default format detection.
|
|
36
|
+
4. **Double-click the imported binary** in the project listing. Ghidra asks to analyze it — say **yes**, accept defaults for the first pass. This takes anywhere from seconds (small binary) to tens of minutes (large binary).
|
|
37
|
+
5. **Once analysis completes**, you're in the CodeBrowser view.
|
|
38
|
+
|
|
39
|
+
Two panels you'll use 95% of the time:
|
|
40
|
+
|
|
41
|
+
- **Listing** (middle) — the disassembly with Ghidra's inferred labels/types.
|
|
42
|
+
- **Decompiler** (right) — the reconstructed C. The real value.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Finding the right function fast
|
|
47
|
+
|
|
48
|
+
Don't try to read the whole binary. Use these to narrow:
|
|
49
|
+
|
|
50
|
+
### Symbol Tree (left panel)
|
|
51
|
+
|
|
52
|
+
- `Functions` — all detected functions. Stripped binaries show `FUN_00401234` (address-named); unstripped show actual names.
|
|
53
|
+
- `Imports` — dynamically-linked functions. Great for "does this binary call `system()`, `strcpy`, `curl_easy_perform`?"
|
|
54
|
+
- `Exports` — if it's a library.
|
|
55
|
+
|
|
56
|
+
Click to jump. The Decompiler updates instantly.
|
|
57
|
+
|
|
58
|
+
### String search
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
Search → For Strings
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Produces a list of all strings. Right-click a string → `References` → `Show References to Address`. Jumps to code that references it. **This is how you find which function handles the error message you saw at runtime.**
|
|
65
|
+
|
|
66
|
+
### Memory search for bytes
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
Search → Memory
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Search hex or text. Useful for known magic bytes, file-format signatures, constants.
|
|
73
|
+
|
|
74
|
+
### Cross-references (XREF)
|
|
75
|
+
|
|
76
|
+
Right-click any function / address → `References → Find References to`. Shows every place that calls it. Walk the call graph backward from interesting functions.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Making the decompiler's output readable
|
|
81
|
+
|
|
82
|
+
Ghidra's decompiler is good but needs hints. These three actions dramatically improve its output:
|
|
83
|
+
|
|
84
|
+
### 1. Rename variables
|
|
85
|
+
|
|
86
|
+
Click a variable in the Decompiler view → press `L` → type a better name. Ghidra propagates the rename across all uses.
|
|
87
|
+
|
|
88
|
+
### 2. Set types
|
|
89
|
+
|
|
90
|
+
A variable that looks like `undefined4` or `void *` is unhelpful. Click it → press `Ctrl+L` → set type (e.g. `int`, `char *`, `struct my_header *`).
|
|
91
|
+
|
|
92
|
+
For pointers to structs from headers you have, use:
|
|
93
|
+
```
|
|
94
|
+
File → Parse C Source → paste header file → auto-creates struct types
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Then assign the struct type to the pointer. Ghidra resolves field accesses immediately.
|
|
98
|
+
|
|
99
|
+
### 3. Retype function signatures
|
|
100
|
+
|
|
101
|
+
Click the function name in the Decompiler → press `F` (Edit Function Signature) → set return type + argument types. This propagates through callers.
|
|
102
|
+
|
|
103
|
+
Do these three actions on the 3-5 most relevant functions and the decompiler output becomes near-source-readable.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Patterns for specific bug types
|
|
108
|
+
|
|
109
|
+
### Looking for integer overflow / buffer overflow
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
Listing: look for
|
|
113
|
+
- LEA → CMP patterns on sizes
|
|
114
|
+
- memcpy/strcpy/sprintf with non-constant sizes
|
|
115
|
+
Decompiler: look for
|
|
116
|
+
- arithmetic on size_t without bounds check
|
|
117
|
+
- `+ user_input` in a length calculation
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Looking for a missing auth check
|
|
121
|
+
|
|
122
|
+
Navigate from the handler entry (found via Strings or Imports) and check the control flow:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
Decompiler: does the function return early / jump to error handler when some flag is not set?
|
|
126
|
+
If the check is absent, that's the bug.
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Looking for hardcoded URLs / keys / paths
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
Search → For Strings → filter `http:` / `https:` / `/etc/` / `bearer ` / `api_key`
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Looking for dispatch / plugin loading
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
Imports → dlopen, LoadLibrary, dlsym, GetProcAddress
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The strings referenced near those calls are often plugin names.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Scripting (headless Ghidra)
|
|
146
|
+
|
|
147
|
+
When you need to automate analysis across many binaries, or repeat a workflow:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Headless analyzer
|
|
151
|
+
$GHIDRA_INSTALL_DIR/support/analyzeHeadless \
|
|
152
|
+
<project-dir> <project-name> \
|
|
153
|
+
-import <binary> \
|
|
154
|
+
-postScript <script.py or script.java>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Ghidra supports Python 3 scripts (via Jython-compatible API) and Java. Useful scripts:
|
|
158
|
+
|
|
159
|
+
- Dump all function signatures to JSON
|
|
160
|
+
- Find all calls to `system()` with constant arguments
|
|
161
|
+
- Auto-rename FUN_xxx based on heuristics (string refs, call patterns)
|
|
162
|
+
|
|
163
|
+
The community has a large collection: https://github.com/NationalSecurityAgency/ghidra/tree/master/Ghidra/Features/Base/ghidra_scripts
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Bookmarks + Notes
|
|
168
|
+
|
|
169
|
+
Ghidra has built-in bookmarks and comments. Use them as your journal inside the project:
|
|
170
|
+
|
|
171
|
+
- Right-click an address → `Set Bookmark` → tag as `Note`. Attach a description.
|
|
172
|
+
- Right-click → `Comments → Set EOL Comment` (shows up inline in decompiler).
|
|
173
|
+
|
|
174
|
+
Treat these as part of the journal. If you end up promoting this Ghidra project (keeping it after the debug session), the comments become durable documentation.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Gotchas
|
|
179
|
+
|
|
180
|
+
- **Large binaries need more Java heap.** Edit `support/launch.properties` and bump `VMARGS=-Xmx8G` (default is often 2G, too small).
|
|
181
|
+
- **Save often.** Ghidra's autosave is not instant; a crash loses uncommitted analysis.
|
|
182
|
+
- **Decompiler has timeouts.** For complex functions it may give up and print `/* WARNING: ... */`. Increase timeout in `Edit → Tool Options → Decompiler`.
|
|
183
|
+
- **Archs beyond x86/ARM/MIPS** sometimes need Sleigh processor module tweaks. Rare but possible.
|
|
184
|
+
- **Signed vs unsigned decompilation** is frequently wrong. Manually retype when integer behavior matters.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## When Ghidra is NOT the right tool
|
|
189
|
+
|
|
190
|
+
- You have the source. Go read it.
|
|
191
|
+
- Bug is in your own recently-compiled binary. Rebuild with `-g` and use gdb/pwndbg (see [pwndbg.md](pwndbg.md)).
|
|
192
|
+
- You just need to know which libs a binary links. `ldd` / `otool -L` / `readelf -d` are faster.
|
|
193
|
+
- You just need strings. `strings -n 8` is faster.
|
|
194
|
+
|
|
195
|
+
Ghidra is the right tool when you need to **read the logic** of a binary you don't have source for.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Phase 9 cleanup specifics
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
# If you created a scratch project just for this debug session, journal path and remove:
|
|
203
|
+
# (the journal should have the exact path)
|
|
204
|
+
# Example:
|
|
205
|
+
ls ~/ghidra-projects/ 2>/dev/null
|
|
206
|
+
# rm -rf ~/ghidra-projects/debug-<binary-name>
|
|
207
|
+
|
|
208
|
+
# If you promoted the project (kept it), it's not cleanup — note it in the final summary to the user
|
|
209
|
+
|
|
210
|
+
# Kill any running Ghidra headless processes
|
|
211
|
+
pkill -f 'analyzeHeadless' || true
|
|
212
|
+
```
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# Playwright CLI — Browser QA That Actually Drives a Browser
|
|
2
|
+
|
|
3
|
+
**https://playwright.dev/ · https://github.com/microsoft/playwright**
|
|
4
|
+
|
|
5
|
+
For any browser-served web UI bug, this is the correct tool. Not curl. Not imagination. Not a headless HTTP library. A real browser with a real rendering engine, real JS execution, real cookies, real service workers, real viewport.
|
|
6
|
+
|
|
7
|
+
**In Phase 8 Manual QA for browser products, using Playwright is not optional.** Curl cannot catch: CSS that breaks at specific viewport widths, hydration mismatches, client-side router bugs, cookie/session interactions, service-worker caching, JS-triggered navigations. All of those are common bug classes. Drive a browser.
|
|
8
|
+
|
|
9
|
+
> Note: `microsoft/playwright-cli` is the legacy repo; the current tooling lives in `@playwright/test` (npm) and `playwright` (pip), which include the `playwright` CLI. Use those — the legacy `playwright-cli` package is deprecated.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## When to reach for Playwright
|
|
14
|
+
|
|
15
|
+
| Bug symptom | Use Playwright? |
|
|
16
|
+
|---|---|
|
|
17
|
+
| Form submit produces wrong result | ✅ — Playwright drives the form exactly as a user does |
|
|
18
|
+
| Page blank in prod, fine locally | ✅ — hydration/env differences need a real browser |
|
|
19
|
+
| CSS looks wrong at a specific width | ✅ — use `--viewport-size` |
|
|
20
|
+
| Click doesn't fire / wrong handler | ✅ — Playwright fires real DOM events |
|
|
21
|
+
| Flash of unstyled content / loading glitch | ✅ — use trace viewer to see frames |
|
|
22
|
+
| API returns wrong data | ❌ — use curl, this isn't a browser bug |
|
|
23
|
+
| Backend returns wrong status code | ❌ — use curl |
|
|
24
|
+
| Client hits a URL that returns 500 | ✅ but also ❌ — Playwright shows the call + response + failure effect on UI |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Install (per-project)
|
|
29
|
+
|
|
30
|
+
Playwright installs browser binaries separately from the npm package.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# In the project
|
|
34
|
+
npm init playwright@latest # interactive; picks TS/JS + browsers + config
|
|
35
|
+
# Or if Playwright is already a dep:
|
|
36
|
+
npx playwright install # downloads browsers
|
|
37
|
+
npx playwright install chromium # just chromium
|
|
38
|
+
npx playwright install --with-deps # also installs OS deps (Linux)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Python:
|
|
42
|
+
```bash
|
|
43
|
+
pip install playwright
|
|
44
|
+
playwright install
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## The four things you'll actually use
|
|
50
|
+
|
|
51
|
+
### 1. `codegen` — record a session, generate the script
|
|
52
|
+
|
|
53
|
+
The fastest way to create a repro. Opens a real browser; your clicks / typing become a Playwright script you can paste into a test.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx playwright codegen https://your-app.local
|
|
57
|
+
npx playwright codegen --viewport-size=375,667 https://your-app.local # iPhone SE size
|
|
58
|
+
npx playwright codegen --device="iPhone 14" https://your-app.local
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Click / type / navigate in the browser; watch the script build in the side panel. Copy the generated script into your journal as the repro for Phase 8.
|
|
62
|
+
|
|
63
|
+
### 2. A one-shot Playwright script — reproduce + capture
|
|
64
|
+
|
|
65
|
+
Usually the Phase 8 QA artifact. Save to `/tmp/debug-repro.spec.ts` (journal it):
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
// /tmp/debug-repro.spec.ts
|
|
69
|
+
import { test, expect } from '@playwright/test';
|
|
70
|
+
|
|
71
|
+
test('refinement chat shows non-empty response when env var set', async ({ page }) => {
|
|
72
|
+
await page.goto('http://localhost:3000/chat');
|
|
73
|
+
await page.fill('textarea[name="message"]', 'Add a logging step');
|
|
74
|
+
await page.click('button[type=submit]');
|
|
75
|
+
|
|
76
|
+
// Wait for the response to appear (not just the spinner to disappear)
|
|
77
|
+
const response = page.locator('[data-testid="assistant-reply"]');
|
|
78
|
+
await expect(response).toBeVisible({ timeout: 30_000 });
|
|
79
|
+
await expect(response).not.toBeEmpty();
|
|
80
|
+
|
|
81
|
+
// Capture evidence
|
|
82
|
+
await page.screenshot({ path: '/tmp/debug-after-fix.png', fullPage: true });
|
|
83
|
+
console.log(await response.textContent());
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Run it with tracing enabled for rich post-mortem:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npx playwright test /tmp/debug-repro.spec.ts --trace on --headed
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 3. `PWDEBUG=1` — step through the script with Playwright Inspector
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
PWDEBUG=1 npx playwright test /tmp/debug-repro.spec.ts
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Opens the Playwright Inspector alongside the browser. You can step through Playwright actions, see the DOM state at each step, and edit selectors on the fly.
|
|
100
|
+
|
|
101
|
+
Use this when the script doesn't reproduce cleanly and you need to watch it run.
|
|
102
|
+
|
|
103
|
+
### 4. `show-trace` — post-mortem on a failed run
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
npx playwright show-trace trace.zip
|
|
107
|
+
# or from the test-results dir:
|
|
108
|
+
npx playwright show-trace test-results/<test-name>/trace.zip
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Scrubs through a recorded session: timeline, DOM snapshot at each action, network, console, source. When a test failed on CI but passed locally, this is the single best artifact.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Headless vs headed during debugging
|
|
116
|
+
|
|
117
|
+
Always add `--headed` when debugging. Headless browsers sometimes behave subtly differently (font rendering, viewport, media permissions). For QA evidence, run headed and screenshot.
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npx playwright test --headed
|
|
121
|
+
npx playwright test --headed --project=chromium # pin the browser
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Catching the silent-failure patterns Playwright is good at
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
// Toast that flashes and disappears
|
|
130
|
+
page.on('console', msg => console.log('[browser console]', msg.type(), msg.text()));
|
|
131
|
+
|
|
132
|
+
// Unhandled page errors (uncaught exceptions in the page JS)
|
|
133
|
+
page.on('pageerror', err => console.error('[page error]', err));
|
|
134
|
+
|
|
135
|
+
// Network failures — e.g., backend returned 500 but UI shows nothing
|
|
136
|
+
page.on('response', async resp => {
|
|
137
|
+
if (!resp.ok()) {
|
|
138
|
+
console.warn(`[network ${resp.status()}] ${resp.url()} — ${await resp.text()}`);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Request that never came back
|
|
143
|
+
page.on('requestfailed', req => {
|
|
144
|
+
console.error('[request failed]', req.url(), req.failure()?.errorText);
|
|
145
|
+
});
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Add these listeners to the top of the debug script. They surface a lot of the "UI showed nothing" class of bug.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Viewport and device emulation
|
|
153
|
+
|
|
154
|
+
CSS bugs that only appear at specific sizes, or layout bugs on mobile:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
// At test level
|
|
158
|
+
test.use({ viewport: { width: 375, height: 667 } });
|
|
159
|
+
|
|
160
|
+
// Per-page
|
|
161
|
+
await page.setViewportSize({ width: 375, height: 667 });
|
|
162
|
+
|
|
163
|
+
// Predefined devices
|
|
164
|
+
import { devices } from '@playwright/test';
|
|
165
|
+
test.use({ ...devices['iPhone 14'] });
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Gotchas
|
|
171
|
+
|
|
172
|
+
- **Wait for state, not for time.** `await page.waitForTimeout(2000)` is flaky. Use `await expect(locator).toBeVisible()` or `page.waitForResponse(urlPattern)`.
|
|
173
|
+
- **Stale selectors re-resolve.** Playwright's locators re-find the element on each action, unlike Puppeteer's handles. Don't over-think it.
|
|
174
|
+
- **Service workers persist across test runs in headed mode.** If you see cached behavior from a previous run, add `await context.clearCookies()` + clear storage before the test.
|
|
175
|
+
- **Installing on CI requires `--with-deps`** on Linux images that lack the browser's shared-library deps.
|
|
176
|
+
- **Parallel tests share a browser process by default**; if one test polls a debugger port, others may interfere. Use `workers: 1` for debugging.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Phase 9 cleanup specifics
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Remove trace files from debug runs
|
|
184
|
+
rm -rf playwright-report/ test-results/ trace.zip
|
|
185
|
+
|
|
186
|
+
# Remove debug spec files from /tmp
|
|
187
|
+
rm -f /tmp/debug-*.spec.ts
|
|
188
|
+
|
|
189
|
+
# Remove screenshot captures
|
|
190
|
+
rm -f /tmp/debug-*.png
|
|
191
|
+
|
|
192
|
+
# If you installed browsers just for this session (rare):
|
|
193
|
+
# Don't remove them — they're useful for future sessions. They live in ~/Library/Caches/ms-playwright (macOS) or ~/.cache/ms-playwright (Linux).
|
|
194
|
+
```
|