ctf-agent 1.2.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.
- package/AGENTS.md +131 -0
- package/Dockerfile +192 -0
- package/README.md +522 -0
- package/agents/ctf-analyzer.md +58 -0
- package/agents/ctf-controller.md +151 -0
- package/agents/ctf-speedrun.md +74 -0
- package/bin/ctf-agent.js +119 -0
- package/docker-compose.yml +13 -0
- package/mcp_config.json +19 -0
- package/package.json +44 -0
- package/references/ctf-triage-ladder.md +68 -0
- package/references/exploit-databases.md +575 -0
- package/references/llm-safety-and-policy-compliance.md +173 -0
- package/references/multi-agent-orchestration-and-policy-routing.md +278 -0
- package/references/security-events-and-intelligence.md +566 -0
- package/references/version-matrix.md +59 -0
- package/rules/ctf-execution-rules.md +44 -0
- package/rules/ctf-safety-framing-rules.md +140 -0
- package/rules/flag-validation-rules.md +25 -0
- package/scripts/__init__.py +1 -0
- package/scripts/ctf-tools.lock +205 -0
- package/scripts/ctf_init.py +1026 -0
- package/scripts/ctf_update.py +583 -0
- package/scripts/ctfd_client.py +81 -0
- package/scripts/cve_lookup.py +453 -0
- package/scripts/extract_flags.py +155 -0
- package/scripts/install_as_agent.py +278 -0
- package/scripts/install_ctf_tools.sh +603 -0
- package/scripts/parallel_triage.py +395 -0
- package/scripts/prompt_policy_sanitizer.py +283 -0
- package/scripts/scope_guard.py +444 -0
- package/scripts/skill_validator.py +504 -0
- package/scripts/workspace_cleaner.py +141 -0
- package/skills/ctf-ai-ml/SKILL.md +120 -0
- package/skills/ctf-ai-ml/adversarial-ml.md +623 -0
- package/skills/ctf-ai-ml/llm-attacks.md +487 -0
- package/skills/ctf-ai-ml/model-attacks.md +422 -0
- package/skills/ctf-crypto/SKILL.md +320 -0
- package/skills/ctf-crypto/advanced-math.md +798 -0
- package/skills/ctf-crypto/classic-ciphers.md +651 -0
- package/skills/ctf-crypto/ecc-attacks.md +347 -0
- package/skills/ctf-crypto/exotic-crypto-2.md +380 -0
- package/skills/ctf-crypto/exotic-crypto.md +528 -0
- package/skills/ctf-crypto/historical.md +113 -0
- package/skills/ctf-crypto/lattice-and-lwe.md +524 -0
- package/skills/ctf-crypto/modern-ciphers-2.md +563 -0
- package/skills/ctf-crypto/modern-ciphers-3.md +453 -0
- package/skills/ctf-crypto/modern-ciphers.md +649 -0
- package/skills/ctf-crypto/prng-attacks.md +257 -0
- package/skills/ctf-crypto/prng.md +664 -0
- package/skills/ctf-crypto/rsa-attacks-2.md +792 -0
- package/skills/ctf-crypto/rsa-attacks.md +487 -0
- package/skills/ctf-crypto/stream-ciphers.md +390 -0
- package/skills/ctf-crypto/zkp-and-advanced.md +456 -0
- package/skills/ctf-forensics/3d-printing.md +121 -0
- package/skills/ctf-forensics/SKILL.md +379 -0
- package/skills/ctf-forensics/disk-advanced.md +497 -0
- package/skills/ctf-forensics/disk-and-memory.md +491 -0
- package/skills/ctf-forensics/disk-recovery.md +699 -0
- package/skills/ctf-forensics/linux-forensics.md +511 -0
- package/skills/ctf-forensics/network-advanced.md +583 -0
- package/skills/ctf-forensics/network.md +645 -0
- package/skills/ctf-forensics/peripheral-capture.md +287 -0
- package/skills/ctf-forensics/signals-and-hardware.md +713 -0
- package/skills/ctf-forensics/steganography.md +694 -0
- package/skills/ctf-forensics/stego-advanced-2.md +475 -0
- package/skills/ctf-forensics/stego-advanced.md +481 -0
- package/skills/ctf-forensics/stego-image.md +691 -0
- package/skills/ctf-forensics/windows.md +625 -0
- package/skills/ctf-malware/SKILL.md +181 -0
- package/skills/ctf-malware/c2-and-protocols.md +274 -0
- package/skills/ctf-malware/pe-and-dotnet.md +108 -0
- package/skills/ctf-malware/scripts-and-obfuscation.md +449 -0
- package/skills/ctf-misc/SKILL.md +498 -0
- package/skills/ctf-misc/bashjails.md +323 -0
- package/skills/ctf-misc/ctfd-navigation.md +465 -0
- package/skills/ctf-misc/dns.md +255 -0
- package/skills/ctf-misc/encodings-advanced.md +504 -0
- package/skills/ctf-misc/encodings.md +431 -0
- package/skills/ctf-misc/games-and-vms-2.md +254 -0
- package/skills/ctf-misc/games-and-vms-3.md +690 -0
- package/skills/ctf-misc/games-and-vms-4.md +229 -0
- package/skills/ctf-misc/games-and-vms.md +529 -0
- package/skills/ctf-misc/linux-privesc.md +333 -0
- package/skills/ctf-misc/pyjails.md +671 -0
- package/skills/ctf-misc/rf-sdr.md +91 -0
- package/skills/ctf-osint/SKILL.md +198 -0
- package/skills/ctf-osint/geolocation-and-media.md +464 -0
- package/skills/ctf-osint/social-media.md +312 -0
- package/skills/ctf-osint/web-and-dns.md +341 -0
- package/skills/ctf-pwn/SKILL.md +214 -0
- package/skills/ctf-pwn/advanced-exploits-2.md +579 -0
- package/skills/ctf-pwn/advanced-exploits-3.md +598 -0
- package/skills/ctf-pwn/advanced-exploits-4.md +590 -0
- package/skills/ctf-pwn/advanced-exploits-5.md +119 -0
- package/skills/ctf-pwn/advanced-exploits.md +773 -0
- package/skills/ctf-pwn/advanced.md +326 -0
- package/skills/ctf-pwn/field-notes.md +245 -0
- package/skills/ctf-pwn/format-string.md +694 -0
- package/skills/ctf-pwn/heap-fsop.md +285 -0
- package/skills/ctf-pwn/heap-techniques-2.md +333 -0
- package/skills/ctf-pwn/heap-techniques.md +513 -0
- package/skills/ctf-pwn/kernel-bypass.md +421 -0
- package/skills/ctf-pwn/kernel-techniques.md +366 -0
- package/skills/ctf-pwn/kernel.md +636 -0
- package/skills/ctf-pwn/overflow-basics.md +611 -0
- package/skills/ctf-pwn/rop-advanced.md +725 -0
- package/skills/ctf-pwn/rop-and-shellcode.md +659 -0
- package/skills/ctf-pwn/sandbox-escape.md +313 -0
- package/skills/ctf-reverse/SKILL.md +163 -0
- package/skills/ctf-reverse/anti-analysis-ctf.md +204 -0
- package/skills/ctf-reverse/anti-analysis.md +693 -0
- package/skills/ctf-reverse/field-notes.md +376 -0
- package/skills/ctf-reverse/languages-compiled.md +666 -0
- package/skills/ctf-reverse/languages-platforms.md +592 -0
- package/skills/ctf-reverse/languages.md +553 -0
- package/skills/ctf-reverse/patterns-ctf-2.md +397 -0
- package/skills/ctf-reverse/patterns-ctf-3.md +797 -0
- package/skills/ctf-reverse/patterns-ctf.md +670 -0
- package/skills/ctf-reverse/patterns-runtime.md +274 -0
- package/skills/ctf-reverse/patterns.md +572 -0
- package/skills/ctf-reverse/platforms-hardware.md +387 -0
- package/skills/ctf-reverse/platforms.md +664 -0
- package/skills/ctf-reverse/tools-advanced-2.md +421 -0
- package/skills/ctf-reverse/tools-advanced.md +407 -0
- package/skills/ctf-reverse/tools-dynamic.md +679 -0
- package/skills/ctf-reverse/tools-emulation.md +319 -0
- package/skills/ctf-reverse/tools.md +573 -0
- package/skills/ctf-web/SKILL.md +153 -0
- package/skills/ctf-web/auth-and-access-2.md +82 -0
- package/skills/ctf-web/auth-and-access.md +783 -0
- package/skills/ctf-web/auth-infra.md +321 -0
- package/skills/ctf-web/auth-jwt.md +186 -0
- package/skills/ctf-web/client-side-advanced.md +739 -0
- package/skills/ctf-web/client-side.md +529 -0
- package/skills/ctf-web/cves.md +373 -0
- package/skills/ctf-web/field-notes.md +482 -0
- package/skills/ctf-web/node-and-prototype.md +200 -0
- package/skills/ctf-web/server-side-2.md +337 -0
- package/skills/ctf-web/server-side-advanced-2.md +559 -0
- package/skills/ctf-web/server-side-advanced-3.md +125 -0
- package/skills/ctf-web/server-side-advanced-4.md +480 -0
- package/skills/ctf-web/server-side-advanced.md +378 -0
- package/skills/ctf-web/server-side-deser.md +443 -0
- package/skills/ctf-web/server-side-exec-2.md +799 -0
- package/skills/ctf-web/server-side-exec.md +457 -0
- package/skills/ctf-web/server-side.md +629 -0
- package/skills/ctf-web/sql-injection.md +790 -0
- package/skills/ctf-web/web3.md +374 -0
- package/skills/ctf-writeup/SKILL.md +90 -0
- package/skills/solve-challenge/SKILL.md +269 -0
- package/skills.json +16 -0
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
CTF-Agent Distribution & Deployment Manager (v1.0)
|
|
4
|
+
Deploys CTF-Agent skills, rules, subagents, and scripts into any CTF competition workspace (.agents/)
|
|
5
|
+
or globally into Antigravity user configuration (~/.gemini/config/).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
import shutil
|
|
11
|
+
import argparse
|
|
12
|
+
import json
|
|
13
|
+
import hashlib
|
|
14
|
+
import subprocess
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Optional
|
|
17
|
+
|
|
18
|
+
# Ensure safe UTF-8 output on Windows consoles
|
|
19
|
+
if hasattr(sys.stdout, "reconfigure"):
|
|
20
|
+
try:
|
|
21
|
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
22
|
+
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
|
|
23
|
+
except Exception:
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
REPO_ROOT = Path(__file__).resolve().parent.parent
|
|
27
|
+
|
|
28
|
+
ESSENTIAL_DIRS = ["skills", "rules", "agents", "scripts", "references"]
|
|
29
|
+
ESSENTIAL_FILES = ["AGENTS.md", "mcp_config.json", "skills.json", "README.md"]
|
|
30
|
+
WORKSPACE_ROOT_FILES = ["AGENTS.md", "mcp_config.json", "skills.json"]
|
|
31
|
+
|
|
32
|
+
def win_to_wsl_path(p: Path) -> str:
|
|
33
|
+
"""Converts a Windows Path (e.g. C:\\path\\to\\dir) to a WSL path (/mnt/c/path/to/dir)."""
|
|
34
|
+
resolved = p.resolve()
|
|
35
|
+
drive = resolved.drive.rstrip(':').lower()
|
|
36
|
+
parts = list(resolved.parts[1:])
|
|
37
|
+
return f"/mnt/{drive}/" + "/".join(parts)
|
|
38
|
+
|
|
39
|
+
def install_wsl_toolchain(target_path: Path, profile: str = "core", distro: str = "kali-linux"):
|
|
40
|
+
"""Installs CTF tools into WSL for the target workspace."""
|
|
41
|
+
if shutil.which("wsl") is None:
|
|
42
|
+
print(" [!] WSL command not available on this system. Skipping WSL toolchain installation.")
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
wsl_target = win_to_wsl_path(target_path)
|
|
46
|
+
script_wsl = f"{wsl_target}/.agents/scripts/install_ctf_tools.sh"
|
|
47
|
+
|
|
48
|
+
profiles = [p.strip() for p in profile.split(",") if p.strip()]
|
|
49
|
+
|
|
50
|
+
print(f"\n[*] Provisioning WSL ({distro}) CTF toolchain for workspace...")
|
|
51
|
+
print(f" Target Workspace : {wsl_target}")
|
|
52
|
+
print(f" Profiles Selected: {', '.join(profiles)}")
|
|
53
|
+
print(f" Installer Script : {script_wsl}")
|
|
54
|
+
|
|
55
|
+
for prof in profiles:
|
|
56
|
+
cmd = ["wsl", "-d", distro, "bash", "-c", f"bash '{script_wsl}' {prof}"]
|
|
57
|
+
try:
|
|
58
|
+
print(f"\n[*] Executing install_ctf_tools.sh {prof} in WSL ({distro})...")
|
|
59
|
+
res = subprocess.run(cmd, check=False)
|
|
60
|
+
if res.returncode == 0:
|
|
61
|
+
print(f"[OK] WSL CTF toolchain [{prof}] installed successfully!")
|
|
62
|
+
else:
|
|
63
|
+
print(f"[!] WSL CTF toolchain installer exited with code {res.returncode}")
|
|
64
|
+
except Exception as e:
|
|
65
|
+
print(f"[!] Error running WSL installer: {e}")
|
|
66
|
+
|
|
67
|
+
# Run verification
|
|
68
|
+
verify_cmd = ["wsl", "-d", distro, "bash", "-c", f"bash '{script_wsl}' --verify {prof}"]
|
|
69
|
+
try:
|
|
70
|
+
print(f"[*] Running toolchain verification check for [{prof}] in WSL...")
|
|
71
|
+
subprocess.run(verify_cmd, check=False)
|
|
72
|
+
except Exception as e:
|
|
73
|
+
print(f"[!] Error running WSL verification: {e}")
|
|
74
|
+
|
|
75
|
+
def deploy_to_workspace(
|
|
76
|
+
target_path: Path,
|
|
77
|
+
use_symlink: bool = False,
|
|
78
|
+
force: bool = False,
|
|
79
|
+
setup_workspace: bool = True,
|
|
80
|
+
install_wsl: bool = True,
|
|
81
|
+
wsl_profile: str = "core",
|
|
82
|
+
wsl_distro: str = "kali-linux"
|
|
83
|
+
):
|
|
84
|
+
"""Deploy CTF-Agent into target directory under .agents/, configure workspace files, and provision WSL toolchain."""
|
|
85
|
+
dot_agents = target_path / ".agents"
|
|
86
|
+
print(f"[*] Deploying CTF-Agent to workspace: {dot_agents}")
|
|
87
|
+
|
|
88
|
+
if dot_agents.exists() and not force:
|
|
89
|
+
print(f"[!] Warning: {dot_agents} already exists. Use --force to overwrite.")
|
|
90
|
+
sys.exit(1)
|
|
91
|
+
|
|
92
|
+
dot_agents.mkdir(parents=True, exist_ok=True)
|
|
93
|
+
|
|
94
|
+
for dir_name in ESSENTIAL_DIRS:
|
|
95
|
+
src_dir = REPO_ROOT / dir_name
|
|
96
|
+
dest_dir = dot_agents / dir_name
|
|
97
|
+
|
|
98
|
+
if not src_dir.exists():
|
|
99
|
+
continue
|
|
100
|
+
|
|
101
|
+
if dest_dir.exists():
|
|
102
|
+
if dest_dir.is_symlink() or (os.name == 'nt' and dest_dir.is_junction()):
|
|
103
|
+
dest_dir.unlink()
|
|
104
|
+
else:
|
|
105
|
+
shutil.rmtree(dest_dir)
|
|
106
|
+
|
|
107
|
+
if use_symlink:
|
|
108
|
+
try:
|
|
109
|
+
if os.name == 'nt':
|
|
110
|
+
import _winapi
|
|
111
|
+
_winapi.CreateJunction(str(src_dir), str(dest_dir))
|
|
112
|
+
else:
|
|
113
|
+
dest_dir.symlink_to(src_dir, target_is_directory=True)
|
|
114
|
+
print(f" [+] Linked {dir_name}/ -> {dest_dir}")
|
|
115
|
+
except Exception as e:
|
|
116
|
+
print(f" [!] Symlink/Junction failed ({e}), falling back to copy...")
|
|
117
|
+
shutil.copytree(src_dir, dest_dir)
|
|
118
|
+
print(f" [+] Copied {dir_name}/ -> {dest_dir}")
|
|
119
|
+
else:
|
|
120
|
+
shutil.copytree(src_dir, dest_dir)
|
|
121
|
+
print(f" [+] Copied {dir_name}/ -> {dest_dir}")
|
|
122
|
+
|
|
123
|
+
for file_name in ESSENTIAL_FILES:
|
|
124
|
+
src_file = REPO_ROOT / file_name
|
|
125
|
+
dest_file = dot_agents / file_name
|
|
126
|
+
if src_file.exists():
|
|
127
|
+
shutil.copy2(src_file, dest_file)
|
|
128
|
+
print(f" [+] Copied {file_name} -> {dest_file}")
|
|
129
|
+
|
|
130
|
+
if setup_workspace:
|
|
131
|
+
print(f"\n[*] Configuring workspace root settings at {target_path}...")
|
|
132
|
+
for file_name in WORKSPACE_ROOT_FILES:
|
|
133
|
+
src_file = REPO_ROOT / file_name
|
|
134
|
+
dest_file = target_path / file_name
|
|
135
|
+
if src_file.exists():
|
|
136
|
+
if file_name == "AGENTS.md" and target_path != REPO_ROOT:
|
|
137
|
+
content = src_file.read_text(encoding="utf-8")
|
|
138
|
+
content = content.replace("](references/", "](.agents/references/")
|
|
139
|
+
content = content.replace("](rules/", "](.agents/rules/")
|
|
140
|
+
dest_file.write_text(content, encoding="utf-8")
|
|
141
|
+
else:
|
|
142
|
+
shutil.copy2(src_file, dest_file)
|
|
143
|
+
print(f" [+] Configured workspace root: {dest_file}")
|
|
144
|
+
|
|
145
|
+
# Synchronize scripts into workspace scripts/ if directory exists
|
|
146
|
+
ws_scripts = target_path / "scripts"
|
|
147
|
+
if ws_scripts.is_dir():
|
|
148
|
+
src_scripts = REPO_ROOT / "scripts"
|
|
149
|
+
for s_file in src_scripts.iterdir():
|
|
150
|
+
if s_file.is_file():
|
|
151
|
+
shutil.copy2(s_file, ws_scripts / s_file.name)
|
|
152
|
+
print(f" [+] Synchronized all scripts -> {ws_scripts}")
|
|
153
|
+
|
|
154
|
+
# Generate skills-lock.json with computed hashes of local skills
|
|
155
|
+
skills_lock = {"version": 1, "skills": {}}
|
|
156
|
+
skills_dir = dot_agents / "skills"
|
|
157
|
+
if skills_dir.exists():
|
|
158
|
+
for skill_path in sorted(skills_dir.iterdir()):
|
|
159
|
+
if skill_path.is_dir():
|
|
160
|
+
skill_md = skill_path / "SKILL.md"
|
|
161
|
+
if skill_md.exists():
|
|
162
|
+
h = hashlib.sha256(skill_md.read_bytes()).hexdigest()
|
|
163
|
+
skills_lock["skills"][skill_path.name] = {
|
|
164
|
+
"source": "CTF-Agent (local)",
|
|
165
|
+
"sourceType": "local",
|
|
166
|
+
"skillPath": f".agents/skills/{skill_path.name}/SKILL.md",
|
|
167
|
+
"computedHash": h
|
|
168
|
+
}
|
|
169
|
+
skills_lock_file = target_path / "skills-lock.json"
|
|
170
|
+
skills_lock_file.write_text(json.dumps(skills_lock, indent=2), encoding="utf-8")
|
|
171
|
+
print(f" [+] Generated {skills_lock_file}")
|
|
172
|
+
|
|
173
|
+
# Provision CTF toolchain into WSL
|
|
174
|
+
if install_wsl and os.name == 'nt':
|
|
175
|
+
install_wsl_toolchain(target_path, profile=wsl_profile, distro=wsl_distro)
|
|
176
|
+
|
|
177
|
+
print(f"\n[OK] Successfully deployed CTF-Agent into {dot_agents}!")
|
|
178
|
+
print(f" Available Subagents:")
|
|
179
|
+
print(f" - @ctf-controller : Master Orchestrator (SCO/TE context, refusal routing, deterministic fallback)")
|
|
180
|
+
print(f" - @ctf-speedrun : Ultra-fast Blitz mode (Stop-on-Flag, zero doc overhead, auto-clean)")
|
|
181
|
+
print(f" - @ctf-analyzer : In-depth Lab/Audit mode (Full RCA, resources/ preservation, writeup.md)")
|
|
182
|
+
|
|
183
|
+
def deploy_globally(force: bool = False):
|
|
184
|
+
"""Deploy skills, rules, and subagents into ~/.gemini/config/ for global availability."""
|
|
185
|
+
home = Path.home()
|
|
186
|
+
global_config = home / ".gemini" / "config"
|
|
187
|
+
print(f"[*] Deploying CTF-Agent globally to: {global_config}")
|
|
188
|
+
|
|
189
|
+
if not global_config.exists():
|
|
190
|
+
global_config.mkdir(parents=True, exist_ok=True)
|
|
191
|
+
|
|
192
|
+
# 1. Deploy Skills
|
|
193
|
+
global_skills = global_config / "skills"
|
|
194
|
+
global_skills.mkdir(exist_ok=True)
|
|
195
|
+
for skill_path in (REPO_ROOT / "skills").iterdir():
|
|
196
|
+
if skill_path.is_dir():
|
|
197
|
+
dest = global_skills / skill_path.name
|
|
198
|
+
if dest.exists() and force:
|
|
199
|
+
shutil.rmtree(dest)
|
|
200
|
+
if not dest.exists():
|
|
201
|
+
shutil.copytree(skill_path, dest)
|
|
202
|
+
print(f" [+] Deployed skill: {skill_path.name}")
|
|
203
|
+
|
|
204
|
+
# 2. Deploy Agents
|
|
205
|
+
global_agents = global_config / "agents"
|
|
206
|
+
global_agents.mkdir(exist_ok=True)
|
|
207
|
+
for agent_path in (REPO_ROOT / "agents").iterdir():
|
|
208
|
+
if agent_path.is_file() and agent_path.suffix == ".md":
|
|
209
|
+
dest = global_agents / agent_path.name
|
|
210
|
+
shutil.copy2(agent_path, dest)
|
|
211
|
+
print(f" [+] Deployed agent: {agent_path.name}")
|
|
212
|
+
|
|
213
|
+
# 3. Deploy Rules
|
|
214
|
+
global_rules = global_config / "rules"
|
|
215
|
+
global_rules.mkdir(exist_ok=True)
|
|
216
|
+
for rule_path in (REPO_ROOT / "rules").iterdir():
|
|
217
|
+
if rule_path.is_file() and rule_path.suffix == ".md":
|
|
218
|
+
dest = global_rules / rule_path.name
|
|
219
|
+
shutil.copy2(rule_path, dest)
|
|
220
|
+
print(f" [+] Deployed rule: {rule_path.name}")
|
|
221
|
+
|
|
222
|
+
print(f"\n[OK] Successfully installed CTF-Agent globally across all Antigravity workspaces!")
|
|
223
|
+
|
|
224
|
+
def main():
|
|
225
|
+
if len(sys.argv) > 1 and sys.argv[1] in ("init", "--init"):
|
|
226
|
+
import ctf_init
|
|
227
|
+
sys.argv = [sys.argv[0]] + sys.argv[2:]
|
|
228
|
+
ctf_init.main()
|
|
229
|
+
return
|
|
230
|
+
|
|
231
|
+
if len(sys.argv) > 1 and sys.argv[1] in ("update", "--update"):
|
|
232
|
+
import ctf_update
|
|
233
|
+
sys.argv = [sys.argv[0]] + sys.argv[2:]
|
|
234
|
+
ctf_update.main()
|
|
235
|
+
return
|
|
236
|
+
|
|
237
|
+
parser = argparse.ArgumentParser(description="CTF-Agent Workspace & Global Deployment Manager")
|
|
238
|
+
parser.add_argument("target", nargs="?", help="Target CTF workspace directory (deploys as .agents/)")
|
|
239
|
+
parser.add_argument("--global", dest="is_global", action="store_true", help="Install CTF skills, rules, and subagents globally into ~/.gemini/config/")
|
|
240
|
+
parser.add_argument("--symlink", "--link", action="store_true", help="Use symlinks/junctions for workspace deployment to keep live sync")
|
|
241
|
+
parser.add_argument("--setup-workspace", dest="setup_workspace", action="store_true", default=True, help="Configure workspace root AGENTS.md, mcp_config.json, skills.json (default: True)")
|
|
242
|
+
parser.add_argument("--no-setup-workspace", dest="setup_workspace", action="store_false", help="Only deploy .agents/ without modifying workspace root files")
|
|
243
|
+
parser.add_argument("--wsl", dest="install_wsl", action="store_true", default=True, help="Automatically install CTF toolchain into WSL during setup (default: True)")
|
|
244
|
+
parser.add_argument("--no-wsl", "--skip-toolchain", dest="install_wsl", action="store_false", help="Skip toolchain installation into backend")
|
|
245
|
+
parser.add_argument("--wsl-profile", default="core", help="WSL toolchain profile to install: core, pwn, rev, crypto, forensics, web, all (default: core)")
|
|
246
|
+
parser.add_argument("--wsl-distro", default="kali-linux", help="WSL distribution target (default: kali-linux)")
|
|
247
|
+
parser.add_argument("--init", dest="is_init", action="store_true", help="Run intelligent preflight detector & workspace initializer")
|
|
248
|
+
parser.add_argument("--update", dest="is_update", action="store_true", help="Run workspace & skill update engine")
|
|
249
|
+
parser.add_argument("--force", "-f", action="store_true", help="Overwrite existing files or directories")
|
|
250
|
+
|
|
251
|
+
args = parser.parse_args()
|
|
252
|
+
|
|
253
|
+
if args.is_update:
|
|
254
|
+
import ctf_update
|
|
255
|
+
workspace = ctf_update.WorkspaceUpdater.resolve_workspace(args.target)
|
|
256
|
+
res = ctf_update.WorkspaceUpdater.update_workspace(workspace, force=args.force)
|
|
257
|
+
ctf_update.print_update_report(res)
|
|
258
|
+
return
|
|
259
|
+
|
|
260
|
+
if args.is_global:
|
|
261
|
+
deploy_globally(force=args.force)
|
|
262
|
+
elif args.target:
|
|
263
|
+
target_dir = Path(args.target).resolve()
|
|
264
|
+
deploy_to_workspace(
|
|
265
|
+
target_dir,
|
|
266
|
+
use_symlink=args.symlink,
|
|
267
|
+
force=args.force,
|
|
268
|
+
setup_workspace=args.setup_workspace,
|
|
269
|
+
install_wsl=args.install_wsl,
|
|
270
|
+
wsl_profile=args.wsl_profile,
|
|
271
|
+
wsl_distro=args.wsl_distro
|
|
272
|
+
)
|
|
273
|
+
else:
|
|
274
|
+
parser.print_help()
|
|
275
|
+
sys.exit(1)
|
|
276
|
+
|
|
277
|
+
if __name__ == "__main__":
|
|
278
|
+
main()
|