Best for
- Use when you need to query an OpenCTI instance — is this IOC already known, what entities/reports/campaigns exist for an actor — or push new intel into it — creating indicators/observables, labelling, TLP markings, rela…
Liberty91LTD/cti-skills/skills/lookup-opencti/SKILL.md
Use when you need to query an OpenCTI instance — is this IOC already known, what entities/reports/campaigns exist for an actor — or push new intel into it — creating indicators/observables, labelling, TLP markings, relationships, or importing a STIX 2.1 bundle. Two-way integration. Commonly invoked by /ip-investigation and friends to check whether an indicator is already in your knowledge base, and by analytical skills that want to publish their findings back to OpenCTI. Reads $OPENCTI_URL and $
Decision brief
Two-way bridge to an OpenCTI threat-intelligence platform. OpenCTI is a STIX 2.1-native knowledge base: everything in it — indicators, observables, intrusion sets, malware, reports, campaigns — is a STIX entity connected by relationships. Like /lookup-misp, this skill also write…
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/Liberty91LTD/cti-skills --skill "skills/lookup-opencti"Inspect the Agent Skill "lookup-opencti" from https://github.com/Liberty91LTD/cti-skills/blob/97d66b3687ba6d32b316a7df3391beb3e2de88de/skills/lookup-opencti/SKILL.md at commit 97d66b3687ba6d32b316a7df3391beb3e2de88de. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Single Python CLI (stdlib only — no install). Single endpoint: everything is GraphQL against $OPENCTIURL/graphql with Authorization: Bearer $OPENCTITOKEN.
Read: - An indicator was found by another lookup (VT, OTX, …) — check whether your OpenCTI instance already knows it (lookup) - An analyst wants the entities, reports, or campaigns your platform holds on an actor, malware family, or CVE (search, list, get) - You need recent high…
Review the “Read operations” section in the pinned source before continuing.
python3 tools/clis/opencti.py version
python3 tools/clis/opencti.py lookup 1.2.3.4 python3 tools/clis/opencti.py lookup evil.example.com --limit 10
Permission review
The documentation asks the agent to run terminal commands or scripts.
python3 tools/clis/opencti.py versionThe documentation asks the agent to run terminal commands or scripts.
python3 tools/clis/opencti.py lookup 1.2.3.4Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 89/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 11 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Two-way bridge to an OpenCTI threat-intelligence platform. OpenCTI is a STIX 2.1-native knowledge base: everything in it — indicators, observables, intrusion sets, malware, reports, campaigns — is a STIX entity connected by relationships. Like /lookup-misp, this skill also writes: it can create indicators and observables, label and TLP-mark entities, relate them, and import STIX 2.1 bundles. Treat write commands as deliberate actions; don't use them in autonomous enrichment loops. The delete command is destructive — always confirm with the user before invoking it.
Read:
lookup)search, list, get)list with filters)connectors, version)Write:
/stix-bundle should be imported as entitiesDo NOT invoke for:
/lookup-misp). OpenCTI is your internal knowledge graph; MISP is the exchange layer. Many teams run both, synced by a connector.Single Python CLI (stdlib only — no install). Single endpoint: everything is GraphQL against $OPENCTI_URL/graphql with Authorization: Bearer $OPENCTI_TOKEN.
# Connectivity + version check
python3 tools/clis/opencti.py version
# Is this IOC known? Checks observables AND indicators in one call
python3 tools/clis/opencti.py lookup 1.2.3.4
python3 tools/clis/opencti.py lookup evil.example.com --limit 10
# Global full-text search across all entity types (actors, malware, reports, ...)
python3 tools/clis/opencti.py search "APT28" --limit 10
# List/filter one entity type. Types: indicators, observables, reports, incidents,
# campaigns, intrusion-sets, malware, attack-patterns, vulnerabilities, sightings
python3 tools/clis/opencti.py list indicators --score-gte 80 --created-after 2026-06-01T00:00:00Z
python3 tools/clis/opencti.py list reports --label apt28 --limit 10
python3 tools/clis/opencti.py list intrusion-sets --order-by modified --order desc
# Full detail + first 25 relationships for one entity (id from lookup/search/list)
python3 tools/clis/opencti.py get <internal-id>
# Connector health (which enrichment/import connectors are registered + active)
python3 tools/clis/opencti.py connectors
list paginates: when the response has has_next_page: true, pass the returned end_cursor back via --after for the next page.
# Create an indicator (auto-generates the STIX pattern; creates the underlying
# observable too by default so raw-value lookups will find it)
python3 tools/clis/opencti.py create-indicator \
--value 185.220.101.45 --type ip \
--score 85 --description 'C2 observed 2026-07-01' \
--labels apt28,c2
# Explicit STIX pattern (for anything the --type shorthand doesn't cover)
python3 tools/clis/opencti.py create-indicator \
--pattern "[file:hashes.'SHA-256' = '<hash>' AND file:name = 'dropper.exe']" \
--observable-type StixFile --name 'APT28 dropper'
# Create a bare observable (a fact, no detection semantics)
python3 tools/clis/opencti.py create-observable --value 185.220.101.45 --type ip --labels apt28
# Label + TLP-mark an existing entity (labels are auto-created if missing)
python3 tools/clis/opencti.py add-label <id> apt28 c2
python3 tools/clis/opencti.py add-marking <id> TLP:AMBER
# Update a field (name | description | score | confidence)
python3 tools/clis/opencti.py update <id> --field score --value 95
# Relate two entities with a STIX relationship (indicates, uses, targets, ...)
python3 tools/clis/opencti.py create-relationship --from <indicator-id> --to <malware-id> --type indicates
# Import a STIX 2.1 bundle (upload + trigger import job)
python3 tools/clis/opencti.py upload-stix data/stix-bundles/2026-07-01-apt28-c2.json
# Delete an entity — DESTRUCTIVE. Confirm with the user first.
python3 tools/clis/opencti.py delete <id>
All commands accept --dry-run (preview the GraphQL request without sending) and --insecure (skip TLS verification, common on internal deployments).
The CLI exits 2 if OPENCTI_URL or OPENCTI_TOKEN is unset (when not in dry-run). Report missing credentials; do not fabricate.
OpenCTI separates the two, and it matters for both reads and writes:
lookup checks both and reports which matched (known_as). When writing: use create-indicator for anything you'd want detections or blocklists built from, and let it create the companion observable (the default — don't pass --no-observable unless you have a reason; without the observable, raw value-searches won't find the IOC). Use create-observable for context-only sightings. Deleting an indicator does not cascade to its observable, and vice versa.
OpenCTI is STIX-native, so bundles from /stix-bundle import without the marking-definition surgery MISP needs:
/ip-investigation)/stix-bundle)/apply-tlp, /score-source)python3 tools/clis/opencti.py upload-stix <bundle.json>Import semantics: by default the CLI triggers the import with bypassValidation, which imports the bundle directly. With --no-bypass (or if your token lacks the bypass capability) the bundle lands in the analyst workbench (Data → Import) awaiting human validation — uploaded but not yet in the knowledge base. The CLI's response note tells you which happened; relay it. Import is asynchronous — poll with lookup/search; small bundles take seconds.
All commands return JSON:
source: opencti
operation: lookup | search | list | get | create-indicator | upload-stix | ...
query_time: <ISO8601>
# lookup:
known: true|false
known_as: [observable, indicator]
observables: [...]
indicators: [...]
# list:
total_matches: <n>
has_next_page: true|false
end_cursor: <cursor for --after>
results: [...]
# get:
entity: {...}
relationships: [...]
Default rating for downstream /score-source: B2 (usually reliable, probably true). OpenCTI is an aggregation platform — the rating belongs to the feed or author behind the entity, not the platform. Check createdBy and the entity's labels/markings:
confidence field on the entity (0-100) maps directly onto /confidence-levels bandserrors array — the CLI surfaces the first message and exits 1. AUTH_REQUIRED means a bad or missing token.x_opencti_score feeds downstream decay and detection-export rules on many deployments. Don't inflate scores on write; 50 is neutral.add-label and --labels auto-create missing labels — check list indicators --label <name> for the existing convention before inventing a new one./stix-bundle — write STIX 2.1 bundles that this CLI's upload-stix consumes (OpenCTI accepts them as-is; no MISP-style TLP workaround needed)/lookup-misp — the sharing-platform sibling; OpenCTI = internal knowledge graph, MISP = community exchange/lookup-virustotal, /lookup-otx — community reputation lookups; chain before pushing into OpenCTI/score-source — apply Admiralty rating before publishing/apply-tlp — decide TLP before add-marking/ip-investigation, /domain-investigation, /hash-investigation, /url-investigation — produce findings that OpenCTI write commands consume/threat-actor-profiling, /campaign-tracking — consume search/list/get output for actor and campaign contexttools/integrations/opencti.mdtools/clis/opencti.py$OPENCTI_URL/public/graphql (when enabled by the admin)Alternatives
prisma/prisma
Review what Prisma Next migrations will run on merge or deploy, render the migration graph, resolve concurrent / diamond-convergence conflicts, and configure environment refs for CI. Use for "what migrations are going to run", "what runs on deploy", merge conflict, diamond convergence, concurrent migrations, migration status, ref management, staging, production, MIGRATION.DIVERGED, MIGRATION.NO_MARKER, MIGRATION.MARKER_NOT_IN_HISTORY, prisma migrate status, prisma migrate diff, prisma migrate re
teng-lin/notebooklm-py
Complete API for Google NotebookLM - full programmatic access including features not in the web UI. Create notebooks, add sources, generate all artifact types, download in multiple formats. Activates on explicit /notebooklm or intent like "create a podcast about X"
wanshuiyin/Auto-claude-code-research-in-sleep
Use it for deployment and design tasks; the detail page covers purpose, installation, and practical steps.
huggingface/skills
Build and publish a Gradio demo on Hugging Face Spaces for a user-provided LoRA. Use when someone asks to create, generate, ship, or publish a Space, demo, Gradio app, or playground for a LoRA — including LoRAs for Qwen-Image, Qwen-Image-Edit, LTX-Video, Wan, FLUX, SDXL, or other diffusion base models. Also triggers when someone describes a LoRA they trained or hosts on the Hub and wants to share it. Covers picking the right base pipeline and `diffusers` inference recipe, designing a UI tailored