Data Structure Protocol (DSP)
DSP builds a dependency graph of project entities in a .dsp/ directory. Each entity (module, function, external dependency) gets a UID, description, import list, and export index. The graph answers: what exists, why it exists, what depends on what, and who uses what.
DSP is NOT documentation for humans or AST dump. It captures meaning (purpose), boundaries (imports/exports), and reasons for connections (why).
Agent Prompt
Embed this context when working on a DSP-tracked project:
This project uses DSP (Data Structure Protocol).
The .dsp/ directory is the entity graph of this project: modules, functions, dependencies, public API. It is your long-term memory of the code structure.
Core rules:
- Before changing code — find affected entities via
dsp-cli search, find-by-source, or read-toc. Read their description and imports to understand context.
- When creating a file/module — call
dsp-cli create-object. For each exported function — create-function (with --owner). Register exports via create-shared.
- When adding an import — call
dsp-cli add-import with a brief why. For external dependencies — first create-object --kind external if the entity doesn't exist yet.
- When removing import / export / file — call
remove-import, remove-shared, remove-entity respectively. Cascade cleanup is automatic.
- When renaming/moving a file — call
move-entity. UID does not change.
- Don't touch DSP if only internal implementation changed without affecting purpose or dependencies.
- Bootstrap — if
.dsp/ is empty, traverse the project from root entrypoint via DFS on imports, documenting every file.
Key commands:
dsp-cli init
dsp-cli create-object <source> <purpose> [--kind external] [--toc ROOT_UID]
dsp-cli create-function <source> <purpose> [--owner UID] [--toc ROOT_UID]
dsp-cli create-shared <exporter_uid> <shared_uid> [<shared_uid> ...]
dsp-cli add-import <importer_uid> <imported_uid> <why> [--exporter UID]
dsp-cli remove-import <importer_uid> <imported_uid> [--exporter UID]
dsp-cli remove-shared <exporter_uid> <shared_uid>
dsp-cli remove-entity <uid>
dsp-cli move-entity <uid> <new_source>
dsp-cli update-description <uid> [--source S] [--purpose P] [--kind K]
dsp-cli get-entity <uid>
dsp-cli get-children <uid> [--depth N]
dsp-cli get-parents <uid> [--depth N]
dsp-cli search <query>
dsp-cli find-by-source <path>
dsp-cli read-toc [--toc ROOT_UID]
dsp-cli get-stats
Using the CLI
The script is at scripts/dsp-cli.py relative to this skill directory.
python <skill-path>/scripts/dsp-cli.py [--root <project-root>] <command> [args]
--root defaults to current working directory. All paths in arguments are repo-relative.
Core Concepts
- Code = graph. Nodes are Objects and Functions. Edges are
imports and shared/exports.
- Identity by UID, not file path. Path is an attribute; renames/moves don't change UID.
- "Shared" creates an entity. If something becomes public (exported), it gets its own UID.
- Import tracks both "from where" and "what". One code import may create two DSP links: to the module and to the specific shared entity.
- Full import coverage. Every imported file/asset must be an Object in
.dsp — code, images, styles, configs, everything.
why lives next to the imported entity in its exports/ directory (reverse index).
- Start from roots. Each root entrypoint has its own TOC file.
- External deps — record only.
kind: external, no deep dive into node_modules/site-packages/etc. But exports index works — shows who imports it.
UID Format
- Objects:
obj-<8 hex> (e.g., obj-a1b2c3d4)
- Functions:
func-<8 hex> (e.g., func-7f3a9c12)
UID marker in source code — comment @dsp <uid> before declaration:
// @dsp func-7f3a9c12
export function calculateTotal(items) { ... }
# @dsp obj-e5f6g7h8
class UserService:
Workflows
Setting Up DSP
- Run
dsp-cli init to create .dsp/ directory.
- Identify root entrypoint(s) —
package.json main, framework entry, etc.
- Run bootstrap (DFS from root). See bootstrap.md.
Creating Entities (when writing new code)
- Create module:
dsp-cli create-object <path> <purpose>
- Create functions:
dsp-cli create-function <path>#<symbol> <purpose> --owner <module-uid>
- Register exports:
dsp-cli create-shared <module-uid> <func-uid> [<func-uid> ...]
- Register imports:
dsp-cli add-import <this-uid> <imported-uid> <why> [--exporter <module-uid>]
- External deps:
dsp-cli create-object <package-name> <purpose> --kind external
Navigating the Graph (when reading/understanding code)
- Find entity by file:
dsp-cli find-by-source <path>
- Search by keyword:
dsp-cli search <query>
- Read TOC:
dsp-cli read-toc → get all UIDs, then get-entity for details
- Dependency tree down:
dsp-cli get-children <uid> --depth N
- Dependency tree up:
dsp-cli get-parents <uid> --depth N
- Impact analysis:
dsp-cli get-recipients <uid> — who depends on this entity
- Path between entities:
dsp-cli get-path <from> <to>
Updating (when modifying code)
- Purpose changed:
dsp-cli update-description <uid> --purpose <new>
- File moved:
dsp-cli move-entity <uid> <new-path>
- Import reason changed:
dsp-cli update-import-why <importer> <imported> <new-why>
Deleting (when removing code)
- Import removed:
dsp-cli remove-import <importer> <imported> [--exporter UID]
- Export removed:
dsp-cli remove-shared <exporter> <shared>
- File/module deleted:
dsp-cli remove-entity <uid> (cascading cleanup)
Diagnostics
dsp-cli detect-cycles — circular dependencies
dsp-cli get-orphans — unused entities
dsp-cli get-stats — project graph overview
When to Update DSP
| Code Change |
DSP Action |
| New file/module |
create-object + create-function + create-shared + add-import |
| New import added |
add-import (+ create-object --kind external if new external dep) |
| Import removed |
remove-import |
| Export added |
create-shared (+ create-function if new function) |
| Export removed |
remove-shared |
| File renamed/moved |
move-entity |
| File deleted |
remove-entity |
| Purpose changed |
update-description |
| Internal-only change |
No DSP update needed |
References
- Storage format —
.dsp/ directory structure, file formats, TOC
- Bootstrap procedure — initial project markup (DFS algorithm)
- Operations reference — detailed semantics of all operations with import examples
1---2name: data-structure-protocol3description: Build and navigate DSP (Data Structure Protocol) — graph-based long-term structural memory of codebases for LLM agents. Stores entities (modules, functions), their dependencies (imports), public API (shared/exports), and reasons for every connection. Use when: (1) project has a .dsp/ directory, (2) user asks to set up DSP or bootstrap project structure, (3) creating/modifying/deleting code files in a DSP-tracked project, (4) navigating project structure, understanding dependencies, or finding modules, (5) user mentions DSP, dsp-cli, .dsp, or structure mapping.4---5
6# Data Structure Protocol (DSP)
7
8DSP builds a dependency graph of project entities in a `.dsp/` directory. Each entity (module, function, external dependency) gets a UID, description, import list, and export index. The graph answers: what exists, why it exists, what depends on what, and who uses what.
9
10**DSP is NOT documentation for humans or AST dump.** It captures _meaning_ (purpose), _boundaries_ (imports/exports), and _reasons for connections_ (why).
11
12## Agent Prompt
13
14Embed this context when working on a DSP-tracked project:
15
16> **This project uses DSP (Data Structure Protocol).**
17> The `.dsp/` directory is the entity graph of this project: modules, functions, dependencies, public API. It is your long-term memory of the code structure.
18>
19> **Core rules:**
20>
21> 1. **Before changing code** — find affected entities via `dsp-cli search`, `find-by-source`, or `read-toc`. Read their `description` and `imports` to understand context.
22> 2. **When creating a file/module** — call `dsp-cli create-object`. For each exported function — `create-function` (with `--owner`). Register exports via `create-shared`.
23> 3. **When adding an import** — call `dsp-cli add-import` with a brief `why`. For external dependencies — first `create-object --kind external` if the entity doesn't exist yet.
24> 4. **When removing import / export / file** — call `remove-import`, `remove-shared`, `remove-entity` respectively. Cascade cleanup is automatic.
25> 5. **When renaming/moving a file** — call `move-entity`. UID does not change.
26> 6. **Don't touch DSP** if only internal implementation changed without affecting purpose or dependencies.
27> 7. **Bootstrap** — if `.dsp/` is empty, traverse the project from root entrypoint via DFS on imports, documenting every file.
28>
29> **Key commands:**
30> ```
31> dsp-cli init
32> dsp-cli create-object <source> <purpose> [--kind external] [--toc ROOT_UID]
33> dsp-cli create-function <source> <purpose> [--owner UID] [--toc ROOT_UID]
34> dsp-cli create-shared <exporter_uid> <shared_uid> [<shared_uid> ...]
35> dsp-cli add-import <importer_uid> <imported_uid> <why> [--exporter UID]
36> dsp-cli remove-import <importer_uid> <imported_uid> [--exporter UID]
37> dsp-cli remove-shared <exporter_uid> <shared_uid>
38> dsp-cli remove-entity <uid>
39> dsp-cli move-entity <uid> <new_source>
40> dsp-cli update-description <uid> [--source S] [--purpose P] [--kind K]
41> dsp-cli get-entity <uid>
42> dsp-cli get-children <uid> [--depth N]
43> dsp-cli get-parents <uid> [--depth N]
44> dsp-cli search <query>
45> dsp-cli find-by-source <path>
46> dsp-cli read-toc [--toc ROOT_UID]
47> dsp-cli get-stats
48> ```
49
50## Using the CLI
51
52The script is at `scripts/dsp-cli.py` relative to this skill directory.
53
54```
55python <skill-path>/scripts/dsp-cli.py [--root <project-root>] <command> [args]
56```
57
58`--root` defaults to current working directory. All paths in arguments are repo-relative.
59
60## Core Concepts
61
62- **Code = graph.** Nodes are Objects and Functions. Edges are `imports` and `shared/exports`.
63- **Identity by UID, not file path.** Path is an attribute; renames/moves don't change UID.
64- **"Shared" creates an entity.** If something becomes public (exported), it gets its own UID.
65- **Import tracks both "from where" and "what".** One code import may create two DSP links: to the module and to the specific shared entity.
66- **Full import coverage.** Every imported file/asset must be an Object in `.dsp` — code, images, styles, configs, everything.
67- **`why` lives next to the imported entity** in its `exports/` directory (reverse index).
68- **Start from roots.** Each root entrypoint has its own TOC file.
69- **External deps — record only.** `kind: external`, no deep dive into `node_modules`/`site-packages`/etc. But `exports index` works — shows who imports it.
70
71## UID Format
72
73- Objects: `obj-<8 hex>` (e.g., `obj-a1b2c3d4`)
74- Functions: `func-<8 hex>` (e.g., `func-7f3a9c12`)
75
76UID marker in source code — comment `@dsp <uid>` before declaration:
77
78```js
79// @dsp func-7f3a9c12
80export function calculateTotal(items) { ... }
81```
82
83```python
84# @dsp obj-e5f6g7h8
85class UserService:
86```
87
88## Workflows
89
90### Setting Up DSP
91
921. Run `dsp-cli init` to create `.dsp/` directory.
932. Identify root entrypoint(s) — `package.json` main, framework entry, etc.
943. Run bootstrap (DFS from root). See [bootstrap.md](references/bootstrap.md).
95
96### Creating Entities (when writing new code)
97
981. Create module: `dsp-cli create-object <path> <purpose>`
992. Create functions: `dsp-cli create-function <path>#<symbol> <purpose> --owner <module-uid>`
1003. Register exports: `dsp-cli create-shared <module-uid> <func-uid> [<func-uid> ...]`
1014. Register imports: `dsp-cli add-import <this-uid> <imported-uid> <why> [--exporter <module-uid>]`
1025. External deps: `dsp-cli create-object <package-name> <purpose> --kind external`
103
104### Navigating the Graph (when reading/understanding code)
105
106- **Find entity by file**: `dsp-cli find-by-source <path>`
107- **Search by keyword**: `dsp-cli search <query>`
108- **Read TOC**: `dsp-cli read-toc` → get all UIDs, then `get-entity` for details
109- **Dependency tree down**: `dsp-cli get-children <uid> --depth N`
110- **Dependency tree up**: `dsp-cli get-parents <uid> --depth N`
111- **Impact analysis**: `dsp-cli get-recipients <uid>` — who depends on this entity
112- **Path between entities**: `dsp-cli get-path <from> <to>`
113
114### Updating (when modifying code)
115
116- Purpose changed: `dsp-cli update-description <uid> --purpose <new>`
117- File moved: `dsp-cli move-entity <uid> <new-path>`
118- Import reason changed: `dsp-cli update-import-why <importer> <imported> <new-why>`
119
120### Deleting (when removing code)
121
122- Import removed: `dsp-cli remove-import <importer> <imported> [--exporter UID]`
123- Export removed: `dsp-cli remove-shared <exporter> <shared>`
124- File/module deleted: `dsp-cli remove-entity <uid>` (cascading cleanup)
125
126### Diagnostics
127
128- `dsp-cli detect-cycles` — circular dependencies
129- `dsp-cli get-orphans` — unused entities
130- `dsp-cli get-stats` — project graph overview
131
132## When to Update DSP
133
134| Code Change | DSP Action |
135|---|---|
136| New file/module | `create-object` + `create-function` + `create-shared` + `add-import` |
137| New import added | `add-import` (+ `create-object --kind external` if new external dep) |
138| Import removed | `remove-import` |
139| Export added | `create-shared` (+ `create-function` if new function) |
140| Export removed | `remove-shared` |
141| File renamed/moved | `move-entity` |
142| File deleted | `remove-entity` |
143| Purpose changed | `update-description` |
144| Internal-only change | **No DSP update needed** |
145
146## References
147
148- **[Storage format](references/storage-format.md)** — `.dsp/` directory structure, file formats, TOC
149- **[Bootstrap procedure](references/bootstrap.md)** — initial project markup (DFS algorithm)
150- **[Operations reference](references/operations.md)** — detailed semantics of all operations with import examples