Copilot CLI
- ID:
copilot - Store:
${COPILOT_HOME:-~/.copilot}/session-state/<sessionId>/events.jsonl;
COPILOT_HOME also moves the MCP config, the skill and the hooks below
- Read override:
DEJA_COPILOT_ROOT(points at thesession-statedirectory) - Format: append-only JSONL, one event per line, each
{type, data, timestamp}
session.start carries sessionId and context.cwd, which is where the
project name comes from; the directory the file sits in is not the id and can
differ from it. Conversation turns are user.message and assistant.message,
both with data.content as a plain string.
The work is filed outside the message stream. tool.execution_start carries
toolName and arguments — path for the file tools, command for bash,
and old_str/new_str for an edit, which is the one place the replaced text
survives. create hands over the whole file as file_text, and that is the
only record a created file's lines were ever in a session — a commit that adds
them deletes nothing for the replaced side to match. view is the file read.
With a GPT model there is no edit or create: every edit is apply_patch,
whose arguments is the patch string itself, read into files, the removed
lines and the added ones as codex's patches are. tool.execution_complete carries data.result.content,
indexed as tool output whether or not the call failed, because the error a
command hit is what a later search reaches for. Its success flag is true on
failed runs too, so a non-zero exit code is read from the telemetry or the
trailer in the output and added to the command record. session.shutdown
lists codeChanges.filesModified; deja does not read it, since the tool events
already name every file.
- MCP:
deja install copilotwritesmcpServers.dejainto
${COPILOT_HOME:-~/.copilot}/mcp-config.json.
- Skill:
~/.copilot/skills/deja-history/SKILL.md(under$COPILOT_HOME
when set), loaded on demand;
Copilot invokes a skill by name, so it is also the /deja-history command.
- Auto-recall:
deja install copilot-autowrites
~/.copilot/hooks/deja.json, which Copilot loads as user-level hooks and VS
Code Copilot Chat reads too. Older installs put the entries in
settings.json or config.json; the install takes them out. Measured on
1.0.92 against a stub model, every one of these reaches the model:
sessionStart(deja hook-context --copilot): the digest, as a message
of its own in front of the first request, kept for the session.
userPromptSubmitted(deja hook-prompt --copilot): per-prompt recall,
appended to the user's turn inside <system_reminder>.
preToolUse(deja hook-tool --copilot, matcherbash|powershell|edit|create):
the file's prior decision before an edit, sent as a message after the
tool's result. Copilot honours the matcher, so deja does not run for reads.
postToolUseandpostToolUseFailure(deja hook-tool-after --copilot,
matcher bash|powershell): the fix line after a failed command. A non-zero
exit is still a successful tool call, so postToolUse carries most of
them; a tool that errors fires postToolUseFailure with the text in error.
PreCompact(deja hook-precompact): spelled the way VS Code reads it;
Copilot runs a PascalCase key too, with snake_case fields. The payload
names events.jsonl as transcript_path; deja captures the session from
it and hands the packet back on the next tool call or prompt.
preMcpToolCall(deja hook-mcp-call) andsessionEnd
(deja hook-session-end): the MCP server is told nothing about who is
calling, so the first marks the session live before each MCP request and
recall leaves it out, and the second clears the mark. A preMcpToolCall
hook's output becomes the request's _meta, so it prints nothing.
Every answer is the flat {"additionalContext": …}; a nested
hookSpecificOutput runs and reaches no one. COPILOT_HOME moves all of
these files.
- Resume:
copilot --resume=<sessionId>. - Handoff: exec.
Known quirks and drift
assistant.messagerecords whose content is empty and whose work is entirely
in tool calls used to be dropped; the tool events now carry them.
- Tool names are lowercase (
edit,view,create,bash) where Claude Code
capitalises, and the edit argument is old_str rather than old_string.
- A session directory can outlive its
events.jsonl; the discovery walk only
picks up files that exist.
- Since 1.0.79 user settings live in
settings.jsonandconfig.jsonis
managed by the CLI. On each start it moves user keys still in config.json
across, and a hooks key there replaces the one in settings.json whole, so
while the reader's hooks are still in config.json deja writes its entry
beside them.
- A hook answer in Claude Code's
hookSpecificOutputenvelope is run and
logged as a success, and its context reaches nobody: Copilot reads only a
top-level additionalContext.
Specified in #655, work
records added in #1231,
auto-recall in #4231.
Last verified: 2026-10-07
deja reads this format and thirty-seven others, and turns what it finds into memory your agents can search. See the harness matrix for what is wired where, or install it and search your own history.
Found this useful? Star deja-vu on GitHub.