PluginsEarly
Types
The types the elements, events and methods use, as plugin.d.ts declares them.
From the plugin interface of gr 0.2.16 (API 0.1, 0.2, 0.3). gr plugin api types prints it on your machine.
Json
type Json = null | boolean | number | string | Json[] | { [k: string]: Json }
Tone
A role of the person's theme; a plugin never names a colour
type Tone = "default" | "bright" | "muted" | "faint" | "accent" | "success" | "warning" | "error"
IconName
type IconName = "close" | "check" | "plus" | "minus" | "more" | "up" | "down" | "overview" | "search" | "gear" | "send" | "architecture" | "graph" | "agents"
Pos
A place in a document: line counted from 0, and column from 0 in UTF-16 code units, as a JavaScript string counts. Every line and column the interface carries counts so
interface Pos {
line: number;
column: number;
}
Context
Sent by the editor with every event that has one; file and selection text only with fs:read:workspace and for files inside the root; file.version (0.2) is the open document's version, what an edit names; file.line and file.column are the cursor's, counted as a Pos is; file.top and file.bottom are the first line on screen and the last, both shown, from 0; node is the node a node's page shows, the one the architecture view is on, or the map's selected node, and absent in a code view
interface Context {
seq: number;
at: number;
root: string;
surface: "map" | "architecture" | "agents" | "agent" | "code" | "node" | "terminal" | "change" | "plugin" | "settings" | "empty";
mode: "normal" | "insert" | "visual" | "visual_line" | "visual_block" | "prompt" | "command";
pane: string;
file?: { path: string;
line: number;
column: number;
text: string;
top: number;
bottom: number;
dirty: boolean;
version?: number;
selection?: { from: Pos;
to: Pos;
text: string;
truncated?: true } };
node?: string;
selection: string[];
agent?: string;
view?: { view: string;
item?: string };
theme: { name: string;
dark: boolean };
}
Filter
Narrows a handler to one of the plugin's commands, views, lists, pickers, (0.2) tools or (0.2) mention sources, or to paths matching a glob
interface Filter {
command?: string;
view?: string;
list?: string;
picker?: string;
path?: string;
tool?: string;
source?: string;
}
Attachment
A file inside the root, and with lines the first line of it and the last, both included, counted from 0; text (0.2) needs agents:write, since it is written into the next message the person sends, and is at most 64 KiB
type Attachment = { node: string } | { file: string; lines?: [number, number] } | { agent: string } | { text: string }
Segment
interface Segment {
text: string;
icon?: IconName;
tone?: Tone;
command?: string;
}
Badge
interface Badge {
text: string;
tone?: Tone;
}
SelectItem
interface SelectItem {
label: string;
detail?: string;
key?: string;
}
Entry
Open is where Enter or a click on the entry goes, with line counted from 0
interface Entry {
key: string;
label: string;
detail?: string;
aside?: string;
icon?: IconName;
tone?: Tone;
open?: { path: string;
line?: number } | { node: string } | { agent: string };
}
GraphNode
Rank is how much the node matters in an overview of the whole graph, from 0 to 1 among all of its nodes, and is absent (never 0) until the workspace has been ranked; tier is how finished the node is: stub (structure nobody has described yet), labeled (a real name, no description) or described. tags (since 0.2) are the node's authored and derived tags; line is the node's first line in its file, counted from 0
interface GraphNode {
id: string;
name: string;
kind: string;
path?: string;
line?: number;
description?: string;
parent?: string;
rank?: number;
tier?: string;
tags?: string[];
}
Neighbor
interface Neighbor {
node: GraphNode;
edge: string;
direction: "in" | "out";
}
Agent
State is one of starting, running, working, waiting (on the person; attention says for what), couldnt_start, open_elsewhere, archived, asleep and stopped; activity is what the agent is doing right now in words ("Editing src/server.go"), when its harness says; absent between turns. startedBy (0.2) is "plugin:<name>" for an agent a plugin started
interface Agent {
id: string;
name: string;
state: string;
harness: string;
root: string;
worktree?: string;
attention?: string;
started?: number;
activity?: string;
startedBy?: string;
}
DirEntry
interface DirEntry {
name: string;
dir: boolean;
size: number;
}
Stat
interface Stat {
size: number;
dir: boolean;
modified: number;
}
ExecResult
interface ExecResult {
code: number;
stdout: string;
stderr: string;
truncated: boolean;
ms: number;
}
FetchResult
interface FetchResult {
status: number;
headers: Record<string, string>;
body: string;
truncated: boolean;
}
TranscriptBlock
One piece of an agent's conversation, oldest first: what the person or a plugin wrote to it (role user), what it answered (assistant), or what its CLI said (notice). kind text is words; tool is a tool it called, tool its name and text its arguments in one line, never what came back; shell is a command the person ran in it, text the command only; image is a picture, text empty. at is when its turn began, in ms since 1970. Each text is cut at 4 KiB (cut: true)
interface TranscriptBlock {
role: "user" | "assistant" | "notice";
kind: "text" | "tool" | "shell" | "notice" | "image";
text: string;
tool?: string;
at: number;
cut?: true;
}
Since API 0.2.
SecretSetting
What $.settings.get and $.settings.all answer for a secret setting: whether the person entered it, never its value. Declared in plugin.toml as [settings.<key>] kind = "secret", with no default: host (one host [allow] net names, never a wildcard or any) and header (Authorization, X-Api-Key) put it in that header of each $.net.fetch addressed to that host, and format ("Bearer {}"; the value alone when not given) says where it goes in the header; an [[mcp]] server's env (env = { GITHUB_TOKEN = "<key>" }) gives it to that server in its environment. The person enters it with gr plugin secret set <plugin> <key> on a terminal; the daemon keeps it in the OS keychain (never config.toml), sends it only there, drops it on a redirect to another host, and takes it out of an answer that echoes it. The settings event says when it is set or cleared. A fetch to its host that sets its header itself is refused (net.secret_header). Tests have no secrets: t.fixtures({ settings: { <key>: { set: true } } }) says one is set
interface SecretSetting {
set: boolean;
}
Since API 0.2.
Worktree
A worktree of the root's repository: upstream is the branch it is measured against and lands into, ahead and behind count commits against it; current is the root's own
interface Worktree {
path: string;
branch?: string;
head: string;
upstream?: string;
ahead?: number;
behind?: number;
current: boolean;
locked?: boolean;
}
Since API 0.2.
GitChange
A path of the root's working tree that differs from HEAD, as git status says; from is a renamed path's old one
interface GitChange {
path: string;
status: "added" | "modified" | "deleted" | "renamed" | "untracked";
from?: string;
}
Since API 0.2.
TextEdit
Text from one place of a document to another replaced: positions in lines from 0 and columns from 0 in UTF-16 code units, as a JavaScript string counts
interface TextEdit {
from: Pos;
to: Pos;
text: string;
}
Since API 0.2.
DocInfo
A document open in an editor of the root: its version rises with every change; tooLarge is one listed without text (over 8 MiB, or past the 64 MiB a root mirrors)
interface DocInfo {
path: string;
version: number;
language: string;
dirty: boolean;
eol: "lf" | "crlf";
tooLarge?: true;
}
Since API 0.2.
Doc
A document and its whole text, lines ending in \n whatever eol says
type Doc = DocInfo & { text: string }
Since API 0.2.
MenuTarget
What a menu a right click opened is about, the one argument of a command run from a plugin's [[menus]] entry: {node} for a card, a box or a node's page; {agent} for an agent or its mark; {path, line, column, selection?} for code, with line from 0 and column in UTF-16 code units (contract C1) at the cursor, and selection the selected text only when the plugin holds fs:read:workspace (the daemon takes it out otherwise); {} at the other places. An entry is declared in plugin.toml as [[menus]] place (card, map, box, atlas, agent, mark, agents, composer, code, terminal, node, pane or tab), command (one of the plugin's own), title (at most 40 characters) and when (a context clause, contract C4: the entry shows only where it holds when the menu opens). Entries show after the editor's own rows, under the plugin's name, each with the keys bound to its command
type MenuTarget = { node: string } | { agent: string } | { path: string; line: number; column: number; selection?: string } | Record<string, never>
Since API 0.2.
MenuEntry
One entry of a row's own menu (the menu prop of item and node): title is what it says, command one of the plugin's own, and args what that command is run with, else [{view, key}], the view and the row's key. A right click on a row with a menu selects it and opens these; on one without, the pane's menu opens
interface MenuEntry {
command: string;
title: string;
args?: Json[];
}
Since API 0.2.
ToolAnswer
What a tool handler answers the agent that called it: words (text), or a value it reads as JSON (json). At most 64 KiB, the json as encoded (tool_answer_bytes); text holds no control character but newlines and tabs (a \r\n is taken as a newline), since the agent's harness shows it on a terminal. To refuse a call, throw: the agent reads the error's message
type ToolAnswer = { text: string } | { json: Json }
Since API 0.2.
MentionEntry
One entry of a mention source: key (unique in the answer) is what mention.pick names, label what the composer's @ list shows, detail a few words after it, attach what choosing it attaches to the message as a chip naming the plugin (an Attachment: a node of the graph, a file inside the root with lines, an agent of the roster, or text, which needs agents:write). The daemon leaves out an entry it would not attach, and says which and why in the plugin's log (mention.entry); the others show
interface MentionEntry {
key: string;
label: string;
detail?: string;
attach: Attachment;
}
Since API 0.2.
Decoration
A mark inside code that is not its text, in one of a plugin's [[decorations]] sets: a sign in the gutter (at most 2 characters, or an icon), an underline, a tinted range or tinted whole lines, words after a line's end (at most 120 characters), words inside a line (an inlay, at most 40), or a line above a line (a lens, at most 120, which runs one of the plugin's own commands with args [{path, line}] when pressed). Lines and columns count from 0, columns in UTF-16 code units; detail, at most 1 KiB, shows when the caret or the pointer rests on the mark. The editor cuts longer words and decides which marks show when room is short
type Decoration = { kind: "sign"; line: number; text?: string; icon?: IconName; tone?: Tone; detail?: string } | { kind: "underline"; from: Pos; to: Pos; style?: "straight" | "wavy" | "dotted"; tone?: Tone; detail?: string } | { kind: "tint"; from: Pos; to: Pos; tone: Tone; lines?: boolean; detail?: string } | { kind: "eol"; line: number; text: string; tone?: Tone; detail?: string } | { kind: "inlay"; at: Pos; text: string; tone?: Tone; side?: "before" | "after"; detail?: string } | { kind: "above"; line: number; text: string; tone?: Tone; command?: string; detail?: string }
Since API 0.2.
GraphCreate
A node to create in this workspace. kind defaults to module; parent is a node of this root. Tags follow the MCP writer's authored-tag rule.
interface GraphCreate {
parent?: string;
kind?: string;
name: string;
description?: string;
tags?: string[];
}
Since API 0.2.
GraphPatch
Only these fields change. Authored tags such as user: travel with the repository; bare tags such as todo stay derived and may be reapplied after graph.changed.
interface GraphPatch {
name?: string;
description?: string;
addTags?: string[];
removeTags?: string[];
}
Since API 0.2.
Diagnostic
One thing a language server says of a file of the root: path is within the root, slash-separated; from and to are where, as a Pos (lines from 0, columns from 0 in UTF-16 code units); severity is 1 error, 2 warning, 3 information, 4 hint, and absent when the server did not say; code and source are the server's own words for the rule and for who found it; tags are the protocol's (1 unnecessary, 2 deprecated); server is the name of the server that said it
interface Diagnostic {
path: string;
from: Pos;
to: Pos;
severity?: 1 | 2 | 3 | 4;
code?: string;
source?: string;
message: string;
tags?: number[];
server: string;
}
Since API 0.2.
DocSymbol
A symbol a language server finds in a file: kind is the protocol's SymbolKind (5 class, 6 method, 12 function, 13 variable, 23 struct and the rest); range is the whole symbol, selectionRange its name, both from and to as a Pos; children are the symbols inside it. A server that answers a flat list gives symbols with no children, range and selectionRange the same, and the name of what holds each as its detail
interface DocSymbol {
name: string;
detail?: string;
kind: number;
range: { from: Pos;
to: Pos };
selectionRange: { from: Pos;
to: Pos };
children?: DocSymbol[];
}
Since API 0.2.
HarnessSetup
What one coding agent (Claude Code or Codex) loads when it starts in the root by one launch path (gr, the way Graphide and gr claude / gr codex start it, or plain, the bare CLI), and which layer each piece came from. Names, paths, sizes and a few setting values only: never a credential file, an MCP server's env or headers, a hook's environment, or an account's fields. layers are in precedence order (0 wins); instructions in load order; startupTokens estimates what loads at session start (four bytes a token); unreadable lists files found and not read, truncated each walk that stopped at its bound
interface HarnessSetup {
harness: "claude-code" | "codex";
launch: "gr" | "plain";
root: string;
config_dir?: string;
layers: SetupLayer[];
instructions: SetupInstruction[];
skills: SetupItem[];
subagents: SetupItem[];
commands: SetupItem[];
hooks: SetupHook[];
mcp: SetupMCP[];
settings: SetupSetting[];
sources: SetupSources;
checks: SetupCheck[];
startup_bytes: number;
startup_tokens: number;
unreadable?: { path: string;
reason: string }[];
truncated?: string[];
}
Since API 0.2.
SetupLayer
A place pieces come from: managed, cli (what the launch passes), local, project, user, profile (Codex's), launch (the launch's own flags, each flag with the path it names; an inline text as its size, never the text; a Codex -c as its key, never its value), plugin-dir, mcp-config, plugin, memory, import
interface SetupLayer {
id: string;
name: string;
path?: string;
present: boolean;
precedence: number;
flags?: { name: string;
value?: string }[];
}
Since API 0.2.
SetupInstruction
An instruction file (CLAUDE.md, AGENTS.md, a rule, an @import, the memory index): always is loaded at session start (false for a path-scoped rule), missing an @import naming a file that is not there, mentions the skills it names, generated the agent-config fragment it is rendered from
interface SetupInstruction {
path: string;
name: string;
kind: string;
layer: string;
order: number;
bytes: number;
tokens: number;
always: boolean;
imported_by?: string;
missing?: boolean;
mentions?: string[];
generated?: string;
}
Since API 0.2.
SetupItem
A skill, subagent or command: shadowed when one of the same name in a winning layer hides it; scripts the files a skill ships beside its SKILL.md; last_used when a session in the root last called the skill (seconds since 1970, Claude Code only)
interface SetupItem {
name: string;
path: string;
layer: string;
bytes?: number;
shadowed?: boolean;
scripts?: string[];
mentions?: string[];
generated?: string;
last_used?: number;
}
Since API 0.2.
SetupHook
A hook: its event and matcher and what it runs, as the program and the script it names, never the command line's arguments or environment; found says whether that exists (absent when it cannot be told)
interface SetupHook {
event: string;
matcher?: string;
program?: string;
script?: string;
layer: string;
path: string;
found?: boolean;
generated?: string;
}
Since API 0.2.
SetupMCP
An MCP server: its name, transport and program or host, never its env, headers or arguments
interface SetupMCP {
name: string;
transport?: string;
program?: string;
host?: string;
layer: string;
path: string;
found?: boolean;
shadowed?: boolean;
}
Since API 0.2.
SetupSetting
A setting worth seeing (the permission mode, model, effort and a few others): the value that wins and the layer that set it, and every layer's value; unknown when the winner cannot be told
interface SetupSetting {
name: string;
value?: string;
layer?: string;
path?: string;
unknown?: boolean;
values?: { layer: string;
path: string;
value: string }[];
}
Since API 0.2.
SetupSources
The agent-config checkout and profile that generate the setup's files, when there is one: each fragment (a profile's source file) and the files it renders, each same, rendered (substituted, so not compared), differs (edited by hand), stale (the fragment changed after the last sync) or missing
interface SetupSources {
agent_config?: string;
profile?: string;
profile_from?: string;
fragments?: { kind: string;
name: string;
path: string;
flows_to?: { target: string;
path: string;
state: "same" | "rendered" | "differs" | "stale" | "missing" }[] }[];
targets?: { name: string;
path?: string;
present: boolean }[];
}
Since API 0.2.
SetupCheck
A problem a check found: drift (a generated file edited, stale or missing), parity (a skill, MCP server or hook event one harness has and the other lacks), broken (a named skill, an import or a hook's or server's program that is not there), unused (a skill nothing names or called in 30 days), size (what loads at start is over the budget), permission-mode (a layer's mode a higher layer replaced). related names the other side: the fragment to edit, the other harness, the layer that won
interface SetupCheck {
kind: "drift" | "parity" | "broken" | "unused" | "size" | "permission-mode";
severity: "warn" | "info";
subject: string;
path?: string;
layer?: string;
detail: string;
related?: string[];
}
Since API 0.2.
SetupLayerState
The Agent setup layer of the root's graph: on while some holder keeps it, with how many hold it and its node and edge counts
interface SetupLayerState {
root: string;
on: boolean;
holders: number;
nodes: number;
edges: number;
}
Since API 0.2.
These docs describe Graphide 0.2.16, the latest release. Something wrong or missing? Tell us onDiscord or at hello@graphide.com.