Managing Context: External Content
Lectic aims to make it easy to pull external information into the conversation, providing the LLM with the context it needs to answer questions, analyze data, or perform tasks.
This is done in two primary ways: by referencing files and URIs using standard Markdown links, and by executing shell commands with the :cmd directive.
Content References via Markdown Links
You can include local or remote content using the standard Markdown link syntax, [Title](URI). Lectic will fetch the content from the URI and include it in the context for the LLM.
Please summarize this local document: [Notes](./notes.md)
Analyze the data in this S3 bucket: [Dataset](s3://my_bucket/dataset.csv)
What does this README say?
[Repo](github+repo://gleachkr/Lectic/contents/README.md)Supported Content Types
- Text: Plain text files are included directly.
- Images: PNG, JPEG, GIF, and WebP images are supported.
- PDFs: Content from PDF files can be extracted (requires a provider that supports PDF ingestion, such as Anthropic, Gemini, or OpenAI).
- Audio: Gemini and OpenAI support audio inputs. For OpenAI, use
provider: openai/chatwith an audio‑capable model; supported formats include MP3, MPEG, and WAV. Gemini supports a broader set of audio types. - Video: Gemini supports video understanding. See supported formats in Google’s docs: https://ai.google.dev/gemini-api/docs/video-understanding#supported-formats
URI Schemes
Lectic supports several URI schemes for referencing content:
- Local Files: Simple relative paths like
./src/main.rsor absolutefile:///path/to/file.txtURIs. - Remote Content:
http://andhttps://for web pages and other online resources. - Amazon S3:
s3://for referencing objects in S3 buckets. This requires AWS credentials to be configured in your environment. - MCP Resources: You can reference resources provided by an MCP server using a custom scheme, like
github+repo://..., wheregithubis the name of the MCP server (provided in the tool specification), and the rest is the resource URL.
A few convenience rules apply:
- For local file references using
file://, use absolute paths. A portable way to build these is with$PWD(e.g.,file://$PWD/papers/some.pdf). - Environment variables in URIs use the
$VARform;${VAR}is not supported. Expansion happens before any globbing. - Environment variable expansion also applies to bare local paths (non‑URL links), such as
./$DATA_ROOT/file.txt. Expansion happens before any globbing.
You can use glob patterns to include multiple files at once. This is useful for providing the entire source code of a project as context.
[All source code](./src/**/*.ts)
[All images in this directory](./images/*.jpg)Lectic uses Bun’s Glob API for matching.
PDF Page Selection
When referencing a PDF, you can point to a specific page or a range of pages by adding a fragment to the URI. Page numbering starts at 1.
- Single Page:
[See page 5](file.pdf#page=5) - Page Range:
[See Chapter 2](book.pdf#pages=20-35)
If both page and pages are supplied, pages takes precedence. If a page or range is malformed or out of bounds, Lectic will surface an error that is visible to the LLM.
Command Output via :cmd
Use :cmd[...] to execute a shell command and insert its output directly into your message. Think of it as a built-in macro that runs a command and pastes in the result.
What can you tell me about my system? :cmd[uname -a]When Lectic processes this, it runs uname -a and replaces the :cmd[...] directive with the command’s output wrapped in XML:
<stdout from="uname -a">Linux myhost 6.1.0 ...</stdout>If the command fails (non-zero exit code), you get an error wrapper instead:
<error>Something went wrong when executing a command:<stdout from="bad-cmd">
</stdout><stderr from="bad-cmd">bad-cmd: command not found</stderr></error>When :cmd runs
:cmd directives are expanded at the beginning of each user turn. You can also expand them with an LSP code action. If you want a :cmd directive to expand only once, you can wrap it in :attach[..] (see below) which will store the results in the lectic document as an attachment, or you can implement some other caching mechanism using the macro system.
Execution environment
:cmdruns with Bun’s$shell in the current working directory.- Standard Lectic environment variables like
LECTIC_FILEare available. - Line breaks inside
:cmd[...]are ignored, so wrapped commands work:
:cmd[find . -name "*.ts"
| head -20]Use cases
- System information:
What can you tell me about my system? :cmd[uname -a] - Project state:
Write a commit message: :cmd[git diff --staged] - Data snippets:
Analyze this: :cmd[head -50 data.csv]
Inline Attachments with :attach
While :cmd inserts command output directly into your message text, sometimes you want to provide context that appears as a separate attachment — for example, to keep the conversation transcript cleaner or to control caching behavior.
The :attach[...] directive creates an inline attachment. The content inside the brackets is stored in the assistant’s response block (after macro expansion) and sent to the LLM as additional user context.
You can optionally set metadata with directive attributes:
icon: custom fold icon in LSP/editor UIsname: custom fold label in LSP/editor UIs
Here's the current state of the config:
:attach[:config_status_macro[]]
What do you think of this configuration?With custom fold display metadata:
:attach[:cmd[git diff --staged]]{name="staged diff" icon=""}When Lectic processes this, it creates an inline attachment that appears at the top of the assistant’s response:
<inline-attachment kind="attach">
<command></command>
<content type="text/plain">
┆server:
┆ port: 8080
┆ host: localhost
</content>
</inline-attachment>Combining :attach with :cmd
You can compose :attach and :cmd to get the best of both worlds — run a command and store its output as an attachment:
Review this diff: :attach[:cmd[git diff --staged]]This executes git diff --staged, then wraps the result as an inline attachment. The attachment is cached in the transcript, so re-running Lectic won’t re-execute the command.
:cmd vs :attach[:cmd[...]]
Use :cmd[...] when you want command output inlined directly in your message. The output becomes part of the message text.
Use :attach[:cmd[...]] when you want the output stored as a cached attachment. This is useful for large outputs or when you want to preserve provider cache efficiency (for example, if the output of :cmd might change in between user turns).
How inline attachments work
For details on how inline attachments are stored in the .lec file and how they interact with the provider, see Inline Attachments in the Conversation Format guide.