aiden-runtime 3.19.5 → 3.19.7

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 (107) hide show
  1. package/README.md +1 -1
  2. package/dist/api/server.js +24 -25
  3. package/dist/core/agentLoop.js +8 -6
  4. package/dist/core/aidenPersonality.js +20 -3
  5. package/dist/core/protectedContext.js +15 -2
  6. package/dist/core/skillLoader.js +2 -0
  7. package/dist/core/skillTeacher.js +18 -5
  8. package/dist/core/version.js +1 -1
  9. package/dist-bundle/cli.js +50 -18
  10. package/dist-bundle/index.js +73 -35
  11. package/package.json +2 -1
  12. package/scripts/postinstall.js +70 -1
  13. package/workspace-templates/HEARTBEAT.md +16 -0
  14. package/workspace-templates/SOUL.md +267 -0
  15. package/workspace-templates/STANDING_ORDERS.md +21 -0
  16. package/workspace-templates/permissions.yaml +180 -0
  17. package/workspace-templates/skills/architecture-diagram/SKILL.md +126 -0
  18. package/workspace-templates/skills/architecture-diagram/skill.json +25 -0
  19. package/workspace-templates/skills/arxiv/SKILL.md +124 -0
  20. package/workspace-templates/skills/arxiv/skill.json +26 -0
  21. package/workspace-templates/skills/ascii-art/SKILL.md +142 -0
  22. package/workspace-templates/skills/ascii-art/skill.json +26 -0
  23. package/workspace-templates/skills/blogwatcher/SKILL.md +147 -0
  24. package/workspace-templates/skills/blogwatcher/skill.json +26 -0
  25. package/workspace-templates/skills/censys/SKILL.md +104 -0
  26. package/workspace-templates/skills/censys/index.ts +133 -0
  27. package/workspace-templates/skills/censys/skill.json +25 -0
  28. package/workspace-templates/skills/clipboard-history/SKILL.md +101 -0
  29. package/workspace-templates/skills/clipboard-history/skill.json +23 -0
  30. package/workspace-templates/skills/crt-sh/SKILL.md +102 -0
  31. package/workspace-templates/skills/crt-sh/index.ts +59 -0
  32. package/workspace-templates/skills/crt-sh/skill.json +25 -0
  33. package/workspace-templates/skills/cveapi/SKILL.md +114 -0
  34. package/workspace-templates/skills/cveapi/index.ts +249 -0
  35. package/workspace-templates/skills/cveapi/skill.json +25 -0
  36. package/workspace-templates/skills/docker-management/SKILL.md +156 -0
  37. package/workspace-templates/skills/docker-management/skill.json +25 -0
  38. package/workspace-templates/skills/excalidraw/SKILL.md +148 -0
  39. package/workspace-templates/skills/excalidraw/skill.json +25 -0
  40. package/workspace-templates/skills/explainshell/SKILL.md +93 -0
  41. package/workspace-templates/skills/explainshell/index.ts +132 -0
  42. package/workspace-templates/skills/explainshell/skill.json +25 -0
  43. package/workspace-templates/skills/financial_research/SKILL.md +21 -0
  44. package/workspace-templates/skills/financial_research/skill.json +24 -0
  45. package/workspace-templates/skills/gif-search/SKILL.md +122 -0
  46. package/workspace-templates/skills/gif-search/skill.json +25 -0
  47. package/workspace-templates/skills/github-auth/SKILL.md +134 -0
  48. package/workspace-templates/skills/github-auth/skill.json +26 -0
  49. package/workspace-templates/skills/github-issues/SKILL.md +130 -0
  50. package/workspace-templates/skills/github-issues/skill.json +25 -0
  51. package/workspace-templates/skills/github-pr-workflow/SKILL.md +143 -0
  52. package/workspace-templates/skills/github-pr-workflow/skill.json +26 -0
  53. package/workspace-templates/skills/github-repo-management/SKILL.md +147 -0
  54. package/workspace-templates/skills/github-repo-management/skill.json +26 -0
  55. package/workspace-templates/skills/google-workspace/SKILL.md +110 -0
  56. package/workspace-templates/skills/google-workspace/skill.json +26 -0
  57. package/workspace-templates/skills/greynoise/SKILL.md +96 -0
  58. package/workspace-templates/skills/greynoise/index.ts +107 -0
  59. package/workspace-templates/skills/greynoise/skill.json +25 -0
  60. package/workspace-templates/skills/haveibeenpwned/SKILL.md +100 -0
  61. package/workspace-templates/skills/haveibeenpwned/index.ts +72 -0
  62. package/workspace-templates/skills/haveibeenpwned/skill.json +24 -0
  63. package/workspace-templates/skills/jupyter-live-kernel/SKILL.md +116 -0
  64. package/workspace-templates/skills/jupyter-live-kernel/skill.json +25 -0
  65. package/workspace-templates/skills/linear/SKILL.md +107 -0
  66. package/workspace-templates/skills/linear/skill.json +25 -0
  67. package/workspace-templates/skills/nano-pdf/SKILL.md +113 -0
  68. package/workspace-templates/skills/nano-pdf/skill.json +26 -0
  69. package/workspace-templates/skills/notion/SKILL.md +108 -0
  70. package/workspace-templates/skills/notion/skill.json +24 -0
  71. package/workspace-templates/skills/obsidian/SKILL.md +115 -0
  72. package/workspace-templates/skills/obsidian/skill.json +24 -0
  73. package/workspace-templates/skills/ocr-and-documents/SKILL.md +125 -0
  74. package/workspace-templates/skills/ocr-and-documents/skill.json +26 -0
  75. package/workspace-templates/skills/p5js/SKILL.md +163 -0
  76. package/workspace-templates/skills/p5js/skill.json +24 -0
  77. package/workspace-templates/skills/research-paper-writing/SKILL.md +158 -0
  78. package/workspace-templates/skills/research-paper-writing/skill.json +26 -0
  79. package/workspace-templates/skills/securityheaders/SKILL.md +99 -0
  80. package/workspace-templates/skills/securityheaders/index.ts +213 -0
  81. package/workspace-templates/skills/securityheaders/skill.json +26 -0
  82. package/workspace-templates/skills/shodan/SKILL.md +113 -0
  83. package/workspace-templates/skills/shodan/index.ts +94 -0
  84. package/workspace-templates/skills/shodan/skill.json +26 -0
  85. package/workspace-templates/skills/songsee/SKILL.md +152 -0
  86. package/workspace-templates/skills/songsee/skill.json +25 -0
  87. package/workspace-templates/skills/ssllabs/SKILL.md +107 -0
  88. package/workspace-templates/skills/ssllabs/index.ts +208 -0
  89. package/workspace-templates/skills/ssllabs/skill.json +27 -0
  90. package/workspace-templates/skills/stable-diffusion-image-generation/SKILL.md +136 -0
  91. package/workspace-templates/skills/stable-diffusion-image-generation/skill.json +24 -0
  92. package/workspace-templates/skills/systematic-debugging/SKILL.md +131 -0
  93. package/workspace-templates/skills/systematic-debugging/skill.json +25 -0
  94. package/workspace-templates/skills/test-driven-development/SKILL.md +164 -0
  95. package/workspace-templates/skills/test-driven-development/skill.json +25 -0
  96. package/workspace-templates/skills/urlscan/SKILL.md +118 -0
  97. package/workspace-templates/skills/urlscan/index.ts +94 -0
  98. package/workspace-templates/skills/urlscan/skill.json +24 -0
  99. package/workspace-templates/skills/virustotal/SKILL.md +120 -0
  100. package/workspace-templates/skills/virustotal/index.ts +124 -0
  101. package/workspace-templates/skills/virustotal/skill.json +26 -0
  102. package/workspace-templates/skills/web_research/SKILL.md +18 -0
  103. package/workspace-templates/skills/web_research/skill.json +20 -0
  104. package/workspace-templates/skills/xitter/SKILL.md +148 -0
  105. package/workspace-templates/skills/xitter/skill.json +26 -0
  106. package/workspace-templates/skills/youtube-content/SKILL.md +121 -0
  107. package/workspace-templates/skills/youtube-content/skill.json +25 -0
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: greynoise
3
+ description: Classify IP addresses as internet scanners (benign/malicious) or targeted attackers — filters noise from security alerts
4
+ category: security
5
+ version: 1.0.0
6
+ license: Apache-2.0
7
+ origin: aiden
8
+ tags: security, greynoise, scanner, threat-intel, ip, osint, soc, incident-response, noise-filtering
9
+ env_required:
10
+ - GREYNOISE_API_KEY
11
+ ---
12
+
13
+ # GreyNoise — Internet Scanner Intelligence
14
+
15
+ GreyNoise collects and analyses internet-wide scan traffic. It tells you whether an IP hitting your firewall is a known mass-scanner (benign research tool or malicious crawler) versus a targeted attacker — helping SOC teams filter out internet noise from real threats.
16
+
17
+ **Community tier:** The `/v3/community/{ip}` endpoint works with limited volume even without a key. Set `GREYNOISE_API_KEY` for higher rate limits.
18
+
19
+ ## When to Use
20
+
21
+ - An IP triggers a firewall rule and you want to know if it is just background internet noise
22
+ - SOC triage: is this alert a known scanner or a targeted attack?
23
+ - Filter false positives from SIEM before escalating an alert
24
+ - User asks "is this IP a scanner?", "is this noisy traffic?", "is IP X benign?"
25
+
26
+ ## How to Use
27
+
28
+ ### Check if an IP is a known internet scanner
29
+
30
+ ```powershell
31
+ $ip = "71.6.135.131"
32
+ $headers = @{}
33
+ if ($env:GREYNOISE_API_KEY) { $headers['key'] = $env:GREYNOISE_API_KEY }
34
+
35
+ $result = Invoke-RestMethod -Uri "https://api.greynoise.io/v3/community/$ip" -Headers $headers
36
+ Write-Host "IP: $($result.ip)"
37
+ Write-Host "Noise: $($result.noise)" # true = mass-scanner
38
+ Write-Host "RIOT: $($result.riot)" # true = trusted benign service
39
+ Write-Host "Classification: $($result.classification)" # benign | malicious | unknown
40
+ Write-Host "Name: $($result.name)"
41
+ Write-Host "Last seen: $($result.last_seen)"
42
+ Write-Host "Link: $($result.link)"
43
+ Write-Host "Message: $($result.message)"
44
+ ```
45
+
46
+ ### Triage a batch of IPs from a firewall log
47
+
48
+ ```powershell
49
+ $ips = @("1.1.1.1", "8.8.8.8", "71.6.135.131", "45.83.66.42")
50
+ $headers = @{}
51
+ if ($env:GREYNOISE_API_KEY) { $headers['key'] = $env:GREYNOISE_API_KEY }
52
+
53
+ foreach ($ip in $ips) {
54
+ try {
55
+ $r = Invoke-RestMethod -Uri "https://api.greynoise.io/v3/community/$ip" -Headers $headers
56
+ $tag = if ($r.riot) { '[RIOT-trusted]' } elseif ($r.noise) { '[SCANNER]' } else { '[TARGETED?]' }
57
+ Write-Host "$ip $tag $($r.classification) $($r.name)"
58
+ } catch {
59
+ Write-Host "$ip [ERROR] $($_.Exception.Message)"
60
+ }
61
+ Start-Sleep -Milliseconds 200
62
+ }
63
+ ```
64
+
65
+ ### Interpret the results
66
+
67
+ ```
68
+ noise = true → IP is a known mass-scanner (benign researchers, crawlers, etc.)
69
+ riot = true → IP belongs to a trusted service (Cloudflare, Google, AWS, etc.)
70
+ classification = "malicious" → Known malicious scanner — block and investigate
71
+ classification = "benign" → Probably safe background noise — may deprioritise
72
+ classification = "unknown" → No data — treat with caution
73
+ ```
74
+
75
+ ## Examples
76
+
77
+ **"Is 71.6.135.131 an attacker?"**
78
+ → Returns classification: malicious, noise: true — known malicious scanner.
79
+
80
+ **"This IP keeps hitting our web server — is it just background noise?"**
81
+ → `noise: true` means it is scanning the whole internet, not targeting you specifically.
82
+
83
+ **"Is 8.8.8.8 a threat?"**
84
+ → `riot: true` — belongs to Google DNS, trusted RIOT (Rule It Out) list.
85
+
86
+ ## Cautions
87
+
88
+ - Community endpoint returns limited data — `GREYNOISE_API_KEY` unlocks full context
89
+ - `noise: false` and `riot: false` does not mean the IP is malicious — GreyNoise may simply have no data for it
90
+ - Data reflects GreyNoise's scanner observations — gaps exist for low-volume IPs
91
+ - Free community endpoint: ~50 lookups/day per source IP without a key
92
+
93
+ ## Requirements
94
+
95
+ - No key required for low-volume community lookups
96
+ - `GREYNOISE_API_KEY` — free community key at https://viz.greynoise.io/account
@@ -0,0 +1,107 @@
1
+ // skills/greynoise/index.ts
2
+ // Programmatic handler — IP scanner intelligence via GreyNoise community API.
3
+
4
+ import { ApiSkill } from '../../core/apiSkillBase'
5
+
6
+ // Community endpoint works with or without a key.
7
+ // We create the skill instance conditionally to avoid sending an empty key header.
8
+ let _skill: ApiSkill | null = null
9
+
10
+ function getSkill(): ApiSkill {
11
+ if (_skill) return _skill
12
+
13
+ const key = process.env['GREYNOISE_API_KEY']
14
+
15
+ _skill = key
16
+ ? new ApiSkill({
17
+ name: 'greynoise',
18
+ baseUrl: 'https://api.greynoise.io/v3',
19
+ authType: 'header',
20
+ authHeader: 'key',
21
+ apiKey: key,
22
+ rateLimit: { requests: 10, windowMs: 60_000 },
23
+ timeout: 15_000,
24
+ retries: 2,
25
+ })
26
+ : new ApiSkill({
27
+ name: 'greynoise',
28
+ baseUrl: 'https://api.greynoise.io/v3',
29
+ authType: 'none',
30
+ rateLimit: { requests: 5, windowMs: 60_000 },
31
+ timeout: 15_000,
32
+ retries: 2,
33
+ })
34
+
35
+ return _skill
36
+ }
37
+
38
+ // ── Output types ──────────────────────────────────────────────
39
+
40
+ export type GreyNoiseClassification = 'benign' | 'malicious' | 'unknown'
41
+
42
+ export interface GreyNoiseReport {
43
+ ip: string
44
+ noise: boolean // true = known mass internet scanner
45
+ riot: boolean // true = trusted benign service (Google, Cloudflare, etc.)
46
+ classification: GreyNoiseClassification | string
47
+ name: string // actor/org name if known
48
+ link: string // GreyNoise visualiser URL
49
+ lastSeen: string
50
+ message: string
51
+ hasKey: boolean // whether an API key was used
52
+ }
53
+
54
+ // ── Public API ────────────────────────────────────────────────
55
+
56
+ /**
57
+ * Check whether an IP address is a known internet scanner.
58
+ *
59
+ * Uses the GreyNoise Community endpoint (/v3/community/{ip}).
60
+ * Works without an API key at low volume (~50 lookups/day).
61
+ * Set GREYNOISE_API_KEY for higher limits.
62
+ */
63
+ export async function checkIp(ip: string): Promise<GreyNoiseReport> {
64
+ const trimmed = ip.trim()
65
+
66
+ // Basic IPv4/IPv6 sanity check
67
+ if (!trimmed) throw new Error('greynoise: IP address is required')
68
+
69
+ const raw = await getSkill().get(`/community/${encodeURIComponent(trimmed)}`)
70
+
71
+ return {
72
+ ip: raw.ip ?? trimmed,
73
+ noise: raw.noise ?? false,
74
+ riot: raw.riot ?? false,
75
+ classification: raw.classification ?? 'unknown',
76
+ name: raw.name ?? '',
77
+ link: raw.link ?? `https://viz.greynoise.io/ip/${trimmed}`,
78
+ lastSeen: raw.last_seen ?? '',
79
+ message: raw.message ?? '',
80
+ hasKey: !!process.env['GREYNOISE_API_KEY'],
81
+ }
82
+ }
83
+
84
+ /** Format a GreyNoiseReport as a human-readable summary. */
85
+ export function formatReport(report: GreyNoiseReport): string {
86
+ const tag = report.riot
87
+ ? '✅ RIOT (trusted service)'
88
+ : report.noise
89
+ ? (report.classification === 'malicious' ? '🚨 MALICIOUS SCANNER' : '🔍 Known scanner')
90
+ : '⚠️ Not in GreyNoise (may be targeted)'
91
+
92
+ const lines = [
93
+ `IP: ${report.ip}`,
94
+ `Tag: ${tag}`,
95
+ `Classification: ${report.classification}`,
96
+ `Noise: ${report.noise}`,
97
+ `RIOT: ${report.riot}`,
98
+ ]
99
+
100
+ if (report.name) lines.push(`Name: ${report.name}`)
101
+ if (report.lastSeen) lines.push(`Last seen: ${report.lastSeen}`)
102
+ if (report.message) lines.push(`Message: ${report.message}`)
103
+
104
+ lines.push(`Profile: ${report.link}`)
105
+
106
+ return lines.join('\n')
107
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "greynoise",
3
+ "version": "1.0.0",
4
+ "description": "Classify IP addresses as internet scanners (benign/malicious) or targeted attackers — filters noise from security alerts",
5
+ "author": "aiden",
6
+ "license": "MIT",
7
+ "tools": [],
8
+ "trigger_phrases": [],
9
+ "compatible_agents": [
10
+ "aiden"
11
+ ],
12
+ "min_agent_version": "3.0.0",
13
+ "tags": [
14
+ "security",
15
+ "greynoise",
16
+ "scanner",
17
+ "threat-intel",
18
+ "ip",
19
+ "osint",
20
+ "soc",
21
+ "incident-response",
22
+ "noise-filtering"
23
+ ],
24
+ "created": "2026-04-27T17:11:39.765Z"
25
+ }
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: haveibeenpwned
3
+ description: Check if an email address or username appears in known data breaches using the Have I Been Pwned v3 API
4
+ category: security
5
+ version: 1.0.0
6
+ license: Apache-2.0
7
+ origin: aiden
8
+ tags: security, breach, pwned, email, password, leak, osint, hibp
9
+ env_required:
10
+ - HIBP_API_KEY
11
+ ---
12
+
13
+ # Have I Been Pwned — Breach Checker
14
+
15
+ Look up whether an email address has appeared in any publicly known data breaches. Uses the [Have I Been Pwned](https://haveibeenpwned.com) v3 API.
16
+
17
+ **Requires:** `HIBP_API_KEY` in `.env` — $3.50/month subscription at haveibeenpwned.com/API/Key
18
+
19
+ ## When to Use
20
+
21
+ - User wants to know if their email was part of a data breach
22
+ - User wants a list of breaches an email was found in
23
+ - User is auditing accounts before a security review
24
+ - User asks "was my email leaked" or "has X been pwned"
25
+
26
+ ## How to Use
27
+
28
+ ### Check a single email for breaches
29
+
30
+ ```powershell
31
+ $email = "user@example.com"
32
+ $key = $env:HIBP_API_KEY
33
+ $url = "https://haveibeenpwned.com/api/v3/breachedaccount/$([Uri]::EscapeDataString($email))?truncateResponse=false"
34
+
35
+ $result = Invoke-RestMethod -Uri $url -Headers @{ "hibp-api-key" = $key } -ErrorAction SilentlyContinue
36
+
37
+ if ($null -eq $result) {
38
+ Write-Host "✅ $email was NOT found in any known data breaches."
39
+ } else {
40
+ Write-Host "⚠️ $email found in $($result.Count) breach(es):"
41
+ $result | ForEach-Object {
42
+ Write-Host " • $($_.Name) ($($_.BreachDate)) — $($_.DataClasses -join ', ')"
43
+ }
44
+ }
45
+ ```
46
+
47
+ ### Check which passwords were exposed (pastes)
48
+
49
+ ```powershell
50
+ $email = "user@example.com"
51
+ $key = $env:HIBP_API_KEY
52
+ $url = "https://haveibeenpwned.com/api/v3/pasteaccount/$([Uri]::EscapeDataString($email))"
53
+
54
+ $result = Invoke-RestMethod -Uri $url -Headers @{ "hibp-api-key" = $key } -ErrorAction SilentlyContinue
55
+
56
+ if ($null -eq $result) {
57
+ Write-Host "✅ No paste exposures found for $email"
58
+ } else {
59
+ Write-Host "Found in $($result.Count) paste(s):"
60
+ $result | Select-Object Source, Title, Date | Format-Table
61
+ }
62
+ ```
63
+
64
+ ### Bulk check a list of emails from a file
65
+
66
+ ```powershell
67
+ $key = $env:HIBP_API_KEY
68
+ $emails = Get-Content "emails.txt"
69
+
70
+ foreach ($email in $emails) {
71
+ Start-Sleep -Milliseconds 1600 # respect 1 req/1.5s rate limit
72
+ $url = "https://haveibeenpwned.com/api/v3/breachedaccount/$([Uri]::EscapeDataString($email))"
73
+ $res = Invoke-RestMethod -Uri $url -Headers @{ "hibp-api-key" = $key } -ErrorAction SilentlyContinue
74
+ $status = if ($res) { "PWNED ($($res.Count) breaches)" } else { "Clean" }
75
+ Write-Host "$email — $status"
76
+ }
77
+ ```
78
+
79
+ ## Examples
80
+
81
+ **"Check if test@example.com has been in any breaches"**
82
+ → Run the single-email check above with that address.
83
+
84
+ **"Was my email leaked in the Adobe breach?"**
85
+ → Run the single check; then filter: `$result | Where-Object Name -eq 'Adobe'`
86
+
87
+ **"Check all emails in a file for breaches"**
88
+ → Use the bulk check snippet — it respects the 1.5s rate limit automatically.
89
+
90
+ ## Cautions
91
+
92
+ - API key is required — there is no free anonymous tier for the v3 breached-account endpoint
93
+ - Rate limit is 1 request per 1.5 seconds — always add `Start-Sleep -Milliseconds 1600` in loops
94
+ - HTTP 404 means the email was not found (not an error) — `Invoke-RestMethod -ErrorAction SilentlyContinue` handles this silently
95
+ - HIBP does not store plaintext passwords — it only records breach metadata and data class types
96
+ - For password hash checks (k-anonymity model), use the `/range/{hash5}` endpoint — no API key required
97
+
98
+ ## Requirements
99
+
100
+ - `HIBP_API_KEY` — subscribe at https://haveibeenpwned.com/API/Key ($3.50/month)
@@ -0,0 +1,72 @@
1
+ // skills/haveibeenpwned/index.ts
2
+ // Programmatic handler — uses ApiSkill for HTTP, auth, and rate limiting.
3
+
4
+ import { ApiSkill, requireApiKey } from '../../core/apiSkillBase'
5
+
6
+ const skill = new ApiSkill({
7
+ name: 'haveibeenpwned',
8
+ baseUrl: 'https://haveibeenpwned.com/api/v3',
9
+ apiKeyEnv: 'HIBP_API_KEY',
10
+ authType: 'header',
11
+ authHeader: 'hibp-api-key',
12
+ rateLimit: { requests: 1, windowMs: 1_500 }, // 1 req / 1.5 s
13
+ timeout: 15_000,
14
+ })
15
+
16
+ export interface Breach {
17
+ Name: string
18
+ BreachDate: string
19
+ DataClasses: string[]
20
+ Description: string
21
+ }
22
+
23
+ export async function checkEmail(email: string): Promise<string> {
24
+ requireApiKey('HIBP_API_KEY')
25
+
26
+ let breaches: Breach[]
27
+ try {
28
+ breaches = await skill.get(
29
+ `/breachedaccount/${encodeURIComponent(email)}`,
30
+ { truncateResponse: false },
31
+ )
32
+ } catch (e: any) {
33
+ // 404 → not found (clean)
34
+ if (e.message.includes('HTTP 404')) {
35
+ return `✅ ${email} was NOT found in any known data breaches.`
36
+ }
37
+ throw e
38
+ }
39
+
40
+ if (!Array.isArray(breaches) || breaches.length === 0) {
41
+ return `✅ ${email} was NOT found in any known data breaches.`
42
+ }
43
+
44
+ const lines = breaches.map(
45
+ b => ` • ${b.Name} (${b.BreachDate}) — ${b.DataClasses.join(', ')}`,
46
+ )
47
+ return [
48
+ `⚠️ ${email} found in ${breaches.length} breach(es):`,
49
+ ...lines,
50
+ ].join('\n')
51
+ }
52
+
53
+ export async function checkPastes(email: string): Promise<string> {
54
+ requireApiKey('HIBP_API_KEY')
55
+
56
+ let pastes: any[]
57
+ try {
58
+ pastes = await skill.get(`/pasteaccount/${encodeURIComponent(email)}`)
59
+ } catch (e: any) {
60
+ if (e.message.includes('HTTP 404')) {
61
+ return `✅ ${email} was NOT found in any known pastes.`
62
+ }
63
+ throw e
64
+ }
65
+
66
+ if (!Array.isArray(pastes) || pastes.length === 0) {
67
+ return `✅ ${email} was NOT found in any known pastes.`
68
+ }
69
+
70
+ const lines = pastes.map(p => ` • ${p.Source} — ${p.Title ?? 'untitled'} (${p.Date ?? 'unknown date'})`)
71
+ return [`⚠️ ${email} found in ${pastes.length} paste(s):`, ...lines].join('\n')
72
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "haveibeenpwned",
3
+ "version": "1.0.0",
4
+ "description": "Check if an email address or username appears in known data breaches using the Have I Been Pwned v3 API",
5
+ "author": "aiden",
6
+ "license": "MIT",
7
+ "tools": [],
8
+ "trigger_phrases": [],
9
+ "compatible_agents": [
10
+ "aiden"
11
+ ],
12
+ "min_agent_version": "3.0.0",
13
+ "tags": [
14
+ "security",
15
+ "breach",
16
+ "pwned",
17
+ "email",
18
+ "password",
19
+ "leak",
20
+ "osint",
21
+ "hibp"
22
+ ],
23
+ "created": "2026-04-27T17:11:39.790Z"
24
+ }
@@ -0,0 +1,116 @@
1
+ ---
2
+ name: jupyter-live-kernel
3
+ description: Execute code in a stateful Jupyter kernel session, maintaining variables across cells using hamelnb or jupyter CLI
4
+ category: developer
5
+ version: 1.0.0
6
+ origin: aiden
7
+ license: Apache-2.0
8
+ tags: jupyter, notebook, kernel, python, data-science, ipython, stateful, cells, pandas
9
+ ---
10
+
11
+ # Jupyter Live Kernel Execution
12
+
13
+ Run Python code in a persistent Jupyter kernel so that variables, imports, and state carry over between executions — exactly like working in a notebook, but from the CLI.
14
+
15
+ ## When to Use
16
+
17
+ - User wants to run data analysis across multiple code cells with shared state
18
+ - User wants to explore a dataset step by step
19
+ - User wants to run ML training and inspect intermediate results
20
+ - User wants to execute a `.ipynb` notebook file from the command line
21
+ - User wants to maintain a REPL-like Python session with persistent variables
22
+
23
+ ## How to Use
24
+
25
+ ### 1. Install hamelnb (stateful kernel CLI)
26
+
27
+ ```powershell
28
+ pip install hamelnb
29
+ # or use jupyter directly
30
+ pip install jupyter
31
+ ```
32
+
33
+ ### 2. Start a kernel and run cells (hamelnb)
34
+
35
+ ```powershell
36
+ # Start a persistent kernel session (keeps running between calls)
37
+ hamelnb start --name datasession
38
+
39
+ # Execute a code snippet in the named session
40
+ hamelnb run datasession "import pandas as pd; df = pd.read_csv('data.csv'); print(df.shape)"
41
+
42
+ # Execute next cell — df variable is still available
43
+ hamelnb run datasession "print(df.describe())"
44
+
45
+ # Stop session when done
46
+ hamelnb stop datasession
47
+ ```
48
+
49
+ ### 3. Execute a notebook file
50
+
51
+ ```powershell
52
+ # Run all cells in a notebook and save output
53
+ jupyter nbconvert --to notebook --execute analysis.ipynb --output analysis_out.ipynb
54
+
55
+ # Run and convert output to HTML for viewing
56
+ jupyter nbconvert --to html --execute analysis.ipynb --output report.html
57
+ ```
58
+
59
+ ### 4. Run Python code in a Jupyter kernel via Python API
60
+
61
+ ```python
62
+ import jupyter_client, queue
63
+
64
+ km = jupyter_client.KernelManager(kernel_name="python3")
65
+ km.start_kernel()
66
+ kc = km.client()
67
+ kc.start_channels()
68
+ kc.wait_for_ready(timeout=30)
69
+
70
+ def run_cell(code):
71
+ kc.execute(code)
72
+ outputs = []
73
+ while True:
74
+ try:
75
+ msg = kc.get_iopub_msg(timeout=10)
76
+ if msg["msg_type"] == "stream":
77
+ outputs.append(msg["content"]["text"])
78
+ elif msg["msg_type"] == "execute_result":
79
+ outputs.append(msg["content"]["data"].get("text/plain",""))
80
+ elif msg["msg_type"] == "status" and msg["content"]["execution_state"] == "idle":
81
+ break
82
+ except queue.Empty:
83
+ break
84
+ return "".join(outputs)
85
+
86
+ print(run_cell("import pandas as pd; df = pd.read_csv('data.csv'); df.shape"))
87
+ print(run_cell("df.describe()")) # df is still in scope!
88
+ km.shutdown_kernel()
89
+ ```
90
+
91
+ ### 5. Inject variables into a running kernel
92
+
93
+ ```python
94
+ # Use run_cell from step 4 to inject values
95
+ run_cell("x = 42; y = [1, 2, 3]")
96
+ result = run_cell("print(x * 2, sum(y))")
97
+ ```
98
+
99
+ ## Examples
100
+
101
+ **"Load sales.csv and show the top 10 rows, then plot revenue by month"**
102
+ → Use step 4: run cell 1 to load and preview the CSV, run cell 2 to group by month and show results — `df` persists between calls.
103
+
104
+ **"Execute my analysis.ipynb notebook and give me the output"**
105
+ → Use step 3 with `jupyter nbconvert --to notebook --execute`.
106
+
107
+ **"Explore the wine quality dataset — check correlations step by step"**
108
+ → Use hamelnb (step 2) to build up analysis iteratively with named session.
109
+
110
+ ## Cautions
111
+
112
+ - Kernel sessions consume memory for as long as they run — always `km.shutdown_kernel()` when done
113
+ - Long-running cells (ML training) will block until complete — set reasonable timeouts
114
+ - `nbconvert --execute` re-runs all cells from scratch — it does not resume a previous state
115
+ - hamelnb is a third-party tool — verify it is installed with `pip show hamelnb` before use
116
+ - Never pass user secrets as inline code strings — use environment variables or config files instead
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "jupyter-live-kernel",
3
+ "version": "1.0.0",
4
+ "description": "Execute code in a stateful Jupyter kernel session, maintaining variables across cells using hamelnb or jupyter CLI",
5
+ "author": "aiden",
6
+ "license": "MIT",
7
+ "tools": [],
8
+ "trigger_phrases": [],
9
+ "compatible_agents": [
10
+ "aiden"
11
+ ],
12
+ "min_agent_version": "3.0.0",
13
+ "tags": [
14
+ "jupyter",
15
+ "notebook",
16
+ "kernel",
17
+ "python",
18
+ "data-science",
19
+ "ipython",
20
+ "stateful",
21
+ "cells",
22
+ "pandas"
23
+ ],
24
+ "created": "2026-04-27T17:11:39.871Z"
25
+ }
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: linear
3
+ description: Manage Linear issues, projects, and cycles via the Linear GraphQL API
4
+ category: productivity
5
+ version: 1.0.0
6
+ origin: aiden
7
+ license: Apache-2.0
8
+ tags: linear, issues, project-management, graphql, engineering, sprint, cycle, team, tasks
9
+ ---
10
+
11
+ # Linear Issue Tracking
12
+
13
+ Query and mutate Linear data — issues, projects, cycles, and teams — using the Linear GraphQL API. Requires `LINEAR_API_KEY` set as an environment variable.
14
+
15
+ ## When to Use
16
+
17
+ - User wants to list open issues in a Linear team or project
18
+ - User wants to create a new Linear issue
19
+ - User wants to update issue status or priority
20
+ - User wants to see issues assigned to them
21
+ - User wants to look up current cycle/sprint progress
22
+
23
+ ## How to Use
24
+
25
+ ### 1. Set API key
26
+
27
+ Generate a Personal API key at https://linear.app/settings/api — select `read` and `write` scopes.
28
+
29
+ ```powershell
30
+ $env:LINEAR_API_KEY = "lin_api_..."
31
+ ```
32
+
33
+ ### 2. Run a GraphQL query helper
34
+
35
+ All Linear API calls are POST to `https://api.linear.app/graphql`.
36
+
37
+ ```powershell
38
+ function Invoke-Linear($query, $variables = @{}) {
39
+ $body = @{ query = $query; variables = $variables } | ConvertTo-Json -Depth 10
40
+ $headers = @{ "Authorization" = $env:LINEAR_API_KEY; "Content-Type" = "application/json" }
41
+ (Invoke-RestMethod -Uri "https://api.linear.app/graphql" -Method Post -Headers $headers -Body $body).data
42
+ }
43
+ ```
44
+
45
+ ### 3. List my assigned issues
46
+
47
+ ```powershell
48
+ $q = '{ viewer { assignedIssues(first: 20, filter: { state: { type: { in: ["started","unstarted"] } } }) { nodes { identifier title priority state { name } } } } }'
49
+ (Invoke-Linear $q).viewer.assignedIssues.nodes | Format-Table identifier, title, priority
50
+ ```
51
+
52
+ ### 4. List issues in a team
53
+
54
+ ```powershell
55
+ $q = 'query($key:String!) { team(key:$key) { issues(first:30, filter:{state:{type:{in:["started","unstarted"]}}}) { nodes { identifier title assignee { name } state { name } } } } }'
56
+ (Invoke-Linear $q @{ key = "ENG" }).team.issues.nodes | Format-Table identifier, title
57
+ ```
58
+
59
+ ### 5. Create a new issue
60
+
61
+ ```powershell
62
+ # First get teamId
63
+ $teamQ = '{ teams { nodes { id key name } } }'
64
+ $teams = (Invoke-Linear $teamQ).teams.nodes
65
+ $teamId = ($teams | Where-Object key -eq "ENG").id
66
+
67
+ $mutation = 'mutation($input:IssueCreateInput!) { issueCreate(input:$input) { issue { identifier title url } } }'
68
+ $vars = @{ input = @{ teamId = $teamId; title = "Fix login timeout bug"; description = "Users are being logged out after 5 min of inactivity."; priority = 2 } }
69
+ (Invoke-Linear $mutation $vars).issueCreate.issue
70
+ ```
71
+
72
+ ### 6. Update issue state
73
+
74
+ ```powershell
75
+ # Get state IDs for the team first
76
+ $stateQ = 'query($key:String!) { team(key:$key) { states { nodes { id name } } } }'
77
+ $states = (Invoke-Linear $stateQ @{ key = "ENG" }).team.states.nodes
78
+ $doneId = ($states | Where-Object name -eq "Done").id
79
+
80
+ $mutation = 'mutation($id:String! $stateId:String!) { issueUpdate(id:$id input:{stateId:$stateId}) { issue { identifier state { name } } } }'
81
+ (Invoke-Linear $mutation @{ id = "ENG-42"; stateId = $doneId }).issueUpdate.issue
82
+ ```
83
+
84
+ ### 7. List current cycle
85
+
86
+ ```powershell
87
+ $q = 'query($key:String!) { team(key:$key) { activeCycle { name startsAt endsAt progress issues(first:50) { nodes { identifier title state { name } } } } } }'
88
+ (Invoke-Linear $q @{ key = "ENG" }).team.activeCycle | Select-Object name, progress
89
+ ```
90
+
91
+ ## Examples
92
+
93
+ **"Show me all my open Linear issues"**
94
+ → Use steps 2–3 to list viewer's assigned unstarted/in-progress issues.
95
+
96
+ **"Create a Linear issue: 'Update onboarding flow' in the PRODUCT team"**
97
+ → Use step 5 — fetch team ID for PRODUCT, then create with given title.
98
+
99
+ **"What's the progress on the current sprint?"**
100
+ → Use step 7 — ask user for their team key, then show activeCycle progress.
101
+
102
+ ## Cautions
103
+
104
+ - Linear API keys are personal — they act as the user who created them
105
+ - Priority values: 0=No priority, 1=Urgent, 2=High, 3=Medium, 4=Low
106
+ - Issue IDs look like `ENG-42` but mutations need the UUID — always fetch UUID from the issues list
107
+ - GraphQL depth limit is ~6 levels — avoid deeply nested queries