agy-superpowers 5.2.2 → 5.2.4

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 (231) hide show
  1. package/README.md +47 -150
  2. package/package.json +1 -1
  3. package/template/agent/rules/CLAUDE.md +80 -0
  4. package/template/agent/rules/code-styles.md +31 -32
  5. package/template/agent/rules/debug-confirmation-policy.md +2 -0
  6. package/template/agent/rules/file-length-policy.md +2 -0
  7. package/template/agent/rules/git-policy.md +7 -0
  8. package/template/agent/rules/language-matching.md +2 -0
  9. package/template/agent/rules/scratch-scripts.md +39 -0
  10. package/template/agent/rules/superpowers.md +8 -51
  11. package/template/agent/skills/executing-plans/SKILL.md +17 -0
  12. package/template/agent/skills/systematic-debugging/SKILL.md +16 -0
  13. package/template/agent/skills/test-driven-development/SKILL.md +16 -0
  14. package/template/agent/skills/verification-before-completion/SKILL.md +22 -0
  15. package/template/agent/skills/writing-plans/SKILL.md +16 -0
  16. package/template/agent/skills/ai-integrated-product/SKILL.md +0 -57
  17. package/template/agent/skills/analytics-setup/SKILL.md +0 -51
  18. package/template/agent/skills/api-design/SKILL.md +0 -193
  19. package/template/agent/skills/app-store-optimizer/SKILL.md +0 -127
  20. package/template/agent/skills/auth-and-identity/SKILL.md +0 -167
  21. package/template/agent/skills/backend-developer/SKILL.md +0 -148
  22. package/template/agent/skills/bootstrapper-finance/SKILL.md +0 -55
  23. package/template/agent/skills/chrome-extension-developer/SKILL.md +0 -53
  24. package/template/agent/skills/community-manager/SKILL.md +0 -115
  25. package/template/agent/skills/content-marketer/SKILL.md +0 -111
  26. package/template/agent/skills/conversion-optimizer/SKILL.md +0 -142
  27. package/template/agent/skills/cto-architect/SKILL.md +0 -133
  28. package/template/agent/skills/customer-success-manager/SKILL.md +0 -126
  29. package/template/agent/skills/data-analyst/SKILL.md +0 -147
  30. package/template/agent/skills/devops-engineer/SKILL.md +0 -117
  31. package/template/agent/skills/email-infrastructure/SKILL.md +0 -164
  32. package/template/agent/skills/game-design/SKILL.md +0 -194
  33. package/template/agent/skills/game-developer/SKILL.md +0 -175
  34. package/template/agent/skills/growth-hacker/SKILL.md +0 -122
  35. package/template/agent/skills/idea-validator/SKILL.md +0 -55
  36. package/template/agent/skills/indie-legal/SKILL.md +0 -53
  37. package/template/agent/skills/influencer-marketer/SKILL.md +0 -141
  38. package/template/agent/skills/landing-page-builder/SKILL.md +0 -59
  39. package/template/agent/skills/launch-strategist/SKILL.md +0 -62
  40. package/template/agent/skills/market-researcher/SKILL.md +0 -53
  41. package/template/agent/skills/micro-saas-builder/SKILL.md +0 -56
  42. package/template/agent/skills/monetization-strategist/SKILL.md +0 -119
  43. package/template/agent/skills/paid-acquisition-specialist/SKILL.md +0 -119
  44. package/template/agent/skills/pricing-psychologist/SKILL.md +0 -58
  45. package/template/agent/skills/real-time-features/SKILL.md +0 -194
  46. package/template/agent/skills/retention-specialist/SKILL.md +0 -123
  47. package/template/agent/skills/rust-developer/SKILL.md +0 -281
  48. package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +0 -231
  49. package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +0 -124
  50. package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +0 -131
  51. package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +0 -132
  52. package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +0 -95
  53. package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +0 -141
  54. package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +0 -125
  55. package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +0 -127
  56. package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +0 -120
  57. package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +0 -131
  58. package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +0 -156
  59. package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +0 -122
  60. package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +0 -167
  61. package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +0 -134
  62. package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +0 -143
  63. package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +0 -121
  64. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +0 -143
  65. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +0 -187
  66. package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +0 -165
  67. package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +0 -177
  68. package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +0 -163
  69. package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +0 -146
  70. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +0 -142
  71. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +0 -160
  72. package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +0 -125
  73. package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +0 -162
  74. package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +0 -177
  75. package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +0 -184
  76. package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +0 -168
  77. package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +0 -182
  78. package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +0 -199
  79. package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +0 -175
  80. package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +0 -185
  81. package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +0 -203
  82. package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +0 -171
  83. package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +0 -158
  84. package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +0 -195
  85. package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +0 -171
  86. package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +0 -156
  87. package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +0 -191
  88. package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +0 -198
  89. package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +0 -154
  90. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +0 -167
  91. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +0 -169
  92. package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +0 -172
  93. package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +0 -189
  94. package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +0 -113
  95. package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +0 -147
  96. package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +0 -122
  97. package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +0 -161
  98. package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +0 -149
  99. package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +0 -138
  100. package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +0 -169
  101. package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +0 -116
  102. package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +0 -128
  103. package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +0 -136
  104. package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +0 -131
  105. package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +0 -179
  106. package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +0 -144
  107. package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +0 -152
  108. package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +0 -145
  109. package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +0 -133
  110. package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +0 -152
  111. package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +0 -124
  112. package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +0 -115
  113. package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +0 -151
  114. package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +0 -130
  115. package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +0 -155
  116. package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +0 -171
  117. package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +0 -138
  118. package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +0 -107
  119. package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +0 -154
  120. package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +0 -118
  121. package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +0 -157
  122. package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +0 -133
  123. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +0 -131
  124. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +0 -136
  125. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +0 -135
  126. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +0 -122
  127. package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +0 -172
  128. package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +0 -168
  129. package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +0 -142
  130. package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +0 -168
  131. package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +0 -147
  132. package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +0 -158
  133. package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +0 -139
  134. package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +0 -147
  135. package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +0 -149
  136. package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +0 -174
  137. package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +0 -159
  138. package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +0 -138
  139. package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +0 -142
  140. package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +0 -156
  141. package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +0 -172
  142. package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +0 -164
  143. package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +0 -99
  144. package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +0 -104
  145. package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +0 -94
  146. package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +0 -78
  147. package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +0 -76
  148. package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +0 -123
  149. package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +0 -127
  150. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +0 -129
  151. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +0 -131
  152. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +0 -142
  153. package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +0 -86
  154. package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +0 -154
  155. package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +0 -118
  156. package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +0 -92
  157. package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +0 -65
  158. package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +0 -101
  159. package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +0 -161
  160. package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +0 -187
  161. package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +0 -142
  162. package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +0 -152
  163. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +0 -141
  164. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +0 -181
  165. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +0 -160
  166. package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +0 -171
  167. package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +0 -130
  168. package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +0 -167
  169. package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +0 -144
  170. package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +0 -154
  171. package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +0 -141
  172. package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +0 -95
  173. package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +0 -135
  174. package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +0 -124
  175. package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +0 -135
  176. package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +0 -134
  177. package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +0 -134
  178. package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +0 -105
  179. package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +0 -65
  180. package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +0 -97
  181. package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +0 -122
  182. package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +0 -119
  183. package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +0 -153
  184. package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +0 -136
  185. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +0 -133
  186. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +0 -120
  187. package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +0 -137
  188. package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +0 -134
  189. package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +0 -150
  190. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +0 -123
  191. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +0 -113
  192. package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +0 -175
  193. package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +0 -149
  194. package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +0 -142
  195. package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +0 -133
  196. package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +0 -148
  197. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +0 -130
  198. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +0 -120
  199. package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +0 -155
  200. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +0 -139
  201. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +0 -135
  202. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +0 -162
  203. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +0 -186
  204. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +0 -162
  205. package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +0 -160
  206. package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +0 -151
  207. package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +0 -171
  208. package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +0 -142
  209. package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +0 -168
  210. package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +0 -151
  211. package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +0 -144
  212. package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +0 -189
  213. package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +0 -226
  214. package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +0 -161
  215. package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +0 -130
  216. package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +0 -154
  217. package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +0 -127
  218. package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +0 -154
  219. package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +0 -142
  220. package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +0 -146
  221. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +0 -160
  222. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +0 -159
  223. package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +0 -144
  224. package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +0 -137
  225. package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +0 -188
  226. package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +0 -143
  227. package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +0 -131
  228. package/template/agent/skills/saas-architect/SKILL.md +0 -139
  229. package/template/agent/skills/security-engineer/SKILL.md +0 -133
  230. package/template/agent/skills/seo-specialist/SKILL.md +0 -130
  231. package/template/agent/skills/solo-founder-ops/SKILL.md +0 -56
@@ -1,179 +0,0 @@
1
- # err-anyhow-app
2
-
3
- > Use `anyhow` for application error handling
4
-
5
- ## Why It Matters
6
-
7
- Applications often don't need typed errors - they just need to report what went wrong with good context. `anyhow` provides easy error handling with context chaining, backtraces, and conversion from any error type.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Tedious type management
13
- fn load_config() -> Result<Config, Box<dyn std::error::Error>> {
14
- let path = find_config()?; // Returns FindError
15
- let content = std::fs::read_to_string(&path)?; // Returns io::Error
16
- let config: Config = toml::from_str(&content)?; // Returns toml::Error
17
- validate(&config)?; // Returns ValidationError
18
- Ok(config)
19
- }
20
-
21
- // No context - hard to debug
22
- fn process() -> Result<(), Box<dyn std::error::Error>> {
23
- let data = fetch()?; // Which fetch failed?
24
- transform(data)?; // What was being transformed?
25
- save()?; // Where was it saving to?
26
- Ok(())
27
- }
28
- ```
29
-
30
- ## Good
31
-
32
- ```rust
33
- use anyhow::{Context, Result};
34
-
35
- fn load_config() -> Result<Config> {
36
- let path = find_config()
37
- .context("failed to locate config file")?;
38
-
39
- let content = std::fs::read_to_string(&path)
40
- .with_context(|| format!("failed to read config from {}", path.display()))?;
41
-
42
- let config: Config = toml::from_str(&content)
43
- .context("failed to parse config as TOML")?;
44
-
45
- validate(&config)
46
- .context("config validation failed")?;
47
-
48
- Ok(config)
49
- }
50
-
51
- // Error message: "config validation failed: field 'port' must be > 0"
52
- // Full chain preserved for debugging
53
- ```
54
-
55
- ## Key Features
56
-
57
- ```rust
58
- use anyhow::{anyhow, bail, ensure, Context, Result};
59
-
60
- fn example() -> Result<()> {
61
- // Create ad-hoc errors
62
- let err = anyhow!("something went wrong");
63
-
64
- // Early return with error
65
- bail!("aborting due to {}", reason);
66
-
67
- // Assert with error
68
- ensure!(condition, "condition was false");
69
-
70
- // Add context to any error
71
- risky_operation()
72
- .context("risky operation failed")?;
73
-
74
- // Dynamic context
75
- fetch(url)
76
- .with_context(|| format!("failed to fetch {}", url))?;
77
-
78
- Ok(())
79
- }
80
- ```
81
-
82
- ## Main Function Pattern
83
-
84
- ```rust
85
- use anyhow::Result;
86
-
87
- fn main() -> Result<()> {
88
- let config = load_config()?;
89
- run_app(config)?;
90
- Ok(())
91
- }
92
-
93
- // Or with custom exit handling
94
- fn main() {
95
- if let Err(e) = run() {
96
- eprintln!("Error: {:#}", e); // Pretty-print with causes
97
- std::process::exit(1);
98
- }
99
- }
100
-
101
- fn run() -> Result<()> {
102
- // Application logic
103
- Ok(())
104
- }
105
- ```
106
-
107
- ## Error Display Formats
108
-
109
- ```rust
110
- use anyhow::Result;
111
-
112
- fn show_error(err: anyhow::Error) {
113
- // Just the top-level message
114
- println!("{}", err);
115
- // "config validation failed"
116
-
117
- // With cause chain (# alternate format)
118
- println!("{:#}", err);
119
- // "config validation failed: field 'port' must be > 0"
120
-
121
- // Debug format with backtrace
122
- println!("{:?}", err);
123
- // Full backtrace if RUST_BACKTRACE=1
124
-
125
- // Iterate through cause chain
126
- for cause in err.chain() {
127
- println!("Caused by: {}", cause);
128
- }
129
- }
130
- ```
131
-
132
- ## Combining with thiserror
133
-
134
- ```rust
135
- // In your library crate - typed errors
136
- use thiserror::Error;
137
-
138
- #[derive(Error, Debug)]
139
- pub enum ApiError {
140
- #[error("rate limited")]
141
- RateLimited,
142
- #[error("not found: {0}")]
143
- NotFound(String),
144
- }
145
-
146
- // In your application - anyhow for handling
147
- use anyhow::{Context, Result};
148
-
149
- fn fetch_user(id: u64) -> Result<User> {
150
- api::get_user(id)
151
- .with_context(|| format!("failed to fetch user {}", id))
152
- }
153
-
154
- // Can still downcast if needed
155
- fn handle_error(err: anyhow::Error) {
156
- if let Some(api_err) = err.downcast_ref::<ApiError>() {
157
- match api_err {
158
- ApiError::RateLimited => wait_and_retry(),
159
- ApiError::NotFound(id) => log_missing(id),
160
- }
161
- }
162
- }
163
- ```
164
-
165
- ## When to Use Which
166
-
167
- | Situation | Use |
168
- |-----------|-----|
169
- | Library public API | `thiserror` |
170
- | Application code | `anyhow` |
171
- | CLI tools | `anyhow` |
172
- | Internal library code | Either |
173
- | Need to match error variants | `thiserror` |
174
- | Just need to report errors | `anyhow` |
175
-
176
- ## See Also
177
-
178
- - [err-thiserror-lib](err-thiserror-lib.md) - Use thiserror for libraries
179
- - [err-context-chain](err-context-chain.md) - Add context to errors
@@ -1,144 +0,0 @@
1
- # err-context-chain
2
-
3
- > Add context with `.context()` or `.with_context()`
4
-
5
- ## Why It Matters
6
-
7
- Raw errors often lack information about what operation failed. Adding context creates an error chain that tells the full story: what you were trying to do, and why it failed.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Raw error - no context
13
- fn load_user(id: u64) -> Result<User, Error> {
14
- let path = format!("users/{}.json", id);
15
- let content = std::fs::read_to_string(&path)?;
16
- Ok(serde_json::from_str(&content)?)
17
- }
18
-
19
- // Error message: "No such file or directory (os error 2)"
20
- // Which file? What were we doing?
21
- ```
22
-
23
- ## Good
24
-
25
- ```rust
26
- use anyhow::{Context, Result};
27
-
28
- fn load_user(id: u64) -> Result<User> {
29
- let path = format!("users/{}.json", id);
30
-
31
- let content = std::fs::read_to_string(&path)
32
- .with_context(|| format!("failed to read user file: {}", path))?;
33
-
34
- let user: User = serde_json::from_str(&content)
35
- .with_context(|| format!("failed to parse user {} JSON", id))?;
36
-
37
- Ok(user)
38
- }
39
-
40
- // Error: "failed to parse user 42 JSON"
41
- // Caused by: "expected ':' at line 5 column 12"
42
- ```
43
-
44
- ## context() vs with_context()
45
-
46
- ```rust
47
- // context() - static string (slight allocation)
48
- fs::read_to_string(path)
49
- .context("failed to read config")?;
50
-
51
- // with_context() - lazy evaluation (only allocates on error)
52
- fs::read_to_string(path)
53
- .with_context(|| format!("failed to read {}", path))?;
54
-
55
- // Use with_context() when:
56
- // - Message includes runtime data (format!)
57
- // - Computing the message is expensive
58
- // - Error path is cold (most of the time)
59
- ```
60
-
61
- ## Building Context Chains
62
-
63
- ```rust
64
- fn process_order(order_id: u64) -> Result<()> {
65
- let order = fetch_order(order_id)
66
- .with_context(|| format!("failed to fetch order {}", order_id))?;
67
-
68
- let user = load_user(order.user_id)
69
- .with_context(|| format!("failed to load user for order {}", order_id))?;
70
-
71
- let payment = process_payment(&order, &user)
72
- .context("payment processing failed")?;
73
-
74
- ship_order(&order, &payment)
75
- .context("shipping failed")?;
76
-
77
- Ok(())
78
- }
79
-
80
- // Full error chain:
81
- // "shipping failed"
82
- // Caused by: "carrier API returned 503"
83
- // Caused by: "connection refused"
84
- ```
85
-
86
- ## Displaying Error Chains
87
-
88
- ```rust
89
- fn main() {
90
- if let Err(e) = run() {
91
- // Just top-level message
92
- eprintln!("Error: {}", e);
93
-
94
- // Full chain with alternate format
95
- eprintln!("Error: {:#}", e);
96
-
97
- // Debug format (includes backtrace if enabled)
98
- eprintln!("Error: {:?}", e);
99
-
100
- // Iterate through chain
101
- for (i, cause) in e.chain().enumerate() {
102
- eprintln!(" {}: {}", i, cause);
103
- }
104
- }
105
- }
106
- ```
107
-
108
- ## With thiserror
109
-
110
- ```rust
111
- use thiserror::Error;
112
-
113
- #[derive(Error, Debug)]
114
- pub enum AppError {
115
- #[error("failed to load config from {path}")]
116
- ConfigLoad {
117
- path: String,
118
- #[source]
119
- cause: std::io::Error,
120
- },
121
-
122
- #[error("failed to connect to database")]
123
- Database {
124
- #[source]
125
- cause: sqlx::Error,
126
- },
127
- }
128
-
129
- // Usage
130
- fn load_config(path: &str) -> Result<Config, AppError> {
131
- let content = std::fs::read_to_string(path)
132
- .map_err(|e| AppError::ConfigLoad {
133
- path: path.to_string(),
134
- cause: e,
135
- })?;
136
- // ...
137
- }
138
- ```
139
-
140
- ## See Also
141
-
142
- - [err-anyhow-app](err-anyhow-app.md) - Use anyhow for applications
143
- - [err-source-chain](err-source-chain.md) - Use #[source] to chain errors
144
- - [err-question-mark](err-question-mark.md) - Use ? for propagation
@@ -1,152 +0,0 @@
1
- # err-custom-type
2
-
3
- > Define custom error types for domain-specific failures
4
-
5
- ## Why It Matters
6
-
7
- Generic errors like `String`, `Box<dyn Error>`, or catch-all enums obscure what can actually go wrong. Custom error types document failure modes in the type system, enable pattern matching for specific handling, and provide clear API contracts. They make your code self-documenting and help callers handle errors appropriately.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- // Generic string errors - no structure
13
- fn validate_user(user: &User) -> Result<(), String> {
14
- if user.name.is_empty() {
15
- return Err("Name is empty".to_string());
16
- }
17
- if user.age > 150 {
18
- return Err("Age is invalid".to_string());
19
- }
20
- Ok(())
21
- }
22
-
23
- // Caller can't match on specific errors
24
- match validate_user(&user) {
25
- Ok(()) => save(user),
26
- Err(msg) => {
27
- // Can only do string comparison - fragile!
28
- if msg.contains("Name") {
29
- prompt_for_name()
30
- }
31
- }
32
- }
33
- ```
34
-
35
- ## Good
36
-
37
- ```rust
38
- use thiserror::Error;
39
-
40
- #[derive(Error, Debug)]
41
- pub enum ValidationError {
42
- #[error("name cannot be empty")]
43
- EmptyName,
44
-
45
- #[error("name exceeds maximum length of {max} characters")]
46
- NameTooLong { max: usize, actual: usize },
47
-
48
- #[error("invalid age {0}: must be between 0 and 150")]
49
- InvalidAge(u8),
50
-
51
- #[error("email format is invalid: {0}")]
52
- InvalidEmail(String),
53
- }
54
-
55
- fn validate_user(user: &User) -> Result<(), ValidationError> {
56
- if user.name.is_empty() {
57
- return Err(ValidationError::EmptyName);
58
- }
59
- if user.name.len() > 100 {
60
- return Err(ValidationError::NameTooLong {
61
- max: 100,
62
- actual: user.name.len()
63
- });
64
- }
65
- if user.age > 150 {
66
- return Err(ValidationError::InvalidAge(user.age));
67
- }
68
- Ok(())
69
- }
70
-
71
- // Caller can match specifically
72
- match validate_user(&user) {
73
- Ok(()) => save(user),
74
- Err(ValidationError::EmptyName) => prompt_for_name(),
75
- Err(ValidationError::InvalidAge(age)) => {
76
- show_error(&format!("Please enter a valid age (you entered {})", age))
77
- }
78
- Err(e) => show_error(&e.to_string()),
79
- }
80
- ```
81
-
82
- ## Error Type Design Guidelines
83
-
84
- ```rust
85
- // 1. Group related errors in domain-specific enums
86
- #[derive(Error, Debug)]
87
- pub enum AuthError {
88
- #[error("invalid credentials")]
89
- InvalidCredentials,
90
- #[error("account locked after {attempts} failed attempts")]
91
- AccountLocked { attempts: u32 },
92
- #[error("token expired")]
93
- TokenExpired,
94
- }
95
-
96
- #[derive(Error, Debug)]
97
- pub enum PaymentError {
98
- #[error("insufficient funds: need {required}, have {available}")]
99
- InsufficientFunds { required: Decimal, available: Decimal },
100
- #[error("card declined: {reason}")]
101
- CardDeclined { reason: String },
102
- }
103
-
104
- // 2. Include relevant data for error handling/display
105
- #[derive(Error, Debug)]
106
- pub enum FileError {
107
- #[error("file not found: {path}")]
108
- NotFound { path: PathBuf },
109
- #[error("permission denied for {path}")]
110
- PermissionDenied { path: PathBuf },
111
- }
112
-
113
- // 3. Consider #[non_exhaustive] for public APIs
114
- #[derive(Error, Debug)]
115
- #[non_exhaustive] // Allows adding variants without breaking changes
116
- pub enum ApiError {
117
- #[error("rate limited")]
118
- RateLimited,
119
- #[error("not found")]
120
- NotFound,
121
- }
122
- ```
123
-
124
- ## When to Use What
125
-
126
- | Error Pattern | Use Case |
127
- |---------------|----------|
128
- | Custom enum | Library with specific failure modes |
129
- | `thiserror` | Libraries needing `std::error::Error` |
130
- | `anyhow::Error` | Applications, prototypes |
131
- | Struct with source | Single error type with wrapped cause |
132
-
133
- ## Struct-Based Errors
134
-
135
- For single error types with rich context:
136
-
137
- ```rust
138
- #[derive(Error, Debug)]
139
- #[error("query failed for table '{table}' with filter '{filter}'")]
140
- pub struct QueryError {
141
- pub table: String,
142
- pub filter: String,
143
- #[source]
144
- pub source: DatabaseError,
145
- }
146
- ```
147
-
148
- ## See Also
149
-
150
- - [err-thiserror-lib](./err-thiserror-lib.md) - thiserror for error definitions
151
- - [err-anyhow-app](./err-anyhow-app.md) - When to use anyhow instead
152
- - [api-non-exhaustive](./api-non-exhaustive.md) - Forward-compatible enums
@@ -1,145 +0,0 @@
1
- # err-doc-errors
2
-
3
- > Document error conditions with `# Errors` section in doc comments
4
-
5
- ## Why It Matters
6
-
7
- Users of your API need to know what can go wrong and why. The `# Errors` documentation section is the standard Rust convention for describing when a function returns `Err`. Good error documentation helps callers handle errors appropriately and understand the contract of your API.
8
-
9
- ## Bad
10
-
11
- ```rust
12
- /// Loads a configuration from the specified path.
13
- pub fn load_config(path: &Path) -> Result<Config, ConfigError> {
14
- // No documentation of error conditions
15
- // Caller must read source code to understand what can fail
16
- }
17
-
18
- /// Parses and validates the input string.
19
- ///
20
- /// Returns the parsed value. // What about errors?
21
- pub fn parse_input(input: &str) -> Result<Value, ParseError> {
22
- // ...
23
- }
24
- ```
25
-
26
- ## Good
27
-
28
- ```rust
29
- /// Loads a configuration from the specified path.
30
- ///
31
- /// # Errors
32
- ///
33
- /// Returns an error if:
34
- /// - The file at `path` does not exist or cannot be read
35
- /// - The file contents are not valid TOML
36
- /// - Required configuration keys are missing
37
- /// - Configuration values are out of valid ranges
38
- ///
39
- /// # Examples
40
- ///
41
- /// ```
42
- /// # use mylib::{load_config, ConfigError};
43
- /// # fn main() -> Result<(), ConfigError> {
44
- /// let config = load_config("app.toml")?;
45
- /// # Ok(())
46
- /// # }
47
- /// ```
48
- pub fn load_config(path: &Path) -> Result<Config, ConfigError> {
49
- // ...
50
- }
51
-
52
- /// Parses and validates the input string as a positive integer.
53
- ///
54
- /// # Errors
55
- ///
56
- /// Returns [`ParseError::Empty`] if the input is empty.
57
- /// Returns [`ParseError::InvalidFormat`] if the input contains non-digit characters.
58
- /// Returns [`ParseError::Overflow`] if the value exceeds `i64::MAX`.
59
- /// Returns [`ParseError::NotPositive`] if the value is zero or negative.
60
- pub fn parse_positive_int(input: &str) -> Result<i64, ParseError> {
61
- // ...
62
- }
63
- ```
64
-
65
- ## Linking to Error Variants
66
-
67
- ```rust
68
- /// Attempts to connect to the database.
69
- ///
70
- /// # Errors
71
- ///
72
- /// This function will return an error if:
73
- ///
74
- /// - [`DbError::ConnectionFailed`] - The database server is unreachable
75
- /// - [`DbError::AuthenticationFailed`] - Invalid credentials
76
- /// - [`DbError::Timeout`] - Connection attempt exceeded timeout
77
- /// - [`DbError::TlsError`] - TLS handshake failed
78
- ///
79
- /// See [`DbError`] for more details on each variant.
80
- pub fn connect(config: &DbConfig) -> Result<Connection, DbError> {
81
- // ...
82
- }
83
- ```
84
-
85
- ## Panic vs Error Documentation
86
-
87
- ```rust
88
- /// Divides two numbers.
89
- ///
90
- /// # Errors
91
- ///
92
- /// Returns [`MathError::DivisionByZero`] if `divisor` is zero.
93
- ///
94
- /// # Panics
95
- ///
96
- /// Panics if called from a non-main thread (debug builds only).
97
- pub fn divide(dividend: i64, divisor: i64) -> Result<i64, MathError> {
98
- // ...
99
- }
100
- ```
101
-
102
- ## Error Section Format Options
103
-
104
- ```rust
105
- // Style 1: Bullet list (good for multiple conditions)
106
- /// # Errors
107
- ///
108
- /// Returns an error if:
109
- /// - The file does not exist
110
- /// - The file cannot be read
111
- /// - The content is invalid UTF-8
112
-
113
- // Style 2: Returns statements (good for mapping to variants)
114
- /// # Errors
115
- ///
116
- /// Returns [`Error::NotFound`] if the item doesn't exist.
117
- /// Returns [`Error::PermissionDenied`] if access is forbidden.
118
-
119
- // Style 3: Prose (good for complex conditions)
120
- /// # Errors
121
- ///
122
- /// This function returns an error when the input fails validation.
123
- /// Validation includes checking that all required fields are present,
124
- /// that numeric fields are within allowed ranges, and that string
125
- /// fields match their expected formats.
126
- ```
127
-
128
- ## Clippy Lint
129
-
130
- ```toml
131
- # Cargo.toml - require error documentation
132
- [lints.clippy]
133
- missing_errors_doc = "warn"
134
- ```
135
-
136
- ```rust
137
- // This will warn without # Errors section
138
- pub fn might_fail() -> Result<(), Error> { Ok(()) }
139
- ```
140
-
141
- ## See Also
142
-
143
- - [doc-examples-section](./doc-examples-section.md) - Examples in documentation
144
- - [err-thiserror-lib](./err-thiserror-lib.md) - Defining error types
145
- - [api-must-use](./api-must-use.md) - Marking Results as must_use