agentic-loop 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/.claude/commands/explain.md +114 -0
  2. package/.claude/commands/idea.md +398 -0
  3. package/.claude/commands/my-dna.md +122 -0
  4. package/.claude/commands/prd.md +286 -0
  5. package/.claude/commands/review.md +167 -0
  6. package/.claude/commands/sign.md +32 -0
  7. package/.claude/commands/styleguide.md +450 -0
  8. package/.claude/commands/tour.md +301 -0
  9. package/.claude/commands/vibe-check.md +116 -0
  10. package/.claude/commands/vibe-help.md +47 -0
  11. package/.claude/commands/vibe-list.md +203 -0
  12. package/.pre-commit-hooks.yaml +102 -0
  13. package/LICENSE +21 -0
  14. package/README.md +238 -0
  15. package/bin/agentic-loop.sh +24 -0
  16. package/bin/postinstall.sh +29 -0
  17. package/bin/ralph.sh +171 -0
  18. package/bin/vibe-check.js +19 -0
  19. package/dist/checks/check-any-types.d.ts +6 -0
  20. package/dist/checks/check-any-types.d.ts.map +1 -0
  21. package/dist/checks/check-any-types.js +73 -0
  22. package/dist/checks/check-any-types.js.map +1 -0
  23. package/dist/checks/check-commented-code.d.ts +6 -0
  24. package/dist/checks/check-commented-code.d.ts.map +1 -0
  25. package/dist/checks/check-commented-code.js +81 -0
  26. package/dist/checks/check-commented-code.js.map +1 -0
  27. package/dist/checks/check-console-error.d.ts +6 -0
  28. package/dist/checks/check-console-error.d.ts.map +1 -0
  29. package/dist/checks/check-console-error.js +41 -0
  30. package/dist/checks/check-console-error.js.map +1 -0
  31. package/dist/checks/check-debug-statements.d.ts +6 -0
  32. package/dist/checks/check-debug-statements.d.ts.map +1 -0
  33. package/dist/checks/check-debug-statements.js +120 -0
  34. package/dist/checks/check-debug-statements.js.map +1 -0
  35. package/dist/checks/check-deep-nesting.d.ts +6 -0
  36. package/dist/checks/check-deep-nesting.d.ts.map +1 -0
  37. package/dist/checks/check-deep-nesting.js +116 -0
  38. package/dist/checks/check-deep-nesting.js.map +1 -0
  39. package/dist/checks/check-docker-platform.d.ts +6 -0
  40. package/dist/checks/check-docker-platform.d.ts.map +1 -0
  41. package/dist/checks/check-docker-platform.js +42 -0
  42. package/dist/checks/check-docker-platform.js.map +1 -0
  43. package/dist/checks/check-dry-violations.d.ts +6 -0
  44. package/dist/checks/check-dry-violations.d.ts.map +1 -0
  45. package/dist/checks/check-dry-violations.js +124 -0
  46. package/dist/checks/check-dry-violations.js.map +1 -0
  47. package/dist/checks/check-empty-catch.d.ts +6 -0
  48. package/dist/checks/check-empty-catch.d.ts.map +1 -0
  49. package/dist/checks/check-empty-catch.js +111 -0
  50. package/dist/checks/check-empty-catch.js.map +1 -0
  51. package/dist/checks/check-function-length.d.ts +6 -0
  52. package/dist/checks/check-function-length.d.ts.map +1 -0
  53. package/dist/checks/check-function-length.js +152 -0
  54. package/dist/checks/check-function-length.js.map +1 -0
  55. package/dist/checks/check-hardcoded-ai-models.d.ts +10 -0
  56. package/dist/checks/check-hardcoded-ai-models.d.ts.map +1 -0
  57. package/dist/checks/check-hardcoded-ai-models.js +102 -0
  58. package/dist/checks/check-hardcoded-ai-models.js.map +1 -0
  59. package/dist/checks/check-hardcoded-urls.d.ts +6 -0
  60. package/dist/checks/check-hardcoded-urls.d.ts.map +1 -0
  61. package/dist/checks/check-hardcoded-urls.js +124 -0
  62. package/dist/checks/check-hardcoded-urls.js.map +1 -0
  63. package/dist/checks/check-magic-numbers.d.ts +6 -0
  64. package/dist/checks/check-magic-numbers.d.ts.map +1 -0
  65. package/dist/checks/check-magic-numbers.js +116 -0
  66. package/dist/checks/check-magic-numbers.js.map +1 -0
  67. package/dist/checks/check-secrets.d.ts +6 -0
  68. package/dist/checks/check-secrets.d.ts.map +1 -0
  69. package/dist/checks/check-secrets.js +138 -0
  70. package/dist/checks/check-secrets.js.map +1 -0
  71. package/dist/checks/check-snake-case-ts.d.ts +6 -0
  72. package/dist/checks/check-snake-case-ts.d.ts.map +1 -0
  73. package/dist/checks/check-snake-case-ts.js +78 -0
  74. package/dist/checks/check-snake-case-ts.js.map +1 -0
  75. package/dist/checks/check-todo-fixme.d.ts +6 -0
  76. package/dist/checks/check-todo-fixme.d.ts.map +1 -0
  77. package/dist/checks/check-todo-fixme.js +41 -0
  78. package/dist/checks/check-todo-fixme.js.map +1 -0
  79. package/dist/checks/check-unsafe-html.d.ts +6 -0
  80. package/dist/checks/check-unsafe-html.d.ts.map +1 -0
  81. package/dist/checks/check-unsafe-html.js +101 -0
  82. package/dist/checks/check-unsafe-html.js.map +1 -0
  83. package/dist/checks/index.d.ts +30 -0
  84. package/dist/checks/index.d.ts.map +1 -0
  85. package/dist/checks/index.js +57 -0
  86. package/dist/checks/index.js.map +1 -0
  87. package/dist/cli.d.ts +13 -0
  88. package/dist/cli.d.ts.map +1 -0
  89. package/dist/cli.js +208 -0
  90. package/dist/cli.js.map +1 -0
  91. package/dist/index.d.ts +9 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +10 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/utils/file-reader.d.ts +24 -0
  96. package/dist/utils/file-reader.d.ts.map +1 -0
  97. package/dist/utils/file-reader.js +146 -0
  98. package/dist/utils/file-reader.js.map +1 -0
  99. package/dist/utils/patterns.d.ts +27 -0
  100. package/dist/utils/patterns.d.ts.map +1 -0
  101. package/dist/utils/patterns.js +84 -0
  102. package/dist/utils/patterns.js.map +1 -0
  103. package/dist/utils/reporters.d.ts +21 -0
  104. package/dist/utils/reporters.d.ts.map +1 -0
  105. package/dist/utils/reporters.js +115 -0
  106. package/dist/utils/reporters.js.map +1 -0
  107. package/dist/utils/types.d.ts +71 -0
  108. package/dist/utils/types.d.ts.map +1 -0
  109. package/dist/utils/types.js +5 -0
  110. package/dist/utils/types.js.map +1 -0
  111. package/package.json +83 -0
  112. package/ralph/api.sh +216 -0
  113. package/ralph/backup.sh +838 -0
  114. package/ralph/browser-verify/README.md +135 -0
  115. package/ralph/browser-verify/verify.ts +450 -0
  116. package/ralph/checks/check-fastapi-responses.py +155 -0
  117. package/ralph/hooks/hooks-config.json +72 -0
  118. package/ralph/hooks/inject-context.sh +44 -0
  119. package/ralph/hooks/install.sh +207 -0
  120. package/ralph/hooks/log-tools.sh +45 -0
  121. package/ralph/hooks/protect-prd.sh +27 -0
  122. package/ralph/hooks/save-learnings.sh +36 -0
  123. package/ralph/hooks/warn-debug.sh +54 -0
  124. package/ralph/hooks/warn-empty-catch.sh +63 -0
  125. package/ralph/hooks/warn-secrets.sh +89 -0
  126. package/ralph/hooks/warn-urls.sh +77 -0
  127. package/ralph/init.sh +515 -0
  128. package/ralph/loop.sh +730 -0
  129. package/ralph/playwright.sh +238 -0
  130. package/ralph/prd.sh +295 -0
  131. package/ralph/setup/feature-tour.sh +155 -0
  132. package/ralph/setup/quick-setup.sh +239 -0
  133. package/ralph/setup/tutorial.sh +159 -0
  134. package/ralph/setup/ui.sh +136 -0
  135. package/ralph/setup.sh +401 -0
  136. package/ralph/signs.sh +150 -0
  137. package/ralph/utils.sh +682 -0
  138. package/ralph/verify/browser.sh +324 -0
  139. package/ralph/verify/lint.sh +363 -0
  140. package/ralph/verify/review.sh +152 -0
  141. package/ralph/verify/tests.sh +81 -0
  142. package/ralph/verify.sh +268 -0
  143. package/templates/PROMPT.md +235 -0
  144. package/templates/config/fullstack.json +86 -0
  145. package/templates/config/go.json +81 -0
  146. package/templates/config/minimal.json +76 -0
  147. package/templates/config/node.json +81 -0
  148. package/templates/config/python.json +81 -0
  149. package/templates/config/rust.json +81 -0
  150. package/templates/examples/CLAUDE-django.md +174 -0
  151. package/templates/examples/CLAUDE-fastapi.md +270 -0
  152. package/templates/examples/CLAUDE-fastmcp.md +352 -0
  153. package/templates/examples/CLAUDE-fullstack.md +256 -0
  154. package/templates/examples/CLAUDE-node.md +246 -0
  155. package/templates/examples/CLAUDE-react.md +138 -0
  156. package/templates/optional/cursorrules.template +147 -0
  157. package/templates/optional/eslint.config.js +34 -0
  158. package/templates/optional/lint-staged.config.js +34 -0
  159. package/templates/optional/ruff.toml +125 -0
  160. package/templates/optional/vibe-check.yml +116 -0
  161. package/templates/optional/vscode-settings.json +127 -0
  162. package/templates/signs.json +46 -0
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env bash
2
+ # warn-empty-catch.sh - Warn about empty catch blocks that silently swallow errors
3
+ # Hook: PostToolUse matcher: "Edit|Write"
4
+
5
+ set -euo pipefail
6
+
7
+ INPUT=$(cat)
8
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""')
9
+ FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
10
+
11
+ # Only check code files
12
+ case "$FILE_PATH" in
13
+ *.ts|*.tsx|*.js|*.jsx|*.py)
14
+ ;;
15
+ *)
16
+ echo '{"continue": true}'
17
+ exit 0
18
+ ;;
19
+ esac
20
+
21
+ # Get the content that was written
22
+ NEW_CONTENT=""
23
+ if [[ "$TOOL_NAME" == "Write" ]]; then
24
+ NEW_CONTENT=$(echo "$INPUT" | jq -r '.tool_input.content // ""')
25
+ elif [[ "$TOOL_NAME" == "Edit" ]]; then
26
+ NEW_CONTENT=$(echo "$INPUT" | jq -r '.tool_input.new_string // ""')
27
+ fi
28
+
29
+ WARNINGS=""
30
+
31
+ # JavaScript/TypeScript: catch (e) { } or catch { }
32
+ if echo "$NEW_CONTENT" | grep -qE 'catch\s*\([^)]*\)\s*\{\s*\}'; then
33
+ WARNINGS="⚠️ Empty catch block detected. Handle the error or add a comment explaining why it's ignored."
34
+ fi
35
+
36
+ # Also check for catch with only a comment (no actual handling)
37
+ if echo "$NEW_CONTENT" | grep -qE 'catch\s*\([^)]*\)\s*\{\s*(//[^\n]*)?\s*\}'; then
38
+ if [[ -z "$WARNINGS" ]]; then
39
+ WARNINGS="⚠️ Catch block with no error handling. Consider logging or rethrowing the error."
40
+ fi
41
+ fi
42
+
43
+ # Python: except: pass or except Exception: pass
44
+ if echo "$NEW_CONTENT" | grep -qE 'except.*:\s*pass\s*$'; then
45
+ WARNINGS="⚠️ Empty except block (pass). Handle the exception or add logging."
46
+ fi
47
+
48
+ # Python: bare except with just pass on next line
49
+ if echo "$NEW_CONTENT" | grep -qE 'except.*:\s*$' && echo "$NEW_CONTENT" | grep -qE '^\s*pass\s*$'; then
50
+ if [[ -z "$WARNINGS" ]]; then
51
+ WARNINGS="⚠️ Except block with only 'pass'. Consider logging or reraising the exception."
52
+ fi
53
+ fi
54
+
55
+ # Block if empty catch detected
56
+ if [[ -n "$WARNINGS" ]]; then
57
+ jq -n --arg warn "$WARNINGS" '{
58
+ "continue": false,
59
+ "message": $warn
60
+ }'
61
+ else
62
+ echo '{"continue": true}'
63
+ fi
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env bash
2
+ # warn-secrets.sh - Warn about potential secrets in written code
3
+ # Hook: PostToolUse matcher: "Edit|Write"
4
+ #
5
+ # Mirrors the pre-commit check-secrets patterns for consistency
6
+
7
+ set -euo pipefail
8
+
9
+ INPUT=$(cat)
10
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""')
11
+ FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
12
+
13
+ # Only check code files
14
+ case "$FILE_PATH" in
15
+ *.ts|*.tsx|*.js|*.jsx|*.py|*.json|*.yaml|*.yml|*.env*)
16
+ ;;
17
+ *)
18
+ echo '{"continue": true}'
19
+ exit 0
20
+ ;;
21
+ esac
22
+
23
+ # Get the content that was written
24
+ NEW_CONTENT=""
25
+ if [[ "$TOOL_NAME" == "Write" ]]; then
26
+ NEW_CONTENT=$(echo "$INPUT" | jq -r '.tool_input.content // ""')
27
+ elif [[ "$TOOL_NAME" == "Edit" ]]; then
28
+ NEW_CONTENT=$(echo "$INPUT" | jq -r '.tool_input.new_string // ""')
29
+ fi
30
+
31
+ WARNINGS=""
32
+
33
+ # AWS Access Key (AKIA followed by 16 alphanumeric chars)
34
+ if echo "$NEW_CONTENT" | grep -qE 'AKIA[0-9A-Z]{16}'; then
35
+ WARNINGS="🚨 SECURITY: Possible AWS Access Key detected! Use environment variables."
36
+ fi
37
+
38
+ # Stripe keys (sk_live_* or sk_test_*)
39
+ if echo "$NEW_CONTENT" | grep -qE 'sk_(live|test)_[0-9a-zA-Z]{24,}'; then
40
+ WARNINGS="${WARNINGS}\n🚨 SECURITY: Stripe API key detected! Use environment variables."
41
+ fi
42
+
43
+ # GitHub tokens (ghp_, gho_, ghu_, ghs_, ghr_)
44
+ if echo "$NEW_CONTENT" | grep -qE 'gh[pousr]_[A-Za-z0-9_]{36,}'; then
45
+ WARNINGS="${WARNINGS}\n🚨 SECURITY: GitHub token detected! Use environment variables."
46
+ fi
47
+
48
+ # Slack tokens (xoxb-, xoxp-, xoxa-, xoxr-, xoxs-)
49
+ if echo "$NEW_CONTENT" | grep -qE 'xox[baprs]-[0-9]{10,}-[0-9a-zA-Z]{24,}'; then
50
+ WARNINGS="${WARNINGS}\n🚨 SECURITY: Slack token detected! Use environment variables."
51
+ fi
52
+
53
+ # SendGrid keys (SG.*)
54
+ if echo "$NEW_CONTENT" | grep -qE 'SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43}'; then
55
+ WARNINGS="${WARNINGS}\n🚨 SECURITY: SendGrid API key detected! Use environment variables."
56
+ fi
57
+
58
+ # Private keys
59
+ if echo "$NEW_CONTENT" | grep -qE '-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----'; then
60
+ WARNINGS="${WARNINGS}\n🚨 SECURITY: Private key detected! Never commit private keys."
61
+ fi
62
+
63
+ # Generic API key patterns (api_key = "...", apikey: "...", etc.)
64
+ if echo "$NEW_CONTENT" | grep -qiE '(api[_-]?key|api[_-]?secret)\s*[:=]\s*['"'"'"][a-zA-Z0-9_\-]{20,}['"'"'"]'; then
65
+ # Check it's not a placeholder
66
+ if ! echo "$NEW_CONTENT" | grep -qiE '(example|placeholder|your[_-]?key|xxx|test|dummy|fake|sample|demo)'; then
67
+ WARNINGS="${WARNINGS}\n⚠️ Possible hardcoded API key - use environment variables."
68
+ fi
69
+ fi
70
+
71
+ # Generic secrets (password = "...", token = "...", etc.)
72
+ if echo "$NEW_CONTENT" | grep -qiE '(password|passwd|pwd|secret|token)\s*[:=]\s*['"'"'"][^'"'"'"]{8,}['"'"'"]'; then
73
+ # Check it's not a placeholder or type annotation
74
+ if ! echo "$NEW_CONTENT" | grep -qiE '(example|placeholder|xxx|test|dummy|type|interface|password:)'; then
75
+ WARNINGS="${WARNINGS}\n⚠️ Possible hardcoded secret - use environment variables."
76
+ fi
77
+ fi
78
+
79
+ # Output warning as additional context (non-blocking)
80
+ if [[ -n "$WARNINGS" ]]; then
81
+ jq -n --arg warn "$WARNINGS" '{
82
+ "continue": true,
83
+ "hookSpecificOutput": {
84
+ "additionalContext": $warn
85
+ }
86
+ }'
87
+ else
88
+ echo '{"continue": true}'
89
+ fi
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env bash
2
+ # warn-urls.sh - Warn about hardcoded URLs in written code
3
+ # Hook: PostToolUse matcher: "Edit|Write"
4
+ #
5
+ # Mirrors the pre-commit check-hardcoded-urls patterns for consistency
6
+
7
+ set -euo pipefail
8
+
9
+ INPUT=$(cat)
10
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""')
11
+ FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
12
+
13
+ # Only check code files (skip test files)
14
+ case "$FILE_PATH" in
15
+ *.test.*|*.spec.*|*/__tests__/*|*/test/*|*/fixtures/*)
16
+ echo '{"continue": true}'
17
+ exit 0
18
+ ;;
19
+ *.ts|*.tsx|*.js|*.jsx|*.py)
20
+ ;;
21
+ *)
22
+ echo '{"continue": true}'
23
+ exit 0
24
+ ;;
25
+ esac
26
+
27
+ # Get the content that was written
28
+ NEW_CONTENT=""
29
+ if [[ "$TOOL_NAME" == "Write" ]]; then
30
+ NEW_CONTENT=$(echo "$INPUT" | jq -r '.tool_input.content // ""')
31
+ elif [[ "$TOOL_NAME" == "Edit" ]]; then
32
+ NEW_CONTENT=$(echo "$INPUT" | jq -r '.tool_input.new_string // ""')
33
+ fi
34
+
35
+ WARNINGS=""
36
+
37
+ # Check for localhost URLs
38
+ if echo "$NEW_CONTENT" | grep -qE 'https?://localhost(:[0-9]+)?'; then
39
+ # Skip if it's in a fallback pattern (|| or ?? or default)
40
+ if ! echo "$NEW_CONTENT" | grep -qE '(\|\||\?\?|default|fallback).*localhost'; then
41
+ WARNINGS="⚠️ Hardcoded localhost URL detected - use environment variable (e.g., process.env.API_URL)"
42
+ fi
43
+ fi
44
+
45
+ # Check for 127.0.0.1 URLs
46
+ if echo "$NEW_CONTENT" | grep -qE 'https?://127\.0\.0\.1(:[0-9]+)?'; then
47
+ if ! echo "$NEW_CONTENT" | grep -qE '(\|\||\?\?|default|fallback).*127\.0\.0\.1'; then
48
+ WARNINGS="${WARNINGS}\n⚠️ Hardcoded 127.0.0.1 URL detected - use environment variable"
49
+ fi
50
+ fi
51
+
52
+ # Check for hardcoded production-looking URLs (skip CDNs and common safe domains)
53
+ SAFE_DOMAINS="cdn.jsdelivr.net|cdnjs.cloudflare.com|unpkg.com|fonts.googleapis.com|fonts.gstatic.com|api.github.com|raw.githubusercontent.com|registry.npmjs.org|schema.org|www.w3.org|example.com|example.org"
54
+
55
+ # Look for https:// URLs that aren't safe domains
56
+ PROD_URLS=$(echo "$NEW_CONTENT" | grep -oE 'https://[a-zA-Z0-9][a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' | grep -vE "$SAFE_DOMAINS" || true)
57
+
58
+ if [[ -n "$PROD_URLS" ]]; then
59
+ # Skip if they look like example/placeholder URLs
60
+ PROD_URLS=$(echo "$PROD_URLS" | grep -v -E '(example|placeholder|test|mock)' || true)
61
+ if [[ -n "$PROD_URLS" ]]; then
62
+ FIRST_URL=$(echo "$PROD_URLS" | head -1)
63
+ WARNINGS="${WARNINGS}\n⚠️ Hardcoded URL ($FIRST_URL) - consider using environment variable"
64
+ fi
65
+ fi
66
+
67
+ # Output warning as additional context (non-blocking)
68
+ if [[ -n "$WARNINGS" ]]; then
69
+ jq -n --arg warn "$WARNINGS" '{
70
+ "continue": true,
71
+ "hookSpecificOutput": {
72
+ "additionalContext": $warn
73
+ }
74
+ }'
75
+ else
76
+ echo '{"continue": true}'
77
+ fi