Agent skill

Devkg Sparql

by robertoshimizu in robertoshimizu/session-graph

Query the Dev Knowledge Graph via SPARQL instead of grepping raw session files.

Apache-2.0Auto-check passedKnowledge Management

Install Devkg Sparql

skills CLI
$ npx skills add robertoshimizu/session-graph --skill devkg-sparql -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install robertoshimizu/session-graph devkg-sparql --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/robertoshimizu/session-graph.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/devkg-sparql .claude/skills/devkg-sparql && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
devkg-sparql
GitHub stars
112
Token cost
~7.6k tokens
SKILL.md length
1,794 words
Files
1
Skills in repo
1
Repo updated
First seen
Licence
Apache-2.0

At a glance

Query the Dev Knowledge Graph via SPARQL instead of grepping raw session files.

  • Works in 12 steps: Entity Lookup — "What do we know about X?" → Entity-to-Entity — "How does X relate to… → Predicate Search — "What… → …
  • Tasks that involve Knowledge graphs
  • SKILL.md covers CRITICAL CONTEXT-SAFETY RULE, Retrieval Strategy (read this…, Execution Pattern and Fallback Rule, plus 5 more sections
  • Calls curl and jq; reaches w3.org and wikidata.org

What it does

Devkg Sparql is an agent skill from robertoshimizu/session-graph. Query the Dev Knowledge Graph via SPARQL instead of grepping raw session files. Use this when asked about technologies, relationships between tools, session history, where a topic was discussed, or cross-platform knowledge. Prefer provenance-first SPARQL (message + session) over label-only CONTAINS or grep.

Its SKILL.md is about 7.6k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Knowledge Management, covering Knowledge graphs. The repository describes itself as: Turn your scattered AI coding sessions into a queryable knowledge graph. Multi-platform (Claude Code, ChatGPT, DeepSeek, Grok, Warp), W3C ontology, Wikidata entity linking, SPARQL. The licence is Apache-2.0.

When your agent uses it

  • Tasks that involve Knowledge graphs

Example prompts

  • “/devkg-sparql”

Requirements

  • Python 3
  • Pre-approved tools (allowed-tools): Bash(curl:*), Bash(jq:*)

Workflow steps

12 steps, taken from the step headings in SKILL.md.

  1. Entity Lookup — "What do we know about X?"
  2. Entity-to-Entity — "How does X relate to Y?"
  3. Predicate Search — "What uses/enables/solves X?"
  4. Session Listing — "What sessions exist?"
  5. Topic + Intent → Sessions (PRIMARY for "where did we discuss X?")
  6. Topic Search (label-only) — fallback entity scan
  7. Cross-Platform Overlap — "What entities appear across platforms?"
  8. Wikidata Enrichment — "What is X?"
  9. Full-Text Content Search — "Find messages mentioning keyword X"
  10. Session Insight Pack — "Summarize what session S knew"
  11. 2-Hop Neighborhood — "What connects to X and what connects to those?"
  12. Hub Detection — "What are the most connected entities?"

What it can do on your machine

Read from SKILL.md and the folder at commit 4adefaa. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves these tools, so the agent can use them without asking each time:

    • Bash(curl:*)
    • Bash(jq:*)

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • curl
    • jq

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • w3.org
    • wikidata.org
    • query.wikidata.org
    • rdfs.org
    • purl.org

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Devkg Sparql loads about 7.6k tokens when it runs. Until then it costs about 80 tokens; SKILL.md has 1,794 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~80
When it runs · the whole SKILL.md, loaded when a task matches
~7.6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from robertoshimizu/session-graph at commit 4adefaa, republished under its Apache-2.0 licence (© robertoshimizu). 1,794 words, ~7,582 tokens.

Download SKILL.mdSave it as .claude/skills/devkg-sparql/SKILL.md (or your agent's skills folder).
name
devkg-sparql
description
Query the Dev Knowledge Graph via SPARQL instead of grepping raw session files. Use this when asked about technologies, relationships between tools, session history, where a topic was discussed, or cross-platform knowledge. Prefer provenance-first SPARQL (message + session) over label-only CONTAINS or grep.
allowed-tools
Bash(curl:*), Bash(jq:*)
user-invocable
true

DevKG SPARQL Query Skill

CRITICAL CONTEXT-SAFETY RULE

NEVER READ LARGE SPARQL RESULTS, SESSION FILES, JSONL, LOGS, OR GENERATED ARTIFACTS ALL AT ONCE. Always add LIMIT, select only needed variables, inspect counts first, and summarize. Never dump huge result sets, ID lists, raw JSON, or transcript content into chat.

Query the developer knowledge graph at http://localhost:3030/devkg/sparql via SPARQL. This graph contains extracted knowledge triples, entities, Wikidata links, and session metadata from Claude Code, pi, Codex, Cursor, ChatGPT, DeepSeek, Grok, and Warp sessions.

Content limit: sioc:content on messages is capped at ~2000 characters at ingest. SPARQL is enough to locate sessions and reason lightly from triples + snippets. For full quotes or deep thread reconstruction, normalize hasSourceFile and read the JSONL only when needed.

Retrieval Strategy (read this first)

User intentDo this firstDo NOT start with
"Where / which sessions discussed X?"Template 5 (topic + intent + provenance)Label-only Template 6, or grep
"What do we know about technology X?"Template 1 (entity + provenance)Grep
"How does X relate to Y?"Template 2Grep
"Find the exact message wording"Template 5 or 9 → then JSONL only if snippet truncatedGrepping all projects

Default for session-discovery questions: multi-signal filter (topic and intent terms) on both triple labels and sioc:content, always joining extractedFrom / extractedInSession, ordered by DESC(?created), with LIMIT.

When Fuseki returns provenance hits, do not fall back to grep. Grep only if Fuseki is down or returns 0 rows after a provenance query.

Execution Pattern

Always use this pattern (POST, URL-encoded query, JSON output). Include Fuseki auth when required:

bash
curl -s -X POST 'http://localhost:3030/devkg/sparql' \
  -u admin:admin \
  -H 'Accept: application/sparql-results+json' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode "query=YOUR_SPARQL_HERE" \
  | jq -r '.results.bindings[] | [.var1.value, .var2.value] | @tsv'

Adjust the jq expression to match your SELECT variables. Use @tsv for compact tabular output. Always LIMIT results.

For multi-line queries, use double quotes around the --data-urlencode value and escape inner quotes:

bash
curl -s -X POST 'http://localhost:3030/devkg/sparql' \
  -u admin:admin \
  -H 'Accept: application/sparql-results+json' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode "query=PREFIX devkg: <http://devkg.local/ontology#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT ?label WHERE {
  ?e a devkg:Entity ; rdfs:label ?label .
  FILTER(LANG(?label) = \"\")
} LIMIT 10" \
  | jq -r '.results.bindings[] | .label.value'

Fallback Rule

If Fuseki is unreachable (curl fails or times out) or a provenance query (Template 5/8) returns 0 results, then fall back to grep-based session search:

bash
grep -rli "keyword" ~/.claude/projects ~/.pi/agent/sessions ~/.cursor/projects 2>/dev/null | head -20

Then read matching JSONL files with bounded Python extraction. Only use this as a last resort.

Resolving hasSourceFile to Disk (and Pruned Sources)

hasSourceFile is NOT always a real absolute path. Normalize before any Read:

hasSourceFile prefixReal on-disk location
/Users/...absolute path — use as-is
/claude-sessions/<munged>/<file>~/.claude/projects/<munged>/<file>
/pi-sessions/<munged>/<file>~/.pi/agent/sessions/<munged>/<file>
/codex-sessions/<path>~/.codex/sessions/<path>
/cursor-sessions/projects/<slug>/...~/.cursor/projects/<slug>/...
bash
resolve_session_path() {
  local sf="$1" p=""
  case "$sf" in
    /Users/*)                    p="$sf" ;;
    /claude-sessions/*)          p="$HOME/.claude/projects/${sf#/claude-sessions/}" ;;
    /pi-sessions/*)              p="$HOME/.pi/agent/sessions/${sf#/pi-sessions/}" ;;
    /codex-sessions/*)           p="$HOME/.codex/sessions/${sf#/codex-sessions/}" ;;
    /cursor-sessions/projects/*) p="$HOME/.cursor/projects/${sf#/cursor-sessions/projects/}" ;;
    *)                           p="$sf" ;;
  esac
  local stem="${p%.jsonl}"
  if [ -f "$p" ];              then echo "FILE:$p";                    return; fi
  if [ -f "$stem" ];           then echo "FILE:$stem";                 return; fi
  if [ -d "$stem/subagents" ]; then echo "SUBAGENTS:$stem/subagents";  return; fi
  if [ -d "$p/subagents" ];    then echo "SUBAGENTS:$p/subagents";     return; fi
  echo "PRUNED:$p"
}

If the path is PRUNED, do NOT grep the filesystem. Re-query KnowledgeTriples for that session via extractedInSession and reconstruct from labels + any remaining sioc:content.

Result Formatting

Present SPARQL results as markdown tables. Never dump raw JSON to the user.

Prefixes (copy into every query)

sparql
PREFIX rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs:    <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl:     <http://www.w3.org/2002/07/owl#>
PREFIX prov:    <http://www.w3.org/ns/prov#>
PREFIX sioc:    <http://rdfs.org/sioc/ns#>
PREFIX skos:    <http://www.w3.org/2004/02/skos/core#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX devkg:   <http://devkg.local/ontology#>
PREFIX data:    <http://devkg.local/data/>
PREFIX wd:      <http://www.wikidata.org/entity/>

Ontology Cheat Sheet

Classes
ClassParentDescription
devkg:Sessionprov:Activity, sioc:ForumA working session (conversation)
devkg:Messagesioc:Post, prov:EntityA message in a session
devkg:UserMessagedevkg:MessageHuman message
devkg:AssistantMessagedevkg:MessageAI message
devkg:ToolCallprov:ActivityLegacy tool invocation nodes (may be absent in new ingests — do not rely on them)
devkg:ToolResultprov:EntityLegacy tool output (may be absent in new ingests)
devkg:CodeArtifactprov:Entity, schema:SoftwareSourceCodeCode file/snippet
devkg:Entityprov:EntityExtracted technical concept
devkg:KnowledgeTriple—Reified triple (subject→predicate→object) with provenance
devkg:Projectprov:EntityA development project
devkg:Developerprov:AgentHuman developer
devkg:AIModelprov:AgentAI model (Claude, GPT, etc.)
devkg:Topicskos:ConceptKnowledge topic
Structural Predicates (Session/Message graph)
PredicateDomain → RangeNotes
devkg:usedInSessionMessage/ToolCall → SessionLinks content to its session
devkg:hasParentMessageMessage → MessageThread structure
devkg:mentionsTopicMessage → TopicTopic tagging
devkg:invokedToolAssistantMessage → ToolCallTool usage
devkg:hasToolResultToolCall → ToolResultTool output
devkg:producedArtifactActivity → CodeArtifactCode generation
devkg:belongsToProjectSession → ProjectProject membership
devkg:extractedFromKnowledgeTriple → MessageTriple provenance
devkg:extractedInSessionKnowledgeTriple → SessionTriple provenance
devkg:tripleSubjectKnowledgeTriple → EntityReified subject
devkg:tripleObjectKnowledgeTriple → EntityReified object
devkg:triplePredicateLabelKnowledgeTriple → xsd:stringPredicate name
Key Datatype Properties
PropertyOnValue
sioc:contentMessageMessage text (truncated ~2000 chars at ingest)
rdfs:labelEntity/Session/ProjectDisplay name
dcterms:createdSession/MessageISO datetime
devkg:hasSourcePlatformSessionclaude-code, pi-coding-agent, codex, cursor, chatgpt, deepseek, grok, warp
devkg:hasSourceFileSessionLogical path to raw source — normalize before Read (see "Resolving hasSourceFile to Disk")
devkg:hasToolNameToolCallLegacy — prefer KnowledgeTriples + message content for discovery
devkg:hasWorkingDirectorySessionProject directory path
owl:sameAsEntityWikidata URI (e.g., wd:Q28865)
Knowledge Predicates (24 total)

These connect devkg:Entity to devkg:Entity via direct edges AND are stored as devkg:triplePredicateLabel strings on reified devkg:KnowledgeTriple nodes:

uses, dependsOn, enables, isPartOf, hasPart, implements, extends, alternativeTo, solves, produces, configures, composesWith, provides, requires, isTypeOf, builtWith, deployedOn, storesIn, queriedWith, integratesWith, broader, narrower, relatedTo, servesAs

Query Templates

1. Entity Lookup — "What do we know about X?"

Returns all relationships (outbound + inbound) for an entity, with source file and content snippet for provenance. Use CONTAINS for fuzzy matching.

sparql
SELECT DISTINCT ?direction ?predicate ?otherLabel ?sourceFile ?platform
       (SUBSTR(?content, 1, 150) AS ?snippet) WHERE {
  {
    ?triple a devkg:KnowledgeTriple ;
            devkg:tripleSubject ?s ;
            devkg:triplePredicateLabel ?predicate ;
            devkg:tripleObject ?o ;
            devkg:extractedFrom ?msg ;
            devkg:extractedInSession ?session .
    ?s rdfs:label ?sLabel .
    ?o rdfs:label ?otherLabel .
    FILTER(CONTAINS(LCASE(STR(?sLabel)), "ENTITY_LOWER"))
    BIND("outbound" AS ?direction)
  } UNION {
    ?triple a devkg:KnowledgeTriple ;
            devkg:tripleSubject ?o ;
            devkg:triplePredicateLabel ?predicate ;
            devkg:tripleObject ?obj ;
            devkg:extractedFrom ?msg ;
            devkg:extractedInSession ?session .
    ?obj rdfs:label ?oLabel .
    ?o rdfs:label ?otherLabel .
    FILTER(CONTAINS(LCASE(STR(?oLabel)), "ENTITY_LOWER"))
    BIND("inbound" AS ?direction)
  }
  OPTIONAL { ?session devkg:hasSourceFile ?sourceFile }
  OPTIONAL { ?session devkg:hasSourcePlatform ?platform }
  OPTIONAL { ?msg sioc:content ?content }
}
ORDER BY ?direction ?predicate

Replace ENTITY_LOWER with the lowercase entity name (e.g., neo4j, opentelemetry).

The sourceFile column is a logical path to the original JSONL/JSON file — normalize it with resolve_session_path (see "Resolving hasSourceFile to Disk") before Read; if it resolves to PRUNED, reconstruct from the triples instead.

2. Entity-to-Entity — "How does X relate to Y?"
sparql
SELECT DISTINCT ?predicate ?sourceSnippet WHERE {
  ?triple a devkg:KnowledgeTriple ;
          devkg:tripleSubject ?s ;
          devkg:triplePredicateLabel ?predicate ;
          devkg:tripleObject ?o ;
          devkg:extractedFrom ?msg .
  ?s rdfs:label ?sLabel .
  ?o rdfs:label ?oLabel .
  OPTIONAL { ?msg sioc:content ?c . BIND(SUBSTR(?c, 1, 150) AS ?sourceSnippet) }
  FILTER(
    CONTAINS(LCASE(STR(?sLabel)), "ENTITY_X") &&
    CONTAINS(LCASE(STR(?oLabel)), "ENTITY_Y")
  )
}
3. Predicate Search — "What uses/enables/solves X?"
sparql
SELECT DISTINCT ?subjectLabel ?objectLabel WHERE {
  ?triple a devkg:KnowledgeTriple ;
          devkg:tripleSubject ?s ;
          devkg:triplePredicateLabel "PREDICATE" ;
          devkg:tripleObject ?o .
  ?s rdfs:label ?subjectLabel .
  ?o rdfs:label ?objectLabel .
  FILTER(CONTAINS(LCASE(STR(?subjectLabel)), "ENTITY_LOWER")
      || CONTAINS(LCASE(STR(?objectLabel)), "ENTITY_LOWER"))
}

Replace PREDICATE with one of the 24 predicates (e.g., uses, integratesWith).

4. Session Listing — "What sessions exist?"
sparql
SELECT ?session ?platform ?created ?title WHERE {
  ?session a devkg:Session .
  OPTIONAL { ?session devkg:hasSourcePlatform ?platform }
  OPTIONAL { ?session dcterms:created ?created }
  OPTIONAL { ?session dcterms:title ?title }
}
ORDER BY DESC(?created)
LIMIT 50
5. Topic + Intent → Sessions (PRIMARY for "where did we discuss X?")

Use this first for session discovery, career/product/person questions, or "exact piece of a session." Do not start with label-only Template 6.

Replace TOPIC_LOWER (required) and add intent terms in the second FILTER (at least one). Example: topic=linkedin, intent=profile|career|roberto|headline|authority.

sparql
SELECT DISTINCT ?created ?platform ?sourceFile ?subj ?pred ?obj
       (SUBSTR(REPLACE(STR(?content), "\n", " "), 1, 200) AS ?snippet)
WHERE {
  {
    # Path A: KnowledgeTriple labels match topic + intent
    ?kt a devkg:KnowledgeTriple ;
        devkg:tripleSubject ?s ;
        devkg:tripleObject ?o ;
        devkg:triplePredicateLabel ?pred ;
        devkg:extractedFrom ?msg ;
        devkg:extractedInSession ?sess .
    ?s rdfs:label ?subj .
    ?o rdfs:label ?obj .
    FILTER(LANG(?subj) = "" && LANG(?obj) = "")
    BIND(LCASE(CONCAT(STR(?subj), " ", STR(?obj))) AS ?tripleText)
    FILTER(CONTAINS(?tripleText, "TOPIC_LOWER"))
    FILTER(
      CONTAINS(?tripleText, "INTENT1")
      || CONTAINS(?tripleText, "INTENT2")
      || CONTAINS(?tripleText, "INTENT3")
    )
  }
  UNION
  {
    # Path B: message text matches topic + intent (catches misses in entity extraction)
    ?msg a ?msgType ;
         sioc:content ?content ;
         sioc:has_container ?sess .
    FILTER(?msgType IN (devkg:AssistantMessage, devkg:UserMessage))
    ?kt a devkg:KnowledgeTriple ;
        devkg:extractedFrom ?msg ;
        devkg:extractedInSession ?sess ;
        devkg:tripleSubject ?s ;
        devkg:tripleObject ?o ;
        devkg:triplePredicateLabel ?pred .
    ?s rdfs:label ?subj .
    ?o rdfs:label ?obj .
    FILTER(LANG(?subj) = "" && LANG(?obj) = "")
    BIND(LCASE(STR(?content)) AS ?msgText)
    FILTER(CONTAINS(?msgText, "TOPIC_LOWER"))
    FILTER(
      CONTAINS(?msgText, "INTENT1")
      || CONTAINS(?msgText, "INTENT2")
      || CONTAINS(?msgText, "INTENT3")
    )
  }
  OPTIONAL { ?msg sioc:content ?content }
  OPTIONAL { ?sess devkg:hasSourcePlatform ?platform }
  OPTIONAL { ?sess devkg:hasSourceFile ?sourceFile }
  OPTIONAL { ?sess dcterms:created ?created }
}
ORDER BY DESC(?created)
LIMIT 40

Present as a session table grouped by sourceFile (date, platform, hit count, 1–2 sample facts/snippets). Reason from triples + snippets when possible; open JSONL only if the user needs full wording beyond the 2000-char cap.

If intent is unknown, keep topic FILTER and drop the intent FILTER (broader recall).

6. Topic Search (label-only) — fallback entity scan

Simpler label scan. Prefer Template 5 when the user asks where or which sessions.

sparql
SELECT DISTINCT ?session ?platform ?created ?sourceFile WHERE {
  ?triple a devkg:KnowledgeTriple ;
          devkg:extractedInSession ?session .
  { ?triple devkg:tripleSubject ?e . ?e rdfs:label ?label . }
  UNION
  { ?triple devkg:tripleObject ?e . ?e rdfs:label ?label . }
  FILTER(CONTAINS(LCASE(STR(?label)), "TOPIC_LOWER"))
  OPTIONAL { ?session devkg:hasSourcePlatform ?platform }
  OPTIONAL { ?session dcterms:created ?created }
  OPTIONAL { ?session devkg:hasSourceFile ?sourceFile }
}
ORDER BY DESC(?created)
LIMIT 30
7. Cross-Platform Overlap — "What entities appear across platforms?"
sparql
SELECT ?label (GROUP_CONCAT(DISTINCT ?platform; separator=", ") AS ?platforms)
       (COUNT(DISTINCT ?platform) AS ?platformCount) WHERE {
  ?triple a devkg:KnowledgeTriple ;
          devkg:tripleSubject ?e ;
          devkg:extractedInSession ?session .
  ?session devkg:hasSourcePlatform ?platform .
  ?e rdfs:label ?label .
  FILTER(LANG(?label) = "")
}
GROUP BY ?label
HAVING(COUNT(DISTINCT ?platform) > 1)
ORDER BY DESC(?platformCount)
LIMIT 40
8. Wikidata Enrichment — "What is X?"
sparql
SELECT ?label ?wikidataURI ?description WHERE {
  ?entity a devkg:Entity ;
          rdfs:label ?label ;
          owl:sameAs ?wikidataURI .
  FILTER(STRSTARTS(STR(?wikidataURI), "http://www.wikidata.org"))
  FILTER(CONTAINS(LCASE(STR(?label)), "ENTITY_LOWER"))
  FILTER(LANG(?label) = "")
  OPTIONAL { ?entity dcterms:description ?description }
}
LIMIT 20
9. Full-Text Content Search — "Find messages mentioning keyword X"

Searches both user and assistant messages (assistant text holds most extractable knowledge).

sparql
SELECT ?platform ?created ?sourceFile
       (SUBSTR(REPLACE(STR(?content), "\n", " "), 1, 200) AS ?snippet)
WHERE {
  ?msg a ?msgType ;
       sioc:content ?content ;
       sioc:has_container ?session .
  FILTER(?msgType IN (devkg:AssistantMessage, devkg:UserMessage))
  OPTIONAL { ?session dcterms:created ?created }
  OPTIONAL { ?session devkg:hasSourcePlatform ?platform }
  OPTIONAL { ?session devkg:hasSourceFile ?sourceFile }
  FILTER(CONTAINS(LCASE(?content), "KEYWORD_LOWER"))
}
ORDER BY DESC(?created)
LIMIT 20
10. Session Insight Pack — "Summarize what session S knew"

Given a session URI or sourceFile, return predicate mix + sample provenance facts (no JSONL required for a light summary).

sparql
SELECT ?pred (COUNT(?kt) AS ?n) WHERE {
  ?sess devkg:hasSourceFile ?sourceFile .
  FILTER(CONTAINS(STR(?sourceFile), "SESSION_PATH_FRAGMENT"))
  ?kt a devkg:KnowledgeTriple ;
      devkg:extractedInSession ?sess ;
      devkg:triplePredicateLabel ?pred .
}
GROUP BY ?pred
ORDER BY DESC(?n)
LIMIT 24

Follow with sample facts:

sparql
SELECT ?subj ?pred ?obj
       (SUBSTR(REPLACE(STR(?content), "\n", " "), 1, 160) AS ?snippet)
WHERE {
  ?sess devkg:hasSourceFile ?sourceFile .
  FILTER(CONTAINS(STR(?sourceFile), "SESSION_PATH_FRAGMENT"))
  ?kt a devkg:KnowledgeTriple ;
      devkg:extractedInSession ?sess ;
      devkg:tripleSubject ?s ;
      devkg:tripleObject ?o ;
      devkg:triplePredicateLabel ?pred ;
      devkg:extractedFrom ?msg .
  ?s rdfs:label ?subj . ?o rdfs:label ?obj .
  FILTER(LANG(?subj) = "" && LANG(?obj) = "")
  OPTIONAL { ?msg sioc:content ?content }
}
LIMIT 15
11. 2-Hop Neighborhood — "What connects to X and what connects to those?"

Traverses outbound edges from X, then follows outbound edges from each neighbor. Shows the subgraph reachable in 2 hops.

sparql
SELECT DISTINCT ?aLabel ?p1 ?bLabel ?p2 ?cLabel WHERE {
  ?t1 a devkg:KnowledgeTriple ;
       devkg:tripleSubject ?a ;
       devkg:triplePredicateLabel ?p1 ;
       devkg:tripleObject ?b .
  ?a rdfs:label ?aLabel .
  ?b rdfs:label ?bLabel .
  FILTER(LANG(?aLabel) = "" && LANG(?bLabel) = "")
  FILTER(CONTAINS(LCASE(?aLabel), "ENTITY_LOWER"))
  OPTIONAL {
    ?t2 a devkg:KnowledgeTriple ;
         devkg:tripleSubject ?b ;
         devkg:triplePredicateLabel ?p2 ;
         devkg:tripleObject ?c .
    ?c rdfs:label ?cLabel .
    FILTER(LANG(?cLabel) = "")
  }
}
ORDER BY ?bLabel ?cLabel
LIMIT 40

For bidirectional 2-hop (also follows inbound edges), add a second UNION branch that reverses subject/object in each hop.

12. Hub Detection — "What are the most connected entities?"
sparql
SELECT ?label (COUNT(DISTINCT ?triple) AS ?degree) WHERE {
  {
    ?triple a devkg:KnowledgeTriple ;
            devkg:tripleSubject ?e .
    ?e rdfs:label ?label .
    FILTER(LANG(?label) = "")
  } UNION {
    ?triple a devkg:KnowledgeTriple ;
            devkg:tripleObject ?e .
    ?e rdfs:label ?label .
    FILTER(LANG(?label) = "")
  }
}
GROUP BY ?label
ORDER BY DESC(?degree)
LIMIT 20
13. Cross-Session Entity Overlap — "What sessions share knowledge?"
sparql
SELECT ?s1File ?s2File
       (COUNT(DISTINCT ?label) AS ?shared)
       (GROUP_CONCAT(DISTINCT ?label; separator=", ") AS ?sharedEntities)
WHERE {
  ?t1 a devkg:KnowledgeTriple ;
      devkg:tripleSubject ?e1 ;
      devkg:extractedInSession ?sess1 .
  ?t2 a devkg:KnowledgeTriple ;
      devkg:tripleSubject ?e2 ;
      devkg:extractedInSession ?sess2 .
  ?e1 rdfs:label ?label .
  ?e2 rdfs:label ?label .
  FILTER(LANG(?label) = "")
  FILTER(STR(?sess1) < STR(?sess2))
  OPTIONAL { ?sess1 devkg:hasSourceFile ?s1File }
  OPTIONAL { ?sess2 devkg:hasSourceFile ?s2File }
}
GROUP BY ?s1File ?s2File
HAVING(COUNT(DISTINCT ?label) > 2)
ORDER BY DESC(?shared)
LIMIT 10
14. Path Discovery — "How does X connect to Y?" (via intermediate entities)
sparql
SELECT DISTINCT ?p1 ?midLabel ?p2 WHERE {
  {
    ?t1 a devkg:KnowledgeTriple ;
        devkg:tripleSubject ?a ;
        devkg:triplePredicateLabel ?p1 ;
        devkg:tripleObject ?mid .
    ?t2 a devkg:KnowledgeTriple ;
        devkg:tripleSubject ?mid ;
        devkg:triplePredicateLabel ?p2 ;
        devkg:tripleObject ?b .
  } UNION {
    ?t1 a devkg:KnowledgeTriple ;
        devkg:tripleSubject ?mid ;
        devkg:triplePredicateLabel ?p1 ;
        devkg:tripleObject ?a .
    ?t2 a devkg:KnowledgeTriple ;
        devkg:tripleSubject ?mid ;
        devkg:triplePredicateLabel ?p2 ;
        devkg:tripleObject ?b .
  } UNION {
    ?t1 a devkg:KnowledgeTriple ;
        devkg:tripleSubject ?a ;
        devkg:triplePredicateLabel ?p1 ;
        devkg:tripleObject ?mid .
    ?t2 a devkg:KnowledgeTriple ;
        devkg:tripleSubject ?b ;
        devkg:triplePredicateLabel ?p2 ;
        devkg:tripleObject ?mid .
  }
  ?a rdfs:label ?aLabel .
  ?b rdfs:label ?bLabel .
  ?mid rdfs:label ?midLabel .
  FILTER(LANG(?aLabel) = "" && LANG(?bLabel) = "" && LANG(?midLabel) = "")
  FILTER(CONTAINS(LCASE(?aLabel), "ENTITY_X"))
  FILTER(CONTAINS(LCASE(?bLabel), "ENTITY_Y"))
  FILTER(?a != ?b && ?a != ?mid && ?mid != ?b)
}
LIMIT 20

Present as: ENTITY_X --p1--> intermediate --p2--> ENTITY_Y

15. Project Knowledge Map — "What does project X know about?"
sparql
SELECT ?label (COUNT(DISTINCT ?triple) AS ?mentions) WHERE {
  ?session devkg:belongsToProject ?project .
  ?project rdfs:label ?projectLabel .
  FILTER(CONTAINS(LCASE(?projectLabel), "PROJECT_LOWER"))
  ?triple a devkg:KnowledgeTriple ;
          devkg:extractedInSession ?session .
  { ?triple devkg:tripleSubject ?e . ?e rdfs:label ?label . }
  UNION
  { ?triple devkg:tripleObject ?e . ?e rdfs:label ?label . }
  FILTER(LANG(?label) = "")
}
GROUP BY ?label
ORDER BY DESC(?mentions)
LIMIT 30
Show full SKILL.md (718 more words)Show less
16. Sibling Entities — "What else uses/requires/enables the same thing as X?"
sparql
SELECT DISTINCT ?siblingLabel ?predicate ?sharedLabel WHERE {
  ?t1 a devkg:KnowledgeTriple ;
      devkg:tripleSubject ?x ;
      devkg:triplePredicateLabel ?predicate ;
      devkg:tripleObject ?shared .
  ?t2 a devkg:KnowledgeTriple ;
      devkg:tripleSubject ?sibling ;
      devkg:triplePredicateLabel ?predicate ;
      devkg:tripleObject ?shared .
  ?x rdfs:label ?xLabel .
  ?sibling rdfs:label ?siblingLabel .
  ?shared rdfs:label ?sharedLabel .
  FILTER(LANG(?xLabel) = "" && LANG(?siblingLabel) = "" && LANG(?sharedLabel) = "")
  FILTER(CONTAINS(LCASE(?xLabel), "ENTITY_LOWER"))
  FILTER(?x != ?sibling)
}
ORDER BY ?predicate ?sharedLabel
LIMIT 40

Wikidata Graph Traversal

Many entities in the local graph have owl:sameAs links to Wikidata QIDs. You can cross into Wikidata's public SPARQL endpoint to discover knowledge that doesn't exist locally — drug classes, software ecosystems, related technologies, disambiguation, etc.

Wikidata endpoint: https://query.wikidata.org/sparql

Execution pattern (same as local, but different URL + requires User-Agent header):

bash
curl -s -X POST 'https://query.wikidata.org/sparql' \
  -H 'Accept: application/sparql-results+json' \
  -H 'User-Agent: DevKG/1.0' \
  --data-urlencode "query=YOUR_SPARQL_HERE" \
  | jq -r '...'

Rate limits: Wikidata allows ~60 requests/minute for anonymous users. Add 1-second delay between queries if doing batch lookups.

Workflow: Local → Wikidata → Back to Local
  1. Start local: Use Template 1 to find what you know about entity X
  2. Get QID: Use Template 8 to retrieve the owl:sameAs Wikidata URI
  3. Cross to Wikidata: Use the QID in Wikidata templates below to discover new knowledge
  4. Come back: Use what you learned to ask better local queries (e.g., discovered a peer → check if it exists locally)
W1. Entity Properties — "What does Wikidata know about QID?"

Returns all direct properties with human-readable labels. Use this first to understand what's available.

sparql
SELECT ?propLabel ?valLabel WHERE {
  wd:QID ?p ?val .
  ?prop wikibase:directClaim ?p .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} LIMIT 30

Key properties to look for:

  • instance of (P31) — what kind of thing it is
  • subclass of (P279) — broader category
  • has use (P366) — what it's used for
  • programmed in (P277) — implementation language (software)
  • uses (P2283) — technologies it depends on
  • part of (P361) — larger system it belongs to
  • ATC code (P267) — drug classification (medications)
  • route of administration (P636) — how a drug is taken
W2. Peer Discovery — "What else is the same kind of thing as X?"

Given a QID, finds its instance of class, then finds all other instances of that class. Discovers alternatives and competitors.

sparql
SELECT ?peerLabel ?peerDescription WHERE {
  wd:QID wdt:P31 ?class .
  ?peer wdt:P31 ?class .
  FILTER(?peer != wd:QID)
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} LIMIT 20

Examples:

  • Neo4j (Q1628290) → instance of: graph database management system → finds ArangoDB, JanusGraph, Amazon Neptune, Dgraph, etc.
  • Fosfomycin (Q183554) → instance of: type of chemical entity → (too broad, use P2868 "subject has role" or ATC code instead)
W3. Disambiguation — "Is this the right entity?"

When an entity label is ambiguous, fetch the Wikidata description to verify. Use this before trusting an owl:sameAs link.

sparql
SELECT ?label ?description WHERE {
  wd:QID rdfs:label ?label .
  wd:QID schema:description ?description .
  FILTER(LANG(?label) = "en")
  FILTER(LANG(?description) = "en")
}
W4. Broader Categories — "What category tree does X belong to?"

Traverses subclass of (P279) upward to find the classification hierarchy.

sparql
SELECT ?classLabel ?superClassLabel WHERE {
  wd:QID wdt:P31 ?class .
  ?class wdt:P279* ?superClass .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} LIMIT 20
W5. Relationship Bridge — "How do two entities connect in Wikidata?"

When two local entities have Wikidata links but no direct local connection, check if Wikidata knows a relationship.

sparql
SELECT ?propLabel WHERE {
  wd:QID_X ?p wd:QID_Y .
  ?prop wikibase:directClaim ?p .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
}

If no direct link, try 2-hop:

sparql
SELECT ?propLabel1 ?midLabel ?propLabel2 WHERE {
  wd:QID_X ?p1 ?mid .
  ?mid ?p2 wd:QID_Y .
  ?prop1 wikibase:directClaim ?p1 .
  ?prop2 wikibase:directClaim ?p2 .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} LIMIT 10
W6. Batch QID Lookup — "Enrich all linked entities at once"

First get all QIDs from the local graph, then query Wikidata for their classes in one request.

Step 1 (local): Extract QIDs

sparql
SELECT ?label (REPLACE(STR(?wikidata), "http://www.wikidata.org/entity/", "") AS ?qid) WHERE {
  ?e a devkg:Entity ; rdfs:label ?label ; owl:sameAs ?wikidata .
  FILTER(LANG(?label) = "")
  FILTER(STRSTARTS(STR(?wikidata), "http://www.wikidata.org"))
}

Step 2 (Wikidata): Get classes for multiple QIDs at once (use VALUES clause):

sparql
SELECT ?item ?itemLabel ?classLabel WHERE {
  VALUES ?item { wd:Q1628290 wd:Q183554 wd:Q28865 }
  ?item wdt:P31 ?class .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
}
When to Use Wikidata Traversal
QuestionLocal enough?Use Wikidata?
"What does X integrate with?"Yes (Template 1)No
"What kind of thing is X?"Maybe (if isTypeOf exists)Yes (W1, W4)
"What are alternatives to X?"Maybe (if alternativeTo exists)Yes (W2)
"Is this the right entity?"NoYes (W3)
"How does X relate to Y globally?"NoYes (W5)
"What drug class is X in?"NoYes (W1 → ATC code, P2868)
"What language is X written in?"MaybeYes (W1 → P277)

Tips

  • Session discovery ("where / which sessions"): always start with Template 5 (topic + intent + provenance). Do not start with label-only Template 6 or grep.
  • Always use DISTINCT — duplicate triples exist from lang-tagged vs untagged literals.
  • Always use FILTER(LANG(?label) = "") to avoid duplicate rows from lang-tagged literals.
  • Entity labels are lowercase in the graph. Always use LCASE() in FILTER for safety.
  • Multi-signal filters beat single keywords: topic (linkedin) and intent (profile, career, roberto).
  • For "What integrates with X?" questions, use Template 1 (bidirectional) — the relationship may be stored in either direction.
  • KnowledgeTriple nodes carry provenance: extractedFrom → source message, extractedInSession → session. Always project these when the user needs where.
  • sioc:content is capped at ~2000 chars — enough to locate and lightly reason; open JSONL only for full fidelity.
  • When following hasSourceFile, normalize the path first. If PRUNED, reconstruct from triples — do not grep.
  • If Fuseki returned provenance hits, do not fall back to grep.
  • Combine templates: e.g., Template 5 → Template 10 (session insight) → Template 8 (Wikidata) as needed.
  • Start with Template 12 (hubs) when exploring an unfamiliar graph.
  • Use Template 14 (path discovery) before concluding two concepts are unrelated.
  • Use Template 16 (siblings) to discover alternatives and peers.
  • Prefer relationship predicates (uses, dependsOn, solves, …) over treating the graph as a tag cloud of labels.

© robertoshimizu, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .claude/skills/devkg-sparql of robertoshimizu/session-graph.

Open the folder on GitHubat commit 4adefaa

Compare with similar skills

Devkg Sparql next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Devkg Sparql compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Devkg Sparql this skillrobertoshimizu/session-graph112—~7.6kAutomated safety check: PassApache-2.0
Obsidian Canvas BoardsAgriciDaniel/claude-obsidian15k—~1.4kAutomated safety check: PassMIT
Ontology1mancompany/OneManCompany4412 repos~1.5kAutomated safety check: PassApache-2.0
Knowledge Graphgnomeria/usbtree691—~1.5kAutomated safety check: PassMIT
Graphagenticnotetaking/arscontexta3.5k—~4.9kAutomated safety check: NotesMIT
LLM Wiki Knowledge GraphEgonex-AI/Understand-Anything86k—~1.5kAutomated safety check: PassMIT

Similar skills

  • Obsidian Canvas Boards

    AgriciDaniel/claude-obsidian

    Creates, inspects and updates Obsidian JSON Canvas boards in a vault, with text, file, link, group and edge nodes, using safe recoverable edits.

    15k GitHub stars~1.4k tokensUpdated 28 days ago
    Knowledge ManagementAuto-check passed
  • Ontology

    1mancompany/OneManCompany

    Typed knowledge graph for structured agent memory and composable skills.

    441 GitHub starsUsed in 2 repos~1.5k tokens
    Knowledge ManagementAuto-check passed
  • Knowledge Graph

    gnomeria/usbtree

    Set up and maintain a lightweight, file-based knowledge graph of the repo — entities, typed relations, decisions, gotchas — so agents load context fast instead of re-exploring the codebase every…

    691 GitHub stars~1.5k tokensUpdated 1 mo ago
    Knowledge ManagementAuto-check passed
  • Graph

    agenticnotetaking/arscontexta

    Interactive knowledge graph analysis. An agent skill from agenticnotetaking/arscontexta.

    3.5k GitHub stars~4.9k tokensUpdated 7 mo ago
    Knowledge ManagementAuto-check: notes
  • LLM Wiki Knowledge Graph

    Egonex-AI/Understand-Anything

    Detects a Karpathy-pattern LLM wiki and builds an interactive knowledge graph with entities, implicit relationships and topic clusters.

    86k GitHub stars~1.5k tokensUpdated today
    Knowledge ManagementAuto-check passed
  • Gitnexus Guide

    aws-samples/sample-kolya-br-proxy

    Official

    A skill your agent uses when the user asks about GitNexus itself — available tools, how to query the knowledge graph, MCP resources, graph schema, or workflow reference.

    106 GitHub starsUsed in 11 repos~867 tokens
    Knowledge ManagementAuto-check passed

Questions about Devkg Sparql

What does Devkg Sparql do?

Query the Dev Knowledge Graph via SPARQL instead of grepping raw session files. Devkg Sparql is an agent skill from robertoshimizu/session-graph. Query the Dev Knowledge Graph via SPARQL instead of grepping raw session files.

When should I use Devkg Sparql?

Devkg Sparql fits situations like: tasks that involve Knowledge graphs.

How do I install Devkg Sparql in Claude Code?

Run `npx skills add robertoshimizu/session-graph --skill devkg-sparql -a claude-code`. Or copy the skill folder (.claude/skills/devkg-sparql in robertoshimizu/session-graph) into .claude/skills/devkg-sparql in your project. Claude Code loads it when a task matches its description.

How do I install Devkg Sparql in Codex?

Run `npx skills add robertoshimizu/session-graph --skill devkg-sparql -a codex`. Or copy the skill folder (.claude/skills/devkg-sparql in robertoshimizu/session-graph) into .agents/skills/devkg-sparql in your project. Codex loads it when a task matches its description.

Can I use Devkg Sparql in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add robertoshimizu/session-graph --skill devkg-sparql -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/devkg-sparql, .gemini/skills/devkg-sparql, .github/skills/devkg-sparql and .opencode/skills/devkg-sparql in your project.

What does Devkg Sparql need to run?

Going by SKILL.md and its folder, Devkg Sparql needs the command-line tools its instructions call (curl and jq). Our summary lists: Python 3. Its frontmatter pre-approves these tools: Bash(curl:*), Bash(jq:*).

Does Devkg Sparql access the network?

SKILL.md names 5 domains. In commands or code: w3.org, wikidata.org, query.wikidata.org, rdfs.org and purl.org; the agent is likely to contact these when it follows the instructions. This is read from the text; nothing was executed.

Is Devkg Sparql safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Devkg Sparql use?

Devkg Sparql is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Devkg Sparql use?

About 7.6k tokens (SKILL.md is roughly 30k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Devkg Sparql?

Skills that share tags, products or a category with Devkg Sparql: Obsidian Canvas Boards (AgriciDaniel/claude-obsidian, 15k stars), Ontology (1mancompany/OneManCompany, 441 stars), Knowledge Graph (gnomeria/usbtree, 691 stars) and Graph (agenticnotetaking/arscontexta, 3.5k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Devkg Sparql?

robertoshimizu (a GitHub user) maintains it in robertoshimizu/session-graph, which has 112 GitHub stars. The repository was last updated on July 29, 2026.

Source: robertoshimizu/session-graph on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.