@shieldly/cli 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 (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +81 -0
  3. package/dist/cli.cjs +249 -0
  4. package/package.json +44 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shieldly
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # @shieldly/cli
2
+
3
+ **AI-Powered Security Analysis for AWS — official CLI.**
4
+
5
+ Analyze AWS IAM policies and CloudFormation templates for security risks from
6
+ any terminal, shell script, or CI/CD pipeline. Powered by
7
+ [Shieldly](https://www.shieldly.io).
8
+
9
+ ```bash
10
+ npm install -g @shieldly/cli
11
+ ```
12
+
13
+ ## Quick start
14
+
15
+ ```bash
16
+ # Authenticate (get a key at https://www.shieldly.io/app/api)
17
+ export SHIELDLY_API_KEY=sk_live_...
18
+
19
+ # Analyze an IAM policy
20
+ shieldly analyze-iam policy.json
21
+
22
+ # Analyze a CloudFormation template
23
+ shieldly analyze-cf template.yaml
24
+
25
+ # Manage API keys
26
+ shieldly api-keys list
27
+ ```
28
+
29
+ Without an API key, `analyze-iam` runs in demo mode (5 lifetime analyses, IAM only).
30
+ `analyze-cf` and `api-keys` require a key.
31
+
32
+ ## Commands
33
+
34
+ | Command | Description |
35
+ | --- | --- |
36
+ | `shieldly analyze-iam <policy-file>` | Analyze an IAM policy for security issues |
37
+ | `shieldly analyze-cf <template-file>` | Analyze a CloudFormation template |
38
+ | `shieldly api-keys list\|create\|revoke` | Manage API keys |
39
+ | `shieldly completion bash\|zsh\|install` | Shell completion |
40
+
41
+ ## Global options
42
+
43
+ | Option | Description |
44
+ | --- | --- |
45
+ | `--api-key <key>` | API key (or set `SHIELDLY_API_KEY`) |
46
+ | `--version` | Show version |
47
+ | `-h`, `--help` | Show help |
48
+
49
+ ## Use in CI
50
+
51
+ ```yaml
52
+ - name: AI-Powered IAM Analysis
53
+ run: |
54
+ npm install -g @shieldly/cli
55
+ shieldly analyze-iam ./iam-policy.json
56
+ env:
57
+ SHIELDLY_API_KEY: ${{ secrets.SHIELDLY_API_KEY }}
58
+ ```
59
+
60
+ For pull-request gating with PR comments, use the
61
+ [Shieldly GitHub Action](https://github.com/shieldly-io/action) instead.
62
+
63
+ ## Privacy
64
+
65
+ Shieldly does **not** log your policy input. Cache keys are one-way SHA-256
66
+ hashes of the input.
67
+
68
+ ## Links
69
+
70
+ - Web app & demo: https://www.shieldly.io
71
+ - API reference: https://www.shieldly.io/docs/api
72
+ - Issues: https://github.com/shieldly-io/cli/issues
73
+
74
+ ## License
75
+
76
+ MIT © Shieldly
77
+
78
+ ---
79
+
80
+ *Amazon Web Services (AWS) is a trademark of Amazon.com, Inc. Shieldly is not
81
+ affiliated with, endorsed by, or sponsored by Amazon Web Services.*
package/dist/cli.cjs ADDED
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/env node
2
+ var J=Object.create;var O=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var V=Object.getPrototypeOf,Z=Object.prototype.hasOwnProperty;var Q=(e,o,t,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let s of q(o))!Z.call(e,s)&&s!==t&&O(e,s,{get:()=>o[s],enumerable:!(n=B(o,s))||n.enumerable});return e};var C=(e,o,t)=>(t=e!=null?J(V(e)):{},Q(o||!e||!e.__esModule?O(t,"default",{value:e,enumerable:!0}):t,e));var $=require("node:fs"),j=require("node:os"),D=require("node:path"),b="Shieldly-CLI/1.0.0",z=(0,D.join)((0,j.homedir)(),".shieldly","config.json"),X="https://api.shieldly.io",ee="https://www.shieldly.io";function g(e){if(e)return e;if(process.env.SHIELDLY_API_KEY)return process.env.SHIELDLY_API_KEY;if((0,$.existsSync)(z))try{let o=JSON.parse((0,$.readFileSync)(z,"utf8"));if(o.apiKey)return o.apiKey}catch{}return null}function _(){return(process.env.SHIELDLY_API_URL||X).replace(/\/$/,"")}function oe(){return(process.env.SHIELDLY_WEB_URL||ee).replace(/\/$/,"")}async function R(e,o){let t=oe(),n=await fetch(`${t}${e}`,{method:"POST",headers:{"Content-Type":"application/json","User-Agent":b},body:JSON.stringify(o)});if(!n.ok){let s=await n.json().catch(()=>({}));throw new Error(s.error||`API error ${n.status}`)}return n.json()}async function I(e,o,t){let n=_(),s=await fetch(`${n}${e}`,{method:"POST",headers:{"Content-Type":"application/json","User-Agent":b,Authorization:`Bearer ${t}`},body:JSON.stringify(o)});if(s.status===202){let r=await s.json().catch(()=>({}));if(r.jobId)return se(r.jobId,t)}if(!s.ok){let r=await s.json().catch(()=>({}));throw new Error(r.error||`API error ${s.status}`)}return s.json()}async function se(e,o){let t=[2e3,3e3,5e3],n=Date.now(),s=0;for(let r=0;r<180;r++){let i=t[Math.min(r,t.length-1)];await new Promise(c=>setTimeout(c,i));let l=Math.round((Date.now()-n)/1e3);process.stderr.write(`\rAI-Powered analysis in progress\u2026 (${l}s)`);let a;try{a=await v(`/v1/jobs/${encodeURIComponent(e)}`,o),s=0}catch(c){if(++s>=3)throw process.stderr.write(`
3
+ `),c;continue}if(a.status==="complete")return process.stderr.write(`
4
+ `),{...a.result,unitInfo:a.unitInfo};if(a.status==="failed")throw process.stderr.write(`
5
+ `),new Error(a.error||"Analysis failed")}throw process.stderr.write(`
6
+ `),new Error("Analysis timed out after polling")}async function v(e,o){let t=_(),n=await fetch(`${t}${e}`,{headers:{Authorization:`Bearer ${o}`,"User-Agent":b}});if(!n.ok){let s=await n.json().catch(()=>({}));throw new Error(s.error||`API error ${n.status}`)}return n.json()}async function M(e,o,t){let n=_(),s=await fetch(`${n}${e}`,{method:"DELETE",headers:{"Content-Type":"application/json","User-Agent":b,Authorization:`Bearer ${t}`},body:JSON.stringify(o)});if(!s.ok){let r=await s.json().catch(()=>({}));throw new Error(r.error||`API error ${s.status}`)}return s.json()}function w(e){return(0,$.existsSync)(e)||(console.error(`Error: File not found: ${e}`),process.exit(1)),(0,$.readFileSync)(e,"utf8")}var K={CRITICAL:"\x1B[31m",HIGH:"\x1B[33m",MEDIUM:"\x1B[36m",LOW:"\x1B[32m",INFO:"\x1B[90m"},m="\x1B[0m",k="\x1B[1m",L="\x1B[2m",Y="\x1B[36m";function x(e,o){if(o==="json"){console.log(JSON.stringify(e,null,2));return}let{score:t,riskLevel:n,findings:s=[],cached:r}=e;if(console.log(""),console.log(`${k}AI-Powered Security Analysis \u2014 Shieldly${m}`),console.log(`${L}${"\u2500".repeat(50)}${m}`),console.log(` ${k}Security Score:${m} ${te(t)}${t}/100${m}`),console.log(` ${k}Risk Level:${m} ${ne(n)}${n}${m}`),r&&console.log(` ${L}(cached result)${m}`),console.log(""),s.length===0)console.log(` ${Y}[PASS] No findings${m}`);else{console.log(`${k}Findings (${s.length}):${m}`);for(let i of s){let l=K[(i.severity||"").toUpperCase()]||"";console.log(`
7
+ ${l}[${i.severity}]${m} ${k}${i.title}${m}`),i.description&&console.log(` ${L}${i.description}${m}`),i.remediation&&console.log(` ${Y}Fix:${m} ${i.remediation}`)}}console.log("")}function te(e){return e>=80?"\x1B[32m":e>=50?"\x1B[33m":"\x1B[31m"}function ne(e){let o=(e||"").toUpperCase();return K[o]||""}var le=`
8
+ Usage: shieldly analyze-cf <template-file> [options]
9
+
10
+ Analyze a CloudFormation template for security issues using AI.
11
+
12
+ Arguments:
13
+ template-file Path to a JSON or YAML CloudFormation template
14
+
15
+ Options:
16
+ --format <fmt> Output format: table | json (default: table)
17
+ --api-key <key> API key (or set SHIELDLY_API_KEY env var)
18
+ -h, --help Show this help
19
+
20
+ Examples:
21
+ shieldly analyze-cf template.json
22
+ shieldly analyze-cf template.yaml --format json
23
+ `;async function H(e){if(e.includes("-h")||e.includes("--help")||e.length===0){console.log(le);return}let o=e.find(l=>!l.startsWith("--"));o||(console.error("Error: template-file argument is required"),process.exit(1));let t=e.indexOf("--format"),n=t!==-1?e[t+1]:"table",s=e.indexOf("--api-key"),r=g(s!==-1?e[s+1]:null);r||(console.error(`Error: API key required. Set SHIELDLY_API_KEY env var or use --api-key.
24
+ Get your free key at https://www.shieldly.io/app/api`),process.exit(1));let i=w(o);n!=="json"&&console.log(`Analyzing ${o}\u2026`);try{let l=await I("/v1/analyze/cf",{template:i},r);x(l,n);let a=(l.findings||[]).filter(y=>y.severity==="CRITICAL").length,c=(l.findings||[]).filter(y=>y.severity==="HIGH").length;(a>0||c>0)&&process.exit(1)}catch(l){console.error(`Error: ${l.message}`),process.exit(1)}}var re=`
25
+ Usage: shieldly analyze-iam <policy-file> [options]
26
+
27
+ Analyze an AWS IAM policy for security issues using AI.
28
+
29
+ Arguments:
30
+ policy-file Path to a JSON file containing the IAM policy
31
+
32
+ Options:
33
+ --type <type> identity (default) | cross_account
34
+ Any IAM or resource policy JSON works as 'identity'.
35
+ 'cross_account' expects {"identityPolicy":\u2026,"trustPolicy":\u2026}.
36
+ --format <fmt> Output format: table | json (default: table)
37
+ --api-key <key> API key (or set SHIELDLY_API_KEY env var)
38
+ -h, --help Show this help
39
+
40
+ Examples:
41
+ shieldly analyze-iam policy.json
42
+ shieldly analyze-iam policy.json --type resource --format json
43
+ SHIELDLY_API_KEY=sk_... shieldly analyze-iam policy.json
44
+ `;async function F(e){if(e.includes("-h")||e.includes("--help")||e.length===0){console.log(re);return}let o=e.find(y=>!y.startsWith("--"));o||(console.error("Error: policy-file argument is required"),process.exit(1));let t=e.indexOf("--type"),n=t!==-1?e[t+1]:"identity",s=e.indexOf("--format"),r=s!==-1?e[s+1]:"table",i=e.indexOf("--api-key"),l=g(i!==-1?e[i+1]:null),a=w(o),c;try{c=JSON.parse(a)}catch{console.error("Error: policy-file must be valid JSON"),process.exit(1)}r!=="json"&&(console.log(`Analyzing ${o} (type: ${n})\u2026`),l||console.log("Demo mode (5 lifetime analyses). Get a free key at https://www.shieldly.io/app/api"));try{let y=l?await I("/v1/analyze/iam",{policy:c,policyType:n},l):await R("/api/demo/analyze-iam",{policy:c,policyType:n});x(y,r);let E=(y.findings||[]).filter(S=>S.severity==="CRITICAL").length,d=(y.findings||[]).filter(S=>S.severity==="HIGH").length;(E>0||d>0)&&process.exit(1)}catch(y){console.error(`Error: ${y.message}`),process.exit(1)}}var U=`
45
+ Usage: shieldly api-keys <subcommand> [options]
46
+
47
+ Manage Shieldly API keys.
48
+
49
+ Subcommands:
50
+ list List all your API keys
51
+ create --label <label> Create a new API key
52
+ --scopes <scopes> Comma-separated scopes: iam,cf,cost (default: iam,cf)
53
+ revoke <key-id> Revoke an API key by ID
54
+
55
+ Options:
56
+ --api-key <key> API key (or set SHIELDLY_API_KEY env var)
57
+ --format json Output as JSON
58
+ -h, --help Show this help
59
+
60
+ Examples:
61
+ shieldly api-keys list
62
+ shieldly api-keys create --label "CI/CD Key" --scopes iam,cf
63
+ shieldly api-keys revoke key_abc123
64
+ `,u="\x1B[1m",N="\x1B[2m",T="\x1B[36m",h="\x1B[0m";function ie(e){return e?new Date(e).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"}):"\u2014"}async function G(e){if(e.includes("-h")||e.includes("--help")||e.length===0){console.log(U);return}let o=e[0],t=e.slice(1),n=t.indexOf("--api-key"),s=g(n!==-1?t[n+1]:null),r=t.indexOf("--format"),i=r!==-1?t[r+1]:"table";if(s||(console.error(`Error: API key required. Set SHIELDLY_API_KEY env var or use --api-key.
65
+ Get your free key at https://www.shieldly.io/app/api`),process.exit(1)),o==="list"){try{let a=(await v("/v1/api-keys",s)).keys||[];if(i==="json"){console.log(JSON.stringify(a,null,2));return}if(a.length===0){console.log("No API keys found. Create one at https://www.shieldly.io/app/api");return}console.log(""),console.log(`${u}API Keys (${a.length}):${h}`),console.log(`${N}${"\u2500".repeat(60)}${h}`);for(let c of a){let y=(c.scopes||[]).join(", ")||"all";console.log(` ${T}${c.keyId}${h}`),console.log(` ${u}Label:${h} ${c.label||"(unlabeled)"}`),console.log(` ${u}Scopes:${h} ${y}`),console.log(` ${u}Uses:${h} ${c.usageCount||0}`),console.log(` ${u}Created:${h} ${ie(c.createdAt)}`),console.log("")}}catch(l){console.error(`Error: ${l.message}`),process.exit(1)}return}if(o==="create"){let l=t.indexOf("--label"),a=l!==-1?t[l+1]:"CLI Key",c=t.indexOf("--scopes"),E=(c!==-1?t[c+1]:"iam,cf").split(",").map(d=>d.trim()).filter(Boolean);try{let d=await I("/v1/api-keys",{label:a,scopes:E},s);if(i==="json"){console.log(JSON.stringify(d,null,2));return}console.log(""),console.log(`${u}[OK] API key created${h}`),console.log(` ${u}Key ID:${h} ${d.keyId}`),console.log(` ${u}API Key:${h} ${T}${d.apiKey}${h}`),console.log(` ${N}Store this key securely \u2014 it won't be shown again.${h}`),console.log("")}catch(d){console.error(`Error: ${d.message}`),process.exit(1)}return}if(o==="revoke"){let l=t.find(a=>!a.startsWith("--")&&a!=="revoke");l||(console.error(`Error: key-id argument is required
66
+ Usage: shieldly api-keys revoke <key-id>`),process.exit(1));try{if(await M("/v1/api-keys",{keyId:l},s),i==="json"){console.log(JSON.stringify({success:!0,keyId:l}));return}console.log(`[OK] API key ${l} revoked`)}catch(a){console.error(`Error: ${a.message}`),process.exit(1)}return}console.error(`Unknown subcommand: ${o}`),console.log(U),process.exit(1)}var ae=`
67
+ _shieldly() {
68
+ local cur prev words cword
69
+ _init_completion || return
70
+
71
+ local commands="analyze-iam analyze-cf api-keys completion"
72
+ local global_opts="--api-key --help -h --version -v"
73
+
74
+ case $prev in
75
+ analyze-iam)
76
+ if [[ $cur == -* ]]; then
77
+ COMPREPLY=($(compgen -W "--type --format --api-key --help -h" -- "$cur"))
78
+ else
79
+ COMPREPLY=($(compgen -f -- "$cur"))
80
+ fi
81
+ return
82
+ ;;
83
+ analyze-cf)
84
+ if [[ $cur == -* ]]; then
85
+ COMPREPLY=($(compgen -W "--format --api-key --help -h" -- "$cur"))
86
+ else
87
+ COMPREPLY=($(compgen -f -- "$cur"))
88
+ fi
89
+ return
90
+ ;;
91
+ api-keys)
92
+ COMPREPLY=($(compgen -W "list create revoke" -- "$cur"))
93
+ return
94
+ ;;
95
+ completion)
96
+ COMPREPLY=($(compgen -W "bash zsh install" -- "$cur"))
97
+ return
98
+ ;;
99
+ --type)
100
+ COMPREPLY=($(compgen -W "identity resource trust s3 sqs kms sns cross_account" -- "$cur"))
101
+ return
102
+ ;;
103
+ --format)
104
+ COMPREPLY=($(compgen -W "table json" -- "$cur"))
105
+ return
106
+ ;;
107
+ --label)
108
+ return
109
+ ;;
110
+ --scopes)
111
+ COMPREPLY=($(compgen -W "iam cf cost" -- "$cur"))
112
+ return
113
+ ;;
114
+ --api-key)
115
+ return
116
+ ;;
117
+ esac
118
+
119
+ if [[ $cur == -* ]]; then
120
+ COMPREPLY=($(compgen -W "$global_opts" -- "$cur"))
121
+ elif [[ $cword -eq 1 ]]; then
122
+ COMPREPLY=($(compgen -W "$commands" -- "$cur"))
123
+ fi
124
+ } &&
125
+ complete -F _shieldly shieldly
126
+ `,ce=`
127
+ #compdef shieldly
128
+
129
+ _shieldly() {
130
+ local -a opts
131
+ local curcontext="$curcontext" state line ret=1
132
+
133
+ _arguments -C '(-h --help)'{-h,--help}'[Show help]' '(-v --version)'{-v,--version}'[Show version]' '--api-key[API key]:api key' '1: :->command' '*: :->args' && ret=0
134
+
135
+ case $state in
136
+ command)
137
+ local commands; commands=(
138
+ 'analyze-iam:Analyze an IAM policy for security issues'
139
+ 'analyze-cf:Analyze a CloudFormation template'
140
+ 'api-keys:Manage API keys'
141
+ 'completion:Generate shell completion script'
142
+ )
143
+ _describe 'command' commands && ret=0
144
+ ;;
145
+ args)
146
+ case $words[1] in
147
+ analyze-iam)
148
+ _arguments '--type[Policy type]:type:(identity resource trust s3 sqs kms sns cross_account)' '--format[Output format]:format:(table json)' '--api-key[API key]:api key' '(-h --help)'{-h,--help}'[Show help]' '*:policy file:_files' && ret=0
149
+ ;;
150
+ analyze-cf)
151
+ _arguments '--format[Output format]:format:(table json)' '--api-key[API key]:api key' '(-h --help)'{-h,--help}'[Show help]' '*:template file:_files' && ret=0
152
+ ;;
153
+ api-keys)
154
+ _arguments '--format[Output format]:format:(table json)' '--api-key[API key]:api key' '1: :->subcommand' '*: :->args' && ret=0
155
+ case $state in
156
+ subcommand)
157
+ local subcommands; subcommands=(
158
+ 'list:List all API keys'
159
+ 'create:Create a new API key'
160
+ 'revoke:Revoke an API key'
161
+ )
162
+ _describe 'subcommand' subcommands && ret=0
163
+ ;;
164
+ args)
165
+ case $words[2] in
166
+ create)
167
+ _arguments '--label[Key label]' '--scopes[Comma-separated scopes]:scopes:(iam cf cost)' && ret=0
168
+ ;;
169
+ revoke)
170
+ _arguments '*:key id' && ret=0
171
+ ;;
172
+ esac
173
+ ;;
174
+ esac
175
+ ;;
176
+ completion)
177
+ _arguments '1: :->shell' && ret=0
178
+ case $state in
179
+ shell)
180
+ local shells; shells=(
181
+ 'bash:Generate bash completion'
182
+ 'zsh:Generate zsh completion'
183
+ 'install:Install completion for current shell'
184
+ )
185
+ _describe 'shell' shells && ret=0
186
+ ;;
187
+ esac
188
+ ;;
189
+ esac
190
+ ;;
191
+ esac
192
+
193
+ return ret
194
+ }
195
+
196
+ _shieldly
197
+ `,pe=`
198
+ Usage: shieldly completion <shell>
199
+
200
+ Generate shell completion scripts for the shieldly CLI.
201
+
202
+ Shells:
203
+ bash Generate bash completion
204
+ zsh Generate zsh completion
205
+ install Auto-detect shell and install completion
206
+
207
+ Examples:
208
+ eval "$(shieldly completion bash)" # Source bash completion
209
+ shieldly completion zsh > /usr/local/share/zsh/site-functions/_shieldly # Install zsh completion
210
+ shieldly completion install # Auto-detect and install
211
+ `;async function W(e){if(!e.length||e.includes("-h")||e.includes("--help")){console.log(pe);return}let o=e[0];switch(o){case"bash":console.log(ae.trimStart());break;case"zsh":console.log(ce.trimStart());break;case"install":await ye();break;default:console.error(`Unsupported shell: ${o}`),console.log("Supported shells: bash, zsh"),process.exit(1)}}async function ye(){let e=process.env.SHELL||"",o=process.env.HOME||"";if(e.includes("zsh")){let t=`${o}/.zshrc`,n=`
212
+ # shieldly CLI completion
213
+ autoload -Uz compinit && compinit -C 2>/dev/null
214
+ eval "$(shieldly completion zsh)" 2>/dev/null`;try{let{readFileSync:s,appendFileSync:r,existsSync:i}=await import("node:fs");if(i(t)&&s(t,"utf8").includes("shieldly completion")){console.log("shieldly completion already installed in ~/.zshrc");return}r(t,n),console.log("Installed shieldly completion in ~/.zshrc"),console.log("Run: source ~/.zshrc")}catch(s){console.error(`Failed to install: ${s.message}`),process.exit(1)}}else if(e.includes("bash")){let t=`${o}/.bashrc`,n=`
215
+ # shieldly CLI completion
216
+ source /dev/stdin <<< "$(shieldly completion bash)" 2>/dev/null`;try{let{readFileSync:s,appendFileSync:r,existsSync:i}=await import("node:fs");if(i(t)&&s(t,"utf8").includes("shieldly completion")){console.log("shieldly completion already installed in ~/.bashrc");return}r(t,n),console.log("Installed shieldly completion in ~/.bashrc"),console.log("Run: source ~/.bashrc")}catch(s){console.error(`Failed to install: ${s.message}`),process.exit(1)}}else console.error(`Unsupported shell: ${e}. Install manually:`),console.log(' eval "$(shieldly completion bash)" # For bash'),console.log(' eval "$(shieldly completion zsh)" # For zsh'),process.exit(1)}var f="\x1B[1m",A="\x1B[36m",P="\x1B[2m",p="\x1B[0m",me="1.0.0",he=`
217
+ ${f}shieldly${p} \u2014 AI-Powered Security Analysis for AWS
218
+
219
+ ${f}Usage:${p}
220
+ shieldly <command> [args] [options]
221
+
222
+ ${f}Commands:${p}
223
+ ${A}analyze-iam${p} <policy-file> Analyze an IAM policy for security issues
224
+ ${A}analyze-cf${p} <template-file> Analyze a CloudFormation template
225
+ ${A}api-keys${p} list|create|revoke Manage API keys
226
+ ${A}completion${p} bash|zsh|install Generate shell completion
227
+
228
+ ${f}Global Options:${p}
229
+ --api-key <key> API key (or set SHIELDLY_API_KEY env var)
230
+ --version Show version
231
+ -h, --help Show this help
232
+
233
+ ${f}Authentication:${p}
234
+ Set your API key via env var: export SHIELDLY_API_KEY=sk_...
235
+ Get a free API key at: ${A}https://www.shieldly.io/app/api${p}
236
+
237
+ ${f}Examples:${p}
238
+ ${P}# Analyze an IAM policy${p}
239
+ shieldly analyze-iam policy.json
240
+
241
+ ${P}# Analyze a CloudFormation template${p}
242
+ shieldly analyze-cf template.yaml
243
+
244
+ ${P}# List API keys${p}
245
+ shieldly api-keys list
246
+
247
+ ${P}# Use in CI${p}
248
+ SHIELDLY_API_KEY=\${{ secrets.SHIELDLY_API_KEY }} shieldly analyze-iam policy.json
249
+ `;async function de(){let[,,e,...o]=process.argv;switch((!e||e==="-h"||e==="--help")&&(console.log(he),process.exit(0)),(e==="--version"||e==="-v")&&(console.log(me),process.exit(0)),e){case"analyze-iam":await F(o);break;case"analyze-cf":await H(o);break;case"api-keys":await G(o);break;case"completion":await W(o);break;default:console.error(`Unknown command: ${e}`),console.log(`Run ${f}shieldly --help${p} for usage`),process.exit(1)}}de().catch(e=>{console.error("Fatal error:",e.message),process.exit(1)});
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@shieldly/cli",
3
+ "version": "1.0.0",
4
+ "description": "AI-Powered Security Analysis for AWS — official CLI",
5
+ "license": "MIT",
6
+ "homepage": "https://www.shieldly.io",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/shieldly-io/cli.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/shieldly-io/cli/issues"
13
+ },
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "type": "module",
18
+ "bin": {
19
+ "shieldly": "dist/cli.cjs"
20
+ },
21
+ "files": [
22
+ "dist/cli.cjs"
23
+ ],
24
+ "keywords": [
25
+ "aws",
26
+ "iam",
27
+ "security",
28
+ "cloudformation",
29
+ "ai",
30
+ "shieldly",
31
+ "cli"
32
+ ],
33
+ "engines": {
34
+ "node": ">=22.0.0"
35
+ },
36
+ "scripts": {
37
+ "build": "node build.js",
38
+ "build:dev": "node build.js --dev",
39
+ "prepublishOnly": "npm run build"
40
+ },
41
+ "devDependencies": {
42
+ "esbuild": "^0.25.0"
43
+ }
44
+ }