agy-superpowers 5.2.1 → 5.2.3

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 (233) hide show
  1. package/README.md +47 -150
  2. package/package.json +1 -1
  3. package/template/agent/patches/skills-patches.md +23 -0
  4. package/template/agent/rules/scratch-scripts.md +37 -0
  5. package/template/agent/rules/superpowers.md +6 -50
  6. package/template/agent/skills/brainstorming/SKILL.md +4 -3
  7. package/template/agent/skills/brainstorming/visual-companion.md +2 -3
  8. package/template/agent/skills/finishing-a-development-branch/SKILL.md +11 -16
  9. package/template/agent/skills/subagent-driven-development/SKILL.md +16 -0
  10. package/template/agent/skills/subagent-driven-development/implementer-prompt.md +4 -3
  11. package/template/agent/skills/using-git-worktrees/SKILL.md +3 -2
  12. package/template/agent/skills/using-superpowers/SKILL.md +8 -6
  13. package/template/agent/skills/using-superpowers/references/copilot-tools.md +52 -0
  14. package/template/agent/skills/writing-plans/SKILL.md +5 -3
  15. package/template/agent/skills/writing-skills/SKILL.md +1 -1
  16. package/template/agent/superpowers-version.json +2 -2
  17. package/template/agent/tmp/agent-config-backup.yml +9 -0
  18. package/template/agent/skills/ai-integrated-product/SKILL.md +0 -57
  19. package/template/agent/skills/analytics-setup/SKILL.md +0 -51
  20. package/template/agent/skills/api-design/SKILL.md +0 -193
  21. package/template/agent/skills/app-store-optimizer/SKILL.md +0 -127
  22. package/template/agent/skills/auth-and-identity/SKILL.md +0 -167
  23. package/template/agent/skills/backend-developer/SKILL.md +0 -148
  24. package/template/agent/skills/bootstrapper-finance/SKILL.md +0 -55
  25. package/template/agent/skills/chrome-extension-developer/SKILL.md +0 -53
  26. package/template/agent/skills/community-manager/SKILL.md +0 -115
  27. package/template/agent/skills/content-marketer/SKILL.md +0 -111
  28. package/template/agent/skills/conversion-optimizer/SKILL.md +0 -142
  29. package/template/agent/skills/cto-architect/SKILL.md +0 -133
  30. package/template/agent/skills/customer-success-manager/SKILL.md +0 -126
  31. package/template/agent/skills/data-analyst/SKILL.md +0 -147
  32. package/template/agent/skills/devops-engineer/SKILL.md +0 -117
  33. package/template/agent/skills/email-infrastructure/SKILL.md +0 -164
  34. package/template/agent/skills/game-design/SKILL.md +0 -194
  35. package/template/agent/skills/game-developer/SKILL.md +0 -175
  36. package/template/agent/skills/growth-hacker/SKILL.md +0 -122
  37. package/template/agent/skills/idea-validator/SKILL.md +0 -55
  38. package/template/agent/skills/indie-legal/SKILL.md +0 -53
  39. package/template/agent/skills/influencer-marketer/SKILL.md +0 -141
  40. package/template/agent/skills/landing-page-builder/SKILL.md +0 -59
  41. package/template/agent/skills/launch-strategist/SKILL.md +0 -62
  42. package/template/agent/skills/market-researcher/SKILL.md +0 -53
  43. package/template/agent/skills/micro-saas-builder/SKILL.md +0 -56
  44. package/template/agent/skills/monetization-strategist/SKILL.md +0 -119
  45. package/template/agent/skills/paid-acquisition-specialist/SKILL.md +0 -119
  46. package/template/agent/skills/pricing-psychologist/SKILL.md +0 -58
  47. package/template/agent/skills/real-time-features/SKILL.md +0 -194
  48. package/template/agent/skills/retention-specialist/SKILL.md +0 -123
  49. package/template/agent/skills/rust-developer/SKILL.md +0 -281
  50. package/template/agent/skills/rust-developer/references/rust-rules/_sections.md +0 -231
  51. package/template/agent/skills/rust-developer/references/rust-rules/anti-clone-excessive.md +0 -124
  52. package/template/agent/skills/rust-developer/references/rust-rules/anti-collect-intermediate.md +0 -131
  53. package/template/agent/skills/rust-developer/references/rust-rules/anti-empty-catch.md +0 -132
  54. package/template/agent/skills/rust-developer/references/rust-rules/anti-expect-lazy.md +0 -95
  55. package/template/agent/skills/rust-developer/references/rust-rules/anti-format-hot-path.md +0 -141
  56. package/template/agent/skills/rust-developer/references/rust-rules/anti-index-over-iter.md +0 -125
  57. package/template/agent/skills/rust-developer/references/rust-rules/anti-lock-across-await.md +0 -127
  58. package/template/agent/skills/rust-developer/references/rust-rules/anti-over-abstraction.md +0 -120
  59. package/template/agent/skills/rust-developer/references/rust-rules/anti-panic-expected.md +0 -131
  60. package/template/agent/skills/rust-developer/references/rust-rules/anti-premature-optimize.md +0 -156
  61. package/template/agent/skills/rust-developer/references/rust-rules/anti-string-for-str.md +0 -122
  62. package/template/agent/skills/rust-developer/references/rust-rules/anti-stringly-typed.md +0 -167
  63. package/template/agent/skills/rust-developer/references/rust-rules/anti-type-erasure.md +0 -134
  64. package/template/agent/skills/rust-developer/references/rust-rules/anti-unwrap-abuse.md +0 -143
  65. package/template/agent/skills/rust-developer/references/rust-rules/anti-vec-for-slice.md +0 -121
  66. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-must-use.md +0 -143
  67. package/template/agent/skills/rust-developer/references/rust-rules/api-builder-pattern.md +0 -187
  68. package/template/agent/skills/rust-developer/references/rust-rules/api-common-traits.md +0 -165
  69. package/template/agent/skills/rust-developer/references/rust-rules/api-default-impl.md +0 -177
  70. package/template/agent/skills/rust-developer/references/rust-rules/api-extension-trait.md +0 -163
  71. package/template/agent/skills/rust-developer/references/rust-rules/api-from-not-into.md +0 -146
  72. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-asref.md +0 -142
  73. package/template/agent/skills/rust-developer/references/rust-rules/api-impl-into.md +0 -160
  74. package/template/agent/skills/rust-developer/references/rust-rules/api-must-use.md +0 -125
  75. package/template/agent/skills/rust-developer/references/rust-rules/api-newtype-safety.md +0 -162
  76. package/template/agent/skills/rust-developer/references/rust-rules/api-non-exhaustive.md +0 -177
  77. package/template/agent/skills/rust-developer/references/rust-rules/api-parse-dont-validate.md +0 -184
  78. package/template/agent/skills/rust-developer/references/rust-rules/api-sealed-trait.md +0 -168
  79. package/template/agent/skills/rust-developer/references/rust-rules/api-serde-optional.md +0 -182
  80. package/template/agent/skills/rust-developer/references/rust-rules/api-typestate.md +0 -199
  81. package/template/agent/skills/rust-developer/references/rust-rules/async-bounded-channel.md +0 -175
  82. package/template/agent/skills/rust-developer/references/rust-rules/async-broadcast-pubsub.md +0 -185
  83. package/template/agent/skills/rust-developer/references/rust-rules/async-cancellation-token.md +0 -203
  84. package/template/agent/skills/rust-developer/references/rust-rules/async-clone-before-await.md +0 -171
  85. package/template/agent/skills/rust-developer/references/rust-rules/async-join-parallel.md +0 -158
  86. package/template/agent/skills/rust-developer/references/rust-rules/async-joinset-structured.md +0 -195
  87. package/template/agent/skills/rust-developer/references/rust-rules/async-mpsc-queue.md +0 -171
  88. package/template/agent/skills/rust-developer/references/rust-rules/async-no-lock-await.md +0 -156
  89. package/template/agent/skills/rust-developer/references/rust-rules/async-oneshot-response.md +0 -191
  90. package/template/agent/skills/rust-developer/references/rust-rules/async-select-racing.md +0 -198
  91. package/template/agent/skills/rust-developer/references/rust-rules/async-spawn-blocking.md +0 -154
  92. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-fs.md +0 -167
  93. package/template/agent/skills/rust-developer/references/rust-rules/async-tokio-runtime.md +0 -169
  94. package/template/agent/skills/rust-developer/references/rust-rules/async-try-join.md +0 -172
  95. package/template/agent/skills/rust-developer/references/rust-rules/async-watch-latest.md +0 -189
  96. package/template/agent/skills/rust-developer/references/rust-rules/doc-all-public.md +0 -113
  97. package/template/agent/skills/rust-developer/references/rust-rules/doc-cargo-metadata.md +0 -147
  98. package/template/agent/skills/rust-developer/references/rust-rules/doc-errors-section.md +0 -122
  99. package/template/agent/skills/rust-developer/references/rust-rules/doc-examples-section.md +0 -161
  100. package/template/agent/skills/rust-developer/references/rust-rules/doc-hidden-setup.md +0 -149
  101. package/template/agent/skills/rust-developer/references/rust-rules/doc-intra-links.md +0 -138
  102. package/template/agent/skills/rust-developer/references/rust-rules/doc-link-types.md +0 -169
  103. package/template/agent/skills/rust-developer/references/rust-rules/doc-module-inner.md +0 -116
  104. package/template/agent/skills/rust-developer/references/rust-rules/doc-panics-section.md +0 -128
  105. package/template/agent/skills/rust-developer/references/rust-rules/doc-question-mark.md +0 -136
  106. package/template/agent/skills/rust-developer/references/rust-rules/doc-safety-section.md +0 -131
  107. package/template/agent/skills/rust-developer/references/rust-rules/err-anyhow-app.md +0 -179
  108. package/template/agent/skills/rust-developer/references/rust-rules/err-context-chain.md +0 -144
  109. package/template/agent/skills/rust-developer/references/rust-rules/err-custom-type.md +0 -152
  110. package/template/agent/skills/rust-developer/references/rust-rules/err-doc-errors.md +0 -145
  111. package/template/agent/skills/rust-developer/references/rust-rules/err-expect-bugs-only.md +0 -133
  112. package/template/agent/skills/rust-developer/references/rust-rules/err-from-impl.md +0 -152
  113. package/template/agent/skills/rust-developer/references/rust-rules/err-lowercase-msg.md +0 -124
  114. package/template/agent/skills/rust-developer/references/rust-rules/err-no-unwrap-prod.md +0 -115
  115. package/template/agent/skills/rust-developer/references/rust-rules/err-question-mark.md +0 -151
  116. package/template/agent/skills/rust-developer/references/rust-rules/err-result-over-panic.md +0 -130
  117. package/template/agent/skills/rust-developer/references/rust-rules/err-source-chain.md +0 -155
  118. package/template/agent/skills/rust-developer/references/rust-rules/err-thiserror-lib.md +0 -171
  119. package/template/agent/skills/rust-developer/references/rust-rules/lint-cargo-metadata.md +0 -138
  120. package/template/agent/skills/rust-developer/references/rust-rules/lint-deny-correctness.md +0 -107
  121. package/template/agent/skills/rust-developer/references/rust-rules/lint-missing-docs.md +0 -154
  122. package/template/agent/skills/rust-developer/references/rust-rules/lint-pedantic-selective.md +0 -118
  123. package/template/agent/skills/rust-developer/references/rust-rules/lint-rustfmt-check.md +0 -157
  124. package/template/agent/skills/rust-developer/references/rust-rules/lint-unsafe-doc.md +0 -133
  125. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-complexity.md +0 -131
  126. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-perf.md +0 -136
  127. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-style.md +0 -135
  128. package/template/agent/skills/rust-developer/references/rust-rules/lint-warn-suspicious.md +0 -122
  129. package/template/agent/skills/rust-developer/references/rust-rules/lint-workspace-lints.md +0 -172
  130. package/template/agent/skills/rust-developer/references/rust-rules/mem-arena-allocator.md +0 -168
  131. package/template/agent/skills/rust-developer/references/rust-rules/mem-arrayvec.md +0 -142
  132. package/template/agent/skills/rust-developer/references/rust-rules/mem-assert-type-size.md +0 -168
  133. package/template/agent/skills/rust-developer/references/rust-rules/mem-avoid-format.md +0 -147
  134. package/template/agent/skills/rust-developer/references/rust-rules/mem-box-large-variant.md +0 -158
  135. package/template/agent/skills/rust-developer/references/rust-rules/mem-boxed-slice.md +0 -139
  136. package/template/agent/skills/rust-developer/references/rust-rules/mem-clone-from.md +0 -147
  137. package/template/agent/skills/rust-developer/references/rust-rules/mem-compact-string.md +0 -149
  138. package/template/agent/skills/rust-developer/references/rust-rules/mem-reuse-collections.md +0 -174
  139. package/template/agent/skills/rust-developer/references/rust-rules/mem-smaller-integers.md +0 -159
  140. package/template/agent/skills/rust-developer/references/rust-rules/mem-smallvec.md +0 -138
  141. package/template/agent/skills/rust-developer/references/rust-rules/mem-thinvec.md +0 -142
  142. package/template/agent/skills/rust-developer/references/rust-rules/mem-with-capacity.md +0 -156
  143. package/template/agent/skills/rust-developer/references/rust-rules/mem-write-over-format.md +0 -172
  144. package/template/agent/skills/rust-developer/references/rust-rules/mem-zero-copy.md +0 -164
  145. package/template/agent/skills/rust-developer/references/rust-rules/name-acronym-word.md +0 -99
  146. package/template/agent/skills/rust-developer/references/rust-rules/name-as-free.md +0 -104
  147. package/template/agent/skills/rust-developer/references/rust-rules/name-consts-screaming.md +0 -94
  148. package/template/agent/skills/rust-developer/references/rust-rules/name-crate-no-rs.md +0 -78
  149. package/template/agent/skills/rust-developer/references/rust-rules/name-funcs-snake.md +0 -76
  150. package/template/agent/skills/rust-developer/references/rust-rules/name-into-ownership.md +0 -123
  151. package/template/agent/skills/rust-developer/references/rust-rules/name-is-has-bool.md +0 -127
  152. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-convention.md +0 -129
  153. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-method.md +0 -131
  154. package/template/agent/skills/rust-developer/references/rust-rules/name-iter-type-match.md +0 -142
  155. package/template/agent/skills/rust-developer/references/rust-rules/name-lifetime-short.md +0 -86
  156. package/template/agent/skills/rust-developer/references/rust-rules/name-no-get-prefix.md +0 -154
  157. package/template/agent/skills/rust-developer/references/rust-rules/name-to-expensive.md +0 -118
  158. package/template/agent/skills/rust-developer/references/rust-rules/name-type-param-single.md +0 -92
  159. package/template/agent/skills/rust-developer/references/rust-rules/name-types-camel.md +0 -65
  160. package/template/agent/skills/rust-developer/references/rust-rules/name-variants-camel.md +0 -101
  161. package/template/agent/skills/rust-developer/references/rust-rules/opt-bounds-check.md +0 -161
  162. package/template/agent/skills/rust-developer/references/rust-rules/opt-cache-friendly.md +0 -187
  163. package/template/agent/skills/rust-developer/references/rust-rules/opt-codegen-units.md +0 -142
  164. package/template/agent/skills/rust-developer/references/rust-rules/opt-cold-unlikely.md +0 -152
  165. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-always-rare.md +0 -141
  166. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-never-cold.md +0 -181
  167. package/template/agent/skills/rust-developer/references/rust-rules/opt-inline-small.md +0 -160
  168. package/template/agent/skills/rust-developer/references/rust-rules/opt-likely-hint.md +0 -171
  169. package/template/agent/skills/rust-developer/references/rust-rules/opt-lto-release.md +0 -130
  170. package/template/agent/skills/rust-developer/references/rust-rules/opt-pgo-profile.md +0 -167
  171. package/template/agent/skills/rust-developer/references/rust-rules/opt-simd-portable.md +0 -144
  172. package/template/agent/skills/rust-developer/references/rust-rules/opt-target-cpu.md +0 -154
  173. package/template/agent/skills/rust-developer/references/rust-rules/own-arc-shared.md +0 -141
  174. package/template/agent/skills/rust-developer/references/rust-rules/own-borrow-over-clone.md +0 -95
  175. package/template/agent/skills/rust-developer/references/rust-rules/own-clone-explicit.md +0 -135
  176. package/template/agent/skills/rust-developer/references/rust-rules/own-copy-small.md +0 -124
  177. package/template/agent/skills/rust-developer/references/rust-rules/own-cow-conditional.md +0 -135
  178. package/template/agent/skills/rust-developer/references/rust-rules/own-lifetime-elision.md +0 -134
  179. package/template/agent/skills/rust-developer/references/rust-rules/own-move-large.md +0 -134
  180. package/template/agent/skills/rust-developer/references/rust-rules/own-mutex-interior.md +0 -105
  181. package/template/agent/skills/rust-developer/references/rust-rules/own-rc-single-thread.md +0 -65
  182. package/template/agent/skills/rust-developer/references/rust-rules/own-refcell-interior.md +0 -97
  183. package/template/agent/skills/rust-developer/references/rust-rules/own-rwlock-readers.md +0 -122
  184. package/template/agent/skills/rust-developer/references/rust-rules/own-slice-over-vec.md +0 -119
  185. package/template/agent/skills/rust-developer/references/rust-rules/perf-black-box-bench.md +0 -153
  186. package/template/agent/skills/rust-developer/references/rust-rules/perf-chain-avoid.md +0 -136
  187. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-into.md +0 -133
  188. package/template/agent/skills/rust-developer/references/rust-rules/perf-collect-once.md +0 -120
  189. package/template/agent/skills/rust-developer/references/rust-rules/perf-drain-reuse.md +0 -137
  190. package/template/agent/skills/rust-developer/references/rust-rules/perf-entry-api.md +0 -134
  191. package/template/agent/skills/rust-developer/references/rust-rules/perf-extend-batch.md +0 -150
  192. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-lazy.md +0 -123
  193. package/template/agent/skills/rust-developer/references/rust-rules/perf-iter-over-index.md +0 -113
  194. package/template/agent/skills/rust-developer/references/rust-rules/perf-profile-first.md +0 -175
  195. package/template/agent/skills/rust-developer/references/rust-rules/perf-release-profile.md +0 -149
  196. package/template/agent/skills/rust-developer/references/rust-rules/proj-bin-dir.md +0 -142
  197. package/template/agent/skills/rust-developer/references/rust-rules/proj-flat-small.md +0 -133
  198. package/template/agent/skills/rust-developer/references/rust-rules/proj-lib-main-split.md +0 -148
  199. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-by-feature.md +0 -130
  200. package/template/agent/skills/rust-developer/references/rust-rules/proj-mod-rs-dir.md +0 -120
  201. package/template/agent/skills/rust-developer/references/rust-rules/proj-prelude-module.md +0 -155
  202. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-crate-internal.md +0 -139
  203. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-super-parent.md +0 -135
  204. package/template/agent/skills/rust-developer/references/rust-rules/proj-pub-use-reexport.md +0 -162
  205. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-deps.md +0 -186
  206. package/template/agent/skills/rust-developer/references/rust-rules/proj-workspace-large.md +0 -162
  207. package/template/agent/skills/rust-developer/references/rust-rules/test-arrange-act-assert.md +0 -160
  208. package/template/agent/skills/rust-developer/references/rust-rules/test-cfg-test-module.md +0 -151
  209. package/template/agent/skills/rust-developer/references/rust-rules/test-criterion-bench.md +0 -171
  210. package/template/agent/skills/rust-developer/references/rust-rules/test-descriptive-names.md +0 -142
  211. package/template/agent/skills/rust-developer/references/rust-rules/test-doctest-examples.md +0 -168
  212. package/template/agent/skills/rust-developer/references/rust-rules/test-fixture-raii.md +0 -151
  213. package/template/agent/skills/rust-developer/references/rust-rules/test-integration-dir.md +0 -144
  214. package/template/agent/skills/rust-developer/references/rust-rules/test-mock-traits.md +0 -189
  215. package/template/agent/skills/rust-developer/references/rust-rules/test-mockall-mocking.md +0 -226
  216. package/template/agent/skills/rust-developer/references/rust-rules/test-proptest-properties.md +0 -161
  217. package/template/agent/skills/rust-developer/references/rust-rules/test-should-panic.md +0 -130
  218. package/template/agent/skills/rust-developer/references/rust-rules/test-tokio-async.md +0 -154
  219. package/template/agent/skills/rust-developer/references/rust-rules/test-use-super.md +0 -127
  220. package/template/agent/skills/rust-developer/references/rust-rules/type-enum-states.md +0 -154
  221. package/template/agent/skills/rust-developer/references/rust-rules/type-generic-bounds.md +0 -142
  222. package/template/agent/skills/rust-developer/references/rust-rules/type-never-diverge.md +0 -146
  223. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-ids.md +0 -160
  224. package/template/agent/skills/rust-developer/references/rust-rules/type-newtype-validated.md +0 -159
  225. package/template/agent/skills/rust-developer/references/rust-rules/type-no-stringly.md +0 -144
  226. package/template/agent/skills/rust-developer/references/rust-rules/type-option-nullable.md +0 -137
  227. package/template/agent/skills/rust-developer/references/rust-rules/type-phantom-marker.md +0 -188
  228. package/template/agent/skills/rust-developer/references/rust-rules/type-repr-transparent.md +0 -143
  229. package/template/agent/skills/rust-developer/references/rust-rules/type-result-fallible.md +0 -131
  230. package/template/agent/skills/saas-architect/SKILL.md +0 -139
  231. package/template/agent/skills/security-engineer/SKILL.md +0 -133
  232. package/template/agent/skills/seo-specialist/SKILL.md +0 -130
  233. 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