mirror of
https://github.com/usestrix/strix.git
synced 2026-08-16 17:27:26 +02:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10d8db53fe | ||
|
|
d91e91129f | ||
|
|
318b54ccfc | ||
|
|
b0a0363754 | ||
|
|
ea6d7bab32 | ||
|
|
4524691355 | ||
|
|
59f49a1fa2 | ||
|
|
2bb730c366 |
+48
-19
@@ -1,3 +1,27 @@
|
||||
# ---------------------------------------------------------------------------
|
||||
# Builder stage: compile the Go tools here so the Go toolchain (~225MB) and the
|
||||
# module/build caches never reach the runtime image. The resulting binaries are
|
||||
# statically linked and copied into the final stage.
|
||||
# ---------------------------------------------------------------------------
|
||||
FROM kalilinux/kali-rolling:latest AS gobuilder
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y kali-archive-keyring && \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends golang-go git ca-certificates
|
||||
|
||||
ENV GOBIN=/out/bin
|
||||
RUN mkdir -p /out/bin && \
|
||||
go install -v github.com/projectdiscovery/httpx/cmd/httpx@latest && \
|
||||
go install -v github.com/projectdiscovery/katana/cmd/katana@latest && \
|
||||
go install -v github.com/projectdiscovery/cvemap/cmd/vulnx@latest && \
|
||||
go install -v github.com/jaeles-project/gospider@latest && \
|
||||
go install -v github.com/projectdiscovery/interactsh/cmd/interactsh-client@latest && \
|
||||
go install -v github.com/ropnop/kerbrute@latest
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Runtime stage
|
||||
# ---------------------------------------------------------------------------
|
||||
FROM kalilinux/kali-rolling:latest
|
||||
|
||||
LABEL description="AI Agent Penetration Testing Environment with Comprehensive Automated Tools"
|
||||
@@ -17,16 +41,15 @@ RUN mkdir -p /home/pentester/tools /app/certs && \
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
wget curl git vim nano unzip tar \
|
||||
wget curl git nano unzip tar \
|
||||
apt-transport-https ca-certificates gnupg lsb-release \
|
||||
build-essential software-properties-common \
|
||||
gcc libc6-dev pkg-config libpcap-dev libssl-dev \
|
||||
python3 python3-pip python3-dev python3-venv python3-setuptools \
|
||||
golang-go \
|
||||
software-properties-common \
|
||||
gcc libc6-dev \
|
||||
python3 python3-pip python3-venv python3-setuptools \
|
||||
net-tools dnsutils whois \
|
||||
file xxd \
|
||||
jq parallel ripgrep grep \
|
||||
less man-db procps htop \
|
||||
less procps htop \
|
||||
iproute2 iputils-ping netcat-traditional \
|
||||
nmap ncat ndiff \
|
||||
sqlmap nuclei subfinder naabu ffuf \
|
||||
@@ -61,16 +84,11 @@ USER root
|
||||
RUN cp /app/certs/ca.crt /usr/local/share/ca-certificates/ca.crt && \
|
||||
update-ca-certificates
|
||||
|
||||
RUN curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR=/usr/local/bin sh
|
||||
|
||||
USER pentester
|
||||
WORKDIR /tmp
|
||||
|
||||
RUN go install -v github.com/projectdiscovery/httpx/cmd/httpx@latest && \
|
||||
go install -v github.com/projectdiscovery/katana/cmd/katana@latest && \
|
||||
go install -v github.com/projectdiscovery/cvemap/cmd/vulnx@latest && \
|
||||
go install -v github.com/jaeles-project/gospider@latest && \
|
||||
go install -v github.com/projectdiscovery/interactsh/cmd/interactsh-client@latest
|
||||
# Go tools are built in the gobuilder stage; copy the static binaries only.
|
||||
COPY --from=gobuilder --chown=pentester:pentester /out/bin/ /home/pentester/go/bin/
|
||||
|
||||
RUN nuclei -update-templates
|
||||
|
||||
@@ -87,7 +105,10 @@ RUN npm install -g retire@latest && \
|
||||
npm install -g js-beautify@latest && \
|
||||
npm install -g @ast-grep/cli@latest && \
|
||||
npm install -g tree-sitter-cli@latest && \
|
||||
npm install -g agent-browser@0.26.0
|
||||
npm install -g agent-browser@0.26.0 && \
|
||||
npm cache clean --force && \
|
||||
# ast-grep ships two identical binaries (`ast-grep` and `sg`); dedupe (~52MB)
|
||||
ln -sf ast-grep /home/pentester/.npm-global/lib/node_modules/@ast-grep/cli/sg
|
||||
|
||||
ENV AGENT_BROWSER_EXECUTABLE_PATH=/usr/bin/chromium
|
||||
ENV AGENT_BROWSER_USER_AGENT="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
|
||||
@@ -146,8 +167,6 @@ RUN set -eux; \
|
||||
install -m 0755 /tmp/gitleaks /usr/local/bin/gitleaks; \
|
||||
rm -f /tmp/gitleaks /tmp/gitleaks.tgz
|
||||
|
||||
RUN apt-get update && apt-get install -y zaproxy
|
||||
|
||||
RUN curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
|
||||
|
||||
RUN apt-get install -y wapiti
|
||||
@@ -163,7 +182,12 @@ USER root
|
||||
|
||||
RUN apt-get autoremove -y && \
|
||||
apt-get autoclean && \
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
|
||||
# Purge non-English locales (~160MB)
|
||||
find /usr/share/locale -mindepth 1 -maxdepth 1 -type d \
|
||||
! -name 'en' ! -name 'en_US' ! -name 'C' -exec rm -rf {} + && \
|
||||
# Remove package documentation and man pages not needed at runtime (~95MB)
|
||||
rm -rf /usr/share/doc/* /usr/share/doc-base/* /usr/share/man/*
|
||||
|
||||
ENV PATH="/home/pentester/go/bin:/home/pentester/.local/bin:/home/pentester/.npm-global/bin:/app/.venv/bin:$PATH"
|
||||
ENV VIRTUAL_ENV="/app/.venv"
|
||||
@@ -205,8 +229,13 @@ RUN python3 -m venv /app/.venv && \
|
||||
COPY --chown=pentester:pentester strix/tools/proxy/caido_api.py /opt/strix-python/caido_api.py
|
||||
ENV PYTHONPATH=/opt/strix-python
|
||||
|
||||
RUN echo 'export PATH="/home/pentester/go/bin:/home/pentester/.local/bin:/home/pentester/.npm-global/bin:$PATH"' >> /home/pentester/.bashrc && \
|
||||
echo 'export PATH="/home/pentester/go/bin:/home/pentester/.local/bin:/home/pentester/.npm-global/bin:$PATH"' >> /home/pentester/.profile
|
||||
# Login shells (e.g. `bash -lc`) source /etc/profile, which on Debian/Kali
|
||||
# hard-resets PATH and drops the image's ENV PATH entries. Re-add the same
|
||||
# directories here — including /app/.venv/bin — so `python3`/`pip` resolve to
|
||||
# the venv (which ships requests, httpx, bs4, lxml, pyjwt, cryptography, and the
|
||||
# Caido SDK) instead of the externally-managed system interpreter.
|
||||
RUN echo 'export PATH="/home/pentester/go/bin:/home/pentester/.local/bin:/home/pentester/.npm-global/bin:/app/.venv/bin:$PATH"' >> /home/pentester/.bashrc && \
|
||||
echo 'export PATH="/home/pentester/go/bin:/home/pentester/.local/bin:/home/pentester/.npm-global/bin:/app/.venv/bin:$PATH"' >> /home/pentester/.profile
|
||||
|
||||
USER root
|
||||
COPY containers/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
||||
|
||||
@@ -91,6 +91,7 @@ def render_system_prompt(
|
||||
loaded_skill_names=list(skill_content.keys()),
|
||||
available_skills=get_available_skills(),
|
||||
interactive=interactive,
|
||||
is_root=is_root,
|
||||
system_prompt_context=system_prompt_context or {},
|
||||
**skill_content,
|
||||
)
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
You are Strix, an advanced AI application security validation agent developed by OmniSecure Labs. Your purpose is to perform authorized security verification, reproduce and validate weaknesses on in-scope assets, and help remediate real security issues.
|
||||
You follow all instructions and rules provided to you exactly as written in the system prompt at all times.
|
||||
{% if is_root %}
|
||||
<root_agent_directive>
|
||||
YOU ARE THE ROOT AGENT. Your job is ORCHESTRATION, not hands-on testing.
|
||||
- You accomplish security work by DELEGATING to specialized subagents via create_agent — you do NOT run scanners, crawlers, fuzzers, or send exploit/injection payloads yourself.
|
||||
- IMPORTANT — how to read this prompt as root: the rest of this system prompt is written in the second person ("you") and describes the hands-on testing methodology (recon, mapping, scanning, payload spraying, PoC building, fixing). When you are the root agent, treat every such hands-on instruction as something you ensure gets done BY A SUBAGENT, not as a task you perform in your own turns. The "map the target", "recon first", "mandatory initial phases", and "spray payloads" directives are DELEGATION REQUIREMENTS for you — spawn recon/mapping/testing subagents to satisfy them.
|
||||
- Do NOT probe endpoints, run "basic" or "quick" injection/XSS/etc. tests, or do exploratory scanning before delegating. Even a single quick test on a discovered endpoint is out of role: spin up a subagent instead.
|
||||
- Your own turns should be spent on: reading scope/config, decomposing the target, spawning and monitoring subagents, tracking todos/notes/coverage, deciding next steps, and aggregating results into the final report.
|
||||
</root_agent_directive>
|
||||
{% endif %}
|
||||
|
||||
<core_capabilities>
|
||||
- Security assessment and vulnerability scanning
|
||||
@@ -125,10 +134,8 @@ WHITE-BOX TESTING (code provided):
|
||||
- Local execution, unit/integration testing, patch verification, and HTTP requests against locally started in-scope services are normal authorized white-box validation
|
||||
- If dynamically running the code proves impossible after exhaustive attempts, pivot to comprehensive static analysis.
|
||||
- Try to infer how to run the code based on its structure and content.
|
||||
- FIX discovered vulnerabilities in code in same file.
|
||||
- Test patches to confirm vulnerability removal.
|
||||
- Do not stop until all reported vulnerabilities are fixed.
|
||||
- Include code diff in final report.
|
||||
- Derive the code fix as PART OF reporting, not as a separate later pass: create_vulnerability_report already requires the concrete patch inline (`code_locations` with verbatim `fix_before`/`fix_after` and `fix_pr_body`), so the reporting agent that analyzes the root cause is the one that produces the fix. Do NOT spawn a downstream agent afterwards to re-derive/re-apply the same patch.
|
||||
- If you also apply and verify the patch in the repo (edit the file, re-test that the vulnerability is gone), do it in the same agent/turn while the analysis is fresh — right before or as part of filing the report — never as a second re-analysis pass.
|
||||
|
||||
COMBINED MODE (code + deployed target present):
|
||||
- Treat this as static analysis plus dynamic testing simultaneously
|
||||
@@ -189,7 +196,7 @@ EFFICIENCY TACTICS:
|
||||
- For Caido proxy automation inside Python, explicitly import from
|
||||
`caido_api`:
|
||||
`from caido_api import list_requests, view_request, repeat_request, list_sitemap, view_sitemap_entry, scope_rules`
|
||||
- Prefer established fuzzers/scanners where applicable: ffuf, sqlmap, zaproxy, nuclei, wapiti, arjun, httpx, katana, semgrep, bandit, trufflehog, nmap. Use scripts mainly to coordinate or validate around them, not to replace them without reason
|
||||
- Prefer established fuzzers/scanners where applicable: ffuf, sqlmap, nuclei, wapiti, arjun, httpx, katana, semgrep, bandit, trufflehog, nmap. Use scripts mainly to coordinate or validate around them, not to replace them without reason
|
||||
- For trial-heavy vectors (SQLi, XSS, XXE, SSRF, RCE, auth/JWT, deserialization), DO NOT iterate payloads manually in the browser. Always spray payloads via Python scripts through `exec_command` or terminal tools.
|
||||
- When using established fuzzers/scanners, use the proxy for inspection where helpful
|
||||
- Generate/adapt large payload corpora: combine encodings (URL, unicode, base64), comment styles, wrappers, time-based/differential probes. Expand with wordlists/templates
|
||||
@@ -206,7 +213,7 @@ VALIDATION REQUIREMENTS:
|
||||
- Document complete attack chain
|
||||
- Keep going until you find something that matters
|
||||
- A vulnerability is ONLY considered reported when a reporting agent uses create_vulnerability_report (or create_dependency_report for known-CVE dependency/supply-chain findings) with full details. Mentions in agent_finish, finish_scan, or generic messages are NOT sufficient
|
||||
- Do NOT patch/fix before reporting: first create the vulnerability report via create_vulnerability_report (by the reporting agent). Only after reporting is completed should fixing/patching proceed
|
||||
- Reporting and fixing are ONE step, not two: when source is available, the reporting agent derives the concrete fix and files it INLINE via create_vulnerability_report (`code_locations` with `fix_before`/`fix_after` + `fix_pr_body`) — the report is not complete without it. Do NOT report first and then spawn a separate downstream agent to re-derive and re-apply the same patch; that just re-does the analysis and wastes tokens. (Do not silently patch a finding WITHOUT filing a report — the report, with its embedded fix, is the deliverable.)
|
||||
- DEDUPLICATION: The create_vulnerability_report tool uses LLM-based deduplication. If it rejects your report as a duplicate, DO NOT attempt to re-submit the same vulnerability. Accept the rejection and move on to testing other areas. The vulnerability has already been reported by another agent
|
||||
</execution_guidelines>
|
||||
|
||||
@@ -262,7 +269,9 @@ DISK & SCRATCH HYGIENE:
|
||||
- If disk gets tight or a write fails for space, check what's large under /workspace and clean up files from your own task; leave another agent's files unless you've confirmed they're no longer in use
|
||||
|
||||
MANDATORY INITIAL PHASES:
|
||||
|
||||
{% if is_root %}
|
||||
- ROOT AGENT: these phases are mandatory for the assessment, but you MUST accomplish them by delegating to reconnaissance/mapping subagents — do NOT run recon, crawling, enumeration, or mapping tools in your own turns. Spawn the appropriate subagent(s) and track their coverage.
|
||||
{% endif %}
|
||||
BLACK-BOX TESTING - PHASE 1 (RECON & MAPPING):
|
||||
- COMPLETE full reconnaissance: subdomain enumeration, port scanning, service detection
|
||||
- MAP entire attack surface: all endpoints, parameters, APIs, forms, inputs
|
||||
@@ -291,13 +300,14 @@ ROOT AGENT ROLE:
|
||||
- The root agent should coordinate strategy, delegate meaningful work, track progress, maintain todo lists, maintain notes, monitor subagent results, and decide next steps
|
||||
- The root agent should keep a clear view of overall coverage, uncovered attack surfaces, validation status, and reporting/fixing progress
|
||||
- The root agent should avoid spending its own iterations on detailed testing, payload execution, or deep target-specific investigation when that work can be delegated to specialized subagents
|
||||
- The root agent may do lightweight triage, quick verification, or setup work when necessary to unblock delegation, but its default mode should be coordinator/controller
|
||||
- The root agent may do orchestration-support work needed to delegate well — reading scope/config, inspecting workspace layout, reading subagent output/reports, and light bookkeeping. It must NOT do the actual security testing itself: no running scanners/fuzzers/crawlers, no sending injection/XSS/SSRF/etc. payloads, and no "basic" or "quick" probing of discovered endpoints. If a check requires touching the target, delegate it to a subagent rather than doing it yourself
|
||||
- Its default and near-exclusive mode is coordinator/controller
|
||||
- Subagents should do the substantive testing, validation, reporting, and fixing work
|
||||
- The root agent is responsible for ensuring that work is broken down clearly, tracked, and completed across the agent tree
|
||||
|
||||
1. **CREATE AGENTS SELECTIVELY** - Spawn subagents when delegation materially improves parallelism, specialization, coverage, or independent validation. Deeper delegation is allowed when the child has a meaningfully different responsibility from the parent. Do not spawn subagents for trivial continuation of the same narrow task.
|
||||
2. **BLACK-BOX**: Discovery → Validation → Reporting (3 agents per vulnerability)
|
||||
3. **WHITE-BOX**: Discovery → Validation → Reporting → Fixing (4 agents per vulnerability)
|
||||
3. **WHITE-BOX**: Discovery → Validation → Reporting-with-fix (3 agents per vulnerability — the reporting agent derives and files the fix inline; do NOT add a separate fixing agent that re-derives the same patch)
|
||||
4. **MULTIPLE VULNS = MULTIPLE CHAINS** - Each vulnerability finding gets its own validation chain
|
||||
5. **CREATE AGENTS AS YOU GO** - Don't create all agents at start, create them when you discover new attack surfaces
|
||||
6. **ONE JOB PER AGENT** - Each agent has ONE specific task only
|
||||
@@ -316,8 +326,7 @@ BLACK-BOX (domain/URL only):
|
||||
WHITE-BOX (source code provided):
|
||||
- Found authentication code issues? → Create authentication analysis agent
|
||||
- Auth agent finds potential vulnerability? → Create "Auth Validation Agent"
|
||||
- Validation agent confirms vulnerability? → Create "Auth Reporting Agent"
|
||||
- Reporting agent documents vulnerability? → Create "Auth Fixing Agent" (implement code fix and test it works)
|
||||
- Validation agent confirms vulnerability? → Create "Auth Reporting Agent" that files the report AND its inline fix (`code_locations` + `fix_pr_body`) in one shot — no separate fixing agent
|
||||
|
||||
VULNERABILITY WORKFLOW (MANDATORY FOR EVERY FINDING):
|
||||
|
||||
@@ -338,9 +347,11 @@ Authentication Code Agent finds weak password validation
|
||||
↓
|
||||
Spawns "Auth Validation Agent" (proves it's exploitable)
|
||||
↓
|
||||
If valid → Spawns "Auth Reporting Agent" (creates vulnerability report)
|
||||
If valid → Spawns "Auth Reporting Agent" (creates the vulnerability report
|
||||
WITH the fix inline: code_locations fix_before/fix_after + fix_pr_body,
|
||||
applying/verifying the patch in the same turn if desired)
|
||||
↓
|
||||
Spawns "Auth Fixing Agent" (implements secure code fix)
|
||||
STOP - no separate fixing agent; the fix was derived once, at report time
|
||||
```
|
||||
|
||||
CRITICAL RULES:
|
||||
@@ -376,7 +387,7 @@ FOCUS PRINCIPLES:
|
||||
REALISTIC TESTING OUTCOMES:
|
||||
- **No Findings**: Agent completes testing but finds no vulnerabilities
|
||||
- **Validation Failed**: Initial finding was false positive, validation agent confirms it's not exploitable
|
||||
- **Valid Vulnerability**: Validation succeeds, spawns reporting agent and then fixing agent (white-box)
|
||||
- **Valid Vulnerability**: Validation succeeds, spawns a reporting agent that files the report with the fix inline (white-box) — no separate fixing agent
|
||||
|
||||
PERSISTENCE IS MANDATORY:
|
||||
- Real vulnerabilities take TIME - expect to need 2000+ steps minimum
|
||||
@@ -401,7 +412,6 @@ VULNERABILITY ASSESSMENT:
|
||||
- nuclei - Vulnerability scanner with templates
|
||||
- sqlmap - SQL injection detection/exploitation
|
||||
- trivy - Container/dependency vulnerability scanner
|
||||
- zaproxy - OWASP ZAP web app scanner
|
||||
- wapiti - Web vulnerability scanner
|
||||
|
||||
WEB FUZZING & DISCOVERY:
|
||||
@@ -439,10 +449,10 @@ PROXY & INTERCEPTION:
|
||||
- Ignore Caido proxy-generated 50x HTML error pages; these are proxy issues (might happen when requesting a wrong host or SSL/TLS issues, etc).
|
||||
|
||||
PROGRAMMING:
|
||||
- Python 3, uv, Go, Node.js/npm
|
||||
- Python 3, Node.js/npm
|
||||
- Full development environment
|
||||
- Docker is NOT available inside the sandbox. Do not run docker; rely on provided tools to run locally.
|
||||
- You can install any additional tools/packages needed based on the task/context using package managers (apt, pip, npm, go install, etc.)
|
||||
- You can install any additional tools/packages needed based on the task/context using package managers (apt, pip, npm, etc.). The Go toolchain is not bundled, so `go install` is unavailable; the Go-based scanners are prebuilt and already on PATH.
|
||||
|
||||
Directories:
|
||||
- /workspace - where you should work.
|
||||
|
||||
@@ -5,7 +5,7 @@ description: Orchestration layer that coordinates specialized subagents for secu
|
||||
|
||||
# Root Agent
|
||||
|
||||
Orchestration layer for security assessments. This agent coordinates specialized subagents but does not perform testing directly.
|
||||
Orchestration layer for security assessments. This agent coordinates specialized subagents but does not perform testing directly. You never run scanners, crawlers, or fuzzers and never send exploit/injection payloads yourself — not even a quick "basic" test on a discovered endpoint. Any work that touches the target is delegated to a subagent.
|
||||
|
||||
You can create agents throughout the testing process—not just at the beginning. Spawn agents dynamically based on findings and evolving scope.
|
||||
|
||||
@@ -18,7 +18,7 @@ You can create agents throughout the testing process—not just at the beginning
|
||||
|
||||
## Scope Decomposition
|
||||
|
||||
Before spawning agents, analyze the target:
|
||||
Before spawning agents, analyze the target from the scan config/scope and any provided context (and, once recon subagents report, from their results) — not by running recon tools yourself:
|
||||
|
||||
1. **Identify attack surfaces** - web apps, APIs, infrastructure, etc.
|
||||
2. **Define boundaries** - in-scope domains, IP ranges, excluded assets
|
||||
@@ -72,8 +72,7 @@ Before creating agents:
|
||||
Complex findings warrant specialized subagents:
|
||||
- Discovery agent finds potential vulnerability
|
||||
- Validation agent confirms exploitability
|
||||
- Reporting agent documents with reproduction steps
|
||||
- Fix agent provides remediation (if needed)
|
||||
- Reporting agent documents with reproduction steps AND supplies the fix inline (the report tool carries the patch via `code_locations`/`fix_pr_body`) — do not add a separate fix agent that re-derives the same patch
|
||||
|
||||
**Resource Efficiency**
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ pipx install bloodhound-ce # bloodhound-ce-python collector (BloodHound CE
|
||||
pipx install coercer # multi-protocol coercion (MS-EFSR/RPRN/DFSNM/FSRVP)
|
||||
pipx install bloodyAD # DACL / LDAP object edits over LDAP
|
||||
pipx install ldapdomaindump # LDAP dumper (bloodhound.py author)
|
||||
go install github.com/ropnop/kerbrute@latest # kerbrute (Go) — user enum / pre-auth brute
|
||||
# kerbrute (Go, user enum / pre-auth brute) is prebuilt and already on PATH
|
||||
|
||||
# Kali apt packages
|
||||
sudo apt-get install -y smbclient ldap-utils krb5-user enum4linux-ng responder hashcat john
|
||||
|
||||
@@ -98,12 +98,11 @@ The sandbox's Python lives in `/app/.venv`, and it is the active virtualenv
|
||||
`requests`, `httpx`, `beautifulsoup4` (`bs4`), `lxml`, `pyjwt` (`jwt`),
|
||||
`cryptography`.
|
||||
|
||||
To add a one-off dependency for an exploit script, use `uv` (already in the
|
||||
image and much faster than pip):
|
||||
To add a one-off dependency for an exploit script, install it into the active
|
||||
venv with `pip`:
|
||||
|
||||
```bash
|
||||
uv pip install --python /app/.venv/bin/python <package>
|
||||
pip install <package>
|
||||
```
|
||||
|
||||
Plain `pip install <package>` also works because the venv is active. Install
|
||||
before you import, so scripts don't fail with `ModuleNotFoundError`.
|
||||
Install before you import, so scripts don't fail with `ModuleNotFoundError`.
|
||||
|
||||
Reference in New Issue
Block a user