Add a linked resource (external file reference) to a ***plain spec. Use when the user wants to reference a JSON schema, API spec, data file, or other external file from within a functional spec, definition, or implementation requirement.
Always use the skill load-plain-reference to retrieve the ***plain syntax rules — but only if you haven't done so yet.
Linked resources are external files referenced from within a .plain spec using markdown link syntax. The file contents are passed to the renderer alongside the spec, providing additional context for code generation.
Workflow
Identify or create the resource file. Keep it inside the project — the resources/ directory is the conventional home; it does not have to sit next to the .plain file.
Add the markdown link at the appropriate place in the spec.
Verify the file path is relative to the .plain file location.
Read the file back to confirm correct link syntax and path.
Format
Use standard markdown link syntax inside any spec section:
***definitions***
- :AuthData: is the authentication data structure.
- Its format is defined in the [auth schema](resources/auth_schema.json).
***implementation reqs***
- When transforming :BackupData:, use the JOLT transform.
- The transform is defined in [backup_transform.jolt](resources/backup_transform.jolt).
***functional specs***
- An API conforming to the [API specification](resources/api_spec.yaml) is exposed.
Path Rules
Paths are resolved relative to the directory where codeplain is run (the current working directory).
Relative paths may traverse into parent directories — [resource](../../resources/resource.md) is valid — as long as they resolve to a real text file on disk.
No external URLs — only local file references.
No folder paths — the target must be a file, not a directory.
Only text-based files are supported.
A linked resource MUST be a single, text-based file that exists on disk
A linked resource is always a single file that exists on disk at the path you reference, and that file's content must be text-based. The renderer reads the linked file's bytes and feeds them into the model alongside the spec; a directory, a remote URL, or a binary blob breaks that contract and is one of the most disruptive mistakes you can make when authoring a .plain file — the spec looks valid but the renderer either silently ignores the link, fails to read it, or wastes the model's context window on bytes it cannot interpret.
Three things a linked resource must not be:
A folder / directory.[integrations](src/integrations/), [schemas](resources/schemas/), [host project](../host_project/) are all invalid — the renderer cannot ingest a directory. If a whole directory's worth of content is relevant, pick the single most representative file inside it (a README.md, an exemplar source file, a manifest at the directory root) and link that.
A URL / external location.[Stripe docs](https://stripe.com/docs/api), [OpenAPI spec](https://example.com/openapi.json), any http:// / https:// / ftp:// / git:// / s3:// / gs:// target. Linked resources are local-file only. If a URL's content is essential to the spec, fetch it once, save the response to a text file under resources/ (e.g. resources/stripe-docs-snapshot.md, resources/example-openapi.yaml), and link that file.
A binary file. PNG, JPG, JPEG, GIF, BMP, TIFF, WebP, ICO, PDF, DOCX, XLSX, PPTX, ZIP, TAR, GZ, MP3, MP4, WAV, compiled binaries (.exe, .so, .dylib, .class, .wasm), and anything else that isn't human-readable text in its raw form. Binary content cannot be meaningfully consumed by the renderer; linking a screenshot, a PDF spec, or a packaged artifact accomplishes nothing except bloating the context. If the information in a binary asset is essential, transcribe it into a text-based form first — a UI screenshot becomes a Markdown description or a structured YAML wireframe under resources/; a PDF spec becomes a Markdown extract or the underlying JSON Schema / OpenAPI; an architecture diagram becomes a Mermaid block inside a Markdown file.
If the markdown-link target ends with /, contains ://, points at a path that resolves to a directory, or points at a file with a binary extension (see the list above), stop — it cannot be a linked resource. Convert it to a text file under resources/ first, then link the converted file.
Do not mention URLs or folder paths in .plain content at all
The constraint above is not just about markdown link syntax. URLs (any http://, https://, ftp://, git://, s3://, … string) and folder paths (src/integrations/, ../host_project/, anything ending with /, anything that resolves to a directory) must not appear anywhere in .plain content — not as link targets, not in concept body prose, not in functional-spec text, not in implementation-reqs. Mentioning a URL or a folder in prose is a critical and common mistake because:
The renderer cannot follow URLs or open folders. A URL or folder reference in prose is a ghost dependency: it looks meaningful to a human reader, but it contributes nothing to code generation. Worse, downstream readers (and future you) assume the renderer used the referenced content, so the spec drifts from reality.
The fix is always the same: if external content matters, fetch it (or pick one canonical file out of the directory), save it as a text file under resources/, and refer to it through a normal linked resource. The concept or spec then names the content through the linked file, not through a URL or folder path string.
The only exceptions are URLs and paths that are values the produced software itself uses at runtime (e.g. the base URL the integration calls, a database connection path, a CLI argument value). Those are configuration values, not external references, and they belong in the spec because the generated code needs them. A useful litmus test: "Would the renderer benefit from reading the bytes at this URL / folder?" If yes, save it to a text file and link the file. If no (it's a runtime value), it can stay as plain text in the spec.
What a linked resource CAN be
A single file inside the project, reachable by a path relative to where codeplain is run — parent-directory traversal (../) is allowed (resources/ is the conventional home).
A text-based file the renderer can read end-to-end: JSON, YAML, XML, HTML, Markdown, plain text, CSV, TSV, source code in any language (.py, .js, .ts, .go, .java, .rb, .rs, .kt, .swift, .c, .cpp, .cs, …), shell scripts, SQL, JSON Schema, OpenAPI, AsyncAPI, Protobuf .proto, GraphQL SDL, .jolt, .env.example, .toml, .ini, .proto, Dockerfile, etc.
Common Resource Types
Type
Typical location
Use case
JSON Schema
resources/*.json
Defining data structure contracts
OpenAPI / Swagger spec
resources/*.yaml
API endpoint definitions
Data transforms
resources/*.jolt
Data transformation rules
Test fixtures
resources/*.json, resources/*.csv
Sample data for tests
Configuration examples
resources/*.yaml
Reference configurations
When to Use Resources
The information is too detailed or structured to express inline in the spec (e.g., a full JSON schema).
The same data is referenced by multiple specs or sections.
The resource is an industry-standard format (OpenAPI, JSON Schema) that the renderer can interpret directly.
When NOT to Use Resources
The information is short enough to include inline in the spec text.
The file is generated code (those belong in plain_modules/, not resources/).
Validation Checklist
Resource file exists at the specified path
Target is a file on disk, not a directory (the path does not end in / and does not resolve to a folder)
Target is a local path, not a URL (no :// anywhere in the target: no http://, https://, ftp://, git://, s3://, gs://, etc.)
No URLs or folder paths anywhere in the surrounding .plain content (not as link targets, not in body prose), with the sole exception of URLs / paths that are runtime values the generated software itself uses
Path is relative to the .plain file, not absolute
Path resolves to a real text file on disk from where codeplain is run (../ traversal is allowed)
Markdown link syntax is correct: [display text](relative/path)
Resource content is relevant and adds value beyond what the spec text says
1---2name: add-resource3description: Add a linked resource (external file reference) to a ***plain spec. Use when the user wants to reference a JSON schema, API spec, data file, or other external file from within a functional spec, definition, or implementation requirement.4---56# Add Resource78Always use the skill `load-plain-reference` to retrieve the ***plain syntax rules — but only if you haven't done so yet.910Linked resources are external files referenced from within a `.plain` spec using markdown link syntax. The file contents are passed to the renderer alongside the spec, providing additional context for code generation.1112## Workflow13141. **Identify or create the resource file.** Keep it inside the project — the `resources/` directory is the conventional home; it does not have to sit next to the `.plain` file.152. **Add the markdown link** at the appropriate place in the spec.163. **Verify the file path** is relative to the `.plain` file location.174. **Read the file back** to confirm correct link syntax and path.1819## Format2021Use standard markdown link syntax inside any spec section:2223```plain24***definitions***25- :AuthData: is the authentication data structure.26 - Its format is defined in the [auth schema](resources/auth_schema.json).2728***implementation reqs***29- When transforming :BackupData:, use the JOLT transform.30 - The transform is defined in [backup_transform.jolt](resources/backup_transform.jolt).3132***functional specs***3334- An API conforming to the [API specification](resources/api_spec.yaml) is exposed.35```3637## Path Rules3839- Paths are resolved **relative to the directory where `codeplain` is run** (the current working directory).40- Relative paths may traverse into parent directories — `[resource](../../resources/resource.md)` is valid — as long as they resolve to a real text file on disk.41- **No external URLs** — only local file references.42- **No folder paths** — the target must be a file, not a directory.43- Only text-based files are supported.4445### A linked resource MUST be a single, text-based file that exists on disk4647A linked resource is **always** a single file that exists on disk at the path you reference, **and** that file's content must be text-based. The renderer reads the linked file's bytes and feeds them into the model alongside the spec; a directory, a remote URL, or a binary blob breaks that contract and is one of the most disruptive mistakes you can make when authoring a `.plain` file — the spec looks valid but the renderer either silently ignores the link, fails to read it, or wastes the model's context window on bytes it cannot interpret.4849Three things a linked resource **must not** be:50511. **A folder / directory.** `[integrations](src/integrations/)`, `[schemas](resources/schemas/)`, `[host project](../host_project/)` are all invalid — the renderer cannot ingest a directory. If a whole directory's worth of content is relevant, pick the single most representative **file** inside it (a `README.md`, an exemplar source file, a manifest at the directory root) and link **that**.522. **A URL / external location.** `[Stripe docs](https://stripe.com/docs/api)`, `[OpenAPI spec](https://example.com/openapi.json)`, any `http://` / `https://` / `ftp://` / `git://` / `s3://` / `gs://` target. Linked resources are local-file only. If a URL's content is essential to the spec, fetch it once, save the response to a text file under `resources/` (e.g. `resources/stripe-docs-snapshot.md`, `resources/example-openapi.yaml`), and link **that file**.533. **A binary file.** PNG, JPG, JPEG, GIF, BMP, TIFF, WebP, ICO, PDF, DOCX, XLSX, PPTX, ZIP, TAR, GZ, MP3, MP4, WAV, compiled binaries (`.exe`, `.so`, `.dylib`, `.class`, `.wasm`), and anything else that isn't human-readable text in its raw form. Binary content cannot be meaningfully consumed by the renderer; linking a screenshot, a PDF spec, or a packaged artifact accomplishes nothing except bloating the context. If the information in a binary asset is essential, transcribe it into a text-based form first — a UI screenshot becomes a Markdown description or a structured YAML wireframe under `resources/`; a PDF spec becomes a Markdown extract or the underlying JSON Schema / OpenAPI; an architecture diagram becomes a Mermaid block inside a Markdown file.5455If the markdown-link target ends with `/`, contains `://`, points at a path that resolves to a directory, or points at a file with a binary extension (see the list above), **stop** — it cannot be a linked resource. Convert it to a text file under `resources/` first, then link the converted file.5657### Do not mention URLs or folder paths in `.plain` content at all5859The constraint above is **not** just about markdown link syntax. URLs (any `http://`, `https://`, `ftp://`, `git://`, `s3://`, … string) and folder paths (`src/integrations/`, `../host_project/`, anything ending with `/`, anything that resolves to a directory) **must not appear anywhere in `.plain` content** — not as link targets, not in concept body prose, not in functional-spec text, not in implementation-reqs. Mentioning a URL or a folder in prose is a critical and common mistake because:6061- The renderer cannot follow URLs or open folders. A URL or folder reference in prose is a *ghost* dependency: it looks meaningful to a human reader, but it contributes nothing to code generation. Worse, downstream readers (and future you) assume the renderer used the referenced content, so the spec drifts from reality.62- The fix is always the same: if external content matters, fetch it (or pick one canonical file out of the directory), save it as a text file under `resources/`, and refer to it through a normal linked resource. The concept or spec then names the content through the linked file, not through a URL or folder path string.6364The **only** exceptions are URLs and paths that are *values the produced software itself uses at runtime* (e.g. the base URL the integration calls, a database connection path, a CLI argument value). Those are configuration values, not external references, and they belong in the spec because the generated code needs them. A useful litmus test: "Would the renderer benefit from reading the bytes at this URL / folder?" If yes, save it to a text file and link the file. If no (it's a runtime value), it can stay as plain text in the spec.6566### What a linked resource CAN be6768- A single file inside the project, reachable by a path relative to where `codeplain` is run — parent-directory traversal (`../`) is allowed (`resources/` is the conventional home).69- A **text-based** file the renderer can read end-to-end: JSON, YAML, XML, HTML, Markdown, plain text, CSV, TSV, source code in any language (`.py`, `.js`, `.ts`, `.go`, `.java`, `.rb`, `.rs`, `.kt`, `.swift`, `.c`, `.cpp`, `.cs`, …), shell scripts, SQL, JSON Schema, OpenAPI, AsyncAPI, Protobuf `.proto`, GraphQL SDL, `.jolt`, `.env.example`, `.toml`, `.ini`, `.proto`, `Dockerfile`, etc.7071## Common Resource Types7273| Type | Typical location | Use case |74|------|-----------------|----------|75| JSON Schema | `resources/*.json` | Defining data structure contracts |76| OpenAPI / Swagger spec | `resources/*.yaml` | API endpoint definitions |77| Data transforms | `resources/*.jolt` | Data transformation rules |78| Test fixtures | `resources/*.json`, `resources/*.csv` | Sample data for tests |79| Configuration examples | `resources/*.yaml` | Reference configurations |8081## When to Use Resources8283- The information is too detailed or structured to express inline in the spec (e.g., a full JSON schema).84- The same data is referenced by multiple specs or sections.85- The resource is an industry-standard format (OpenAPI, JSON Schema) that the renderer can interpret directly.8687## When NOT to Use Resources8889- The information is short enough to include inline in the spec text.90- The file is generated code (those belong in `plain_modules/`, not `resources/`).9192## Validation Checklist9394- [ ] Resource file exists at the specified path95- [ ] **Target is a file on disk, not a directory** (the path does not end in `/` and does not resolve to a folder)96- [ ] **Target is a local path, not a URL** (no `://` anywhere in the target: no `http://`, `https://`, `ftp://`, `git://`, `s3://`, `gs://`, etc.)97- [ ] **Target is a text-based file** (no binary extensions: `.png`, `.jpg`, `.jpeg`, `.gif`, `.bmp`, `.tiff`, `.webp`, `.ico`, `.pdf`, `.docx`, `.xlsx`, `.pptx`, `.zip`, `.tar`, `.gz`, `.mp3`, `.mp4`, `.wav`, `.exe`, `.so`, `.dylib`, `.class`, `.wasm`, …)98- [ ] **No URLs or folder paths anywhere in the surrounding `.plain` content** (not as link targets, not in body prose), with the sole exception of URLs / paths that are runtime values the generated software itself uses99- [ ] Path is relative to the `.plain` file, not absolute100- [ ] Path resolves to a real text file on disk from where `codeplain` is run (`../` traversal is allowed)101- [ ] Markdown link syntax is correct: `[display text](relative/path)`102- [ ] Resource content is relevant and adds value beyond what the spec text says
Run npx skillmds@latest add codeplain-ai/add-resource in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Add a linked resource (external file reference) to a ***plain spec. Use when the user wants to reference a JSON schema, API spec, data file, or other external file from within a functional spec, definition, or implementation requirement. It is listed under Integrations & APIs on SkillMD.
This skill has not completed SkillMD's automated safety review yet. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
codeplain-ai (@codeplain-ai) published this skill. Their other Agent Skills are listed on their SkillMD profile.