Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/agent-memory/archgate-developer/MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Skipping steps 2 or 3 is a workflow violation. The user should NEVER have to inv

## Patterns & Fixes

- **YAML double-quoted strings require escaped backslashes for Windows paths in tests** — YAML interprets `\` as an escape character inside double-quoted strings. Writing `cwd: "E:\project"` silently corrupts the parsed value because `\p` is not a valid escape sequence. Fix: use `JSON.stringify(path)` to produce properly escaped YAML values (e.g., `cwd: ${JSON.stringify(cwd)}`). JSON and YAML double-quoted strings share the same escape syntax. Encountered in Copilot CLI session-context tests (`workspace.yaml` with Windows paths).
- **`git commit` in temp repos requires local identity** — CI runners have no global `user.email`/`user.name` configured. Any test that runs `git commit` on a temp repo MUST call `git config user.email` and `git config user.name` locally after `git init`. Fails with a cryptic `ShellPromise` error in CI; passes locally. Also captured in ARCH-005 Do's.
- **Never use `bunx prettier` directly** — Always use `bun run format` (to fix) or `bun run format:check` (to verify). Using `bunx prettier` can fail or use a different version than the project's devDependency. The same applies to all dev tools: prefer `bun run <script>` over `bunx <tool>` when a package.json script exists.
- **`Bun.Glob.match()` triggers oxlint `prefer-regexp-test`** — `Bun.Glob.match()` returns a boolean (not a RegExp), but oxlint can't tell. Suppress with `// oxlint-disable-next-line prefer-regexp-test -- Bun.Glob.match() returns boolean, not RegExp`.
Expand Down
38 changes: 38 additions & 0 deletions docs/public/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3860,6 +3860,19 @@ archgate session-context claude-code [options]
| ------------------- | ---------------------------------------- |
| `--max-entries <n>` | Maximum entries to return (default: 200) |

### archgate session-context copilot

Read the Copilot CLI session transcript for the project. Sessions are matched by their workspace `cwd` field.

```bash
archgate session-context copilot [options]
```

| Option | Description |
| ------------------- | ---------------------------------------- |
| `--max-entries <n>` | Maximum entries to return (default: 200) |
| `--session-id <id>` | Specific session UUID to read |

### archgate session-context cursor

Read the Cursor agent session transcript for the project.
Expand All @@ -3873,6 +3886,19 @@ archgate session-context cursor [options]
| `--max-entries <n>` | Maximum entries to return (default: 200) |
| `--session-id <id>` | Specific session UUID to read |

### archgate session-context opencode

Read the opencode session transcript for the project. Sessions are matched by the project `path` field in session metadata.

```bash
archgate session-context opencode [options]
```

| Option | Description |
| ------------------- | ---------------------------------------- |
| `--max-entries <n>` | Maximum entries to return (default: 200) |
| `--session-id <id>` | Specific session ID to read |

## Examples

Read the latest Claude Code session:
Expand All @@ -3887,6 +3913,18 @@ Read a specific Cursor session:
archgate session-context cursor --session-id abc123
```

Read the latest Copilot CLI session:

```bash
archgate session-context copilot
```

Read the latest opencode session:

```bash
archgate session-context opencode
```

---

## Reference: archgate telemetry
Expand Down
38 changes: 38 additions & 0 deletions docs/src/content/docs/pt-br/reference/cli/session-context.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@ archgate session-context claude-code [options]
| ------------------- | ------------------------------------------- |
| `--max-entries <n>` | Máximo de entradas a retornar (padrão: 200) |

### archgate session-context copilot

Lê a transcrição de sessão do Copilot CLI para o projeto. Sessões são correspondidas pelo campo `cwd` do workspace.

```bash
archgate session-context copilot [options]
```

| Opção | Descrição |
| ------------------- | ------------------------------------------- |
| `--max-entries <n>` | Máximo de entradas a retornar (padrão: 200) |
| `--session-id <id>` | UUID específico da sessão a ser lida |

### archgate session-context cursor

Lê a transcrição de sessão do agente Cursor para o projeto.
Expand All @@ -36,6 +49,19 @@ archgate session-context cursor [options]
| `--max-entries <n>` | Máximo de entradas a retornar (padrão: 200) |
| `--session-id <id>` | UUID específico da sessão a ser lida |

### archgate session-context opencode

Lê a transcrição de sessão do opencode para o projeto. Sessões são correspondidas pelo campo `path` do projeto nos metadados da sessão.

```bash
archgate session-context opencode [options]
```

| Opção | Descrição |
| ------------------- | ------------------------------------------- |
| `--max-entries <n>` | Máximo de entradas a retornar (padrão: 200) |
| `--session-id <id>` | ID específico da sessão a ser lida |

## Exemplos

Ler a última sessão do Claude Code:
Expand All @@ -49,3 +75,15 @@ Ler uma sessão específica do Cursor:
```bash
archgate session-context cursor --session-id abc123
```

Ler a última sessão do Copilot CLI:

```bash
archgate session-context copilot
```

Ler a última sessão do opencode:

```bash
archgate session-context opencode
```
38 changes: 38 additions & 0 deletions docs/src/content/docs/reference/cli/session-context.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@ archgate session-context claude-code [options]
| ------------------- | ---------------------------------------- |
| `--max-entries <n>` | Maximum entries to return (default: 200) |

### archgate session-context copilot

Read the Copilot CLI session transcript for the project. Sessions are matched by their workspace `cwd` field.

```bash
archgate session-context copilot [options]
```

| Option | Description |
| ------------------- | ---------------------------------------- |
| `--max-entries <n>` | Maximum entries to return (default: 200) |
| `--session-id <id>` | Specific session UUID to read |

### archgate session-context cursor

Read the Cursor agent session transcript for the project.
Expand All @@ -36,6 +49,19 @@ archgate session-context cursor [options]
| `--max-entries <n>` | Maximum entries to return (default: 200) |
| `--session-id <id>` | Specific session UUID to read |

### archgate session-context opencode

Read the opencode session transcript for the project. Sessions are matched by the project `path` field in session metadata.

```bash
archgate session-context opencode [options]
```

| Option | Description |
| ------------------- | ---------------------------------------- |
| `--max-entries <n>` | Maximum entries to return (default: 200) |
| `--session-id <id>` | Specific session ID to read |

## Examples

Read the latest Claude Code session:
Expand All @@ -49,3 +75,15 @@ Read a specific Cursor session:
```bash
archgate session-context cursor --session-id abc123
```

Read the latest Copilot CLI session:

```bash
archgate session-context copilot
```

Read the latest opencode session:

```bash
archgate session-context opencode
```
41 changes: 41 additions & 0 deletions src/commands/session-context/copilot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { Command } from "@commander-js/extra-typings";
import { Option } from "@commander-js/extra-typings";

import { exitWith } from "../../helpers/exit";
import { logError } from "../../helpers/log";
import { formatJSON } from "../../helpers/output";
import { findProjectRoot } from "../../helpers/paths";
import { readCopilotSession } from "../../helpers/session-context-copilot";

const maxEntriesOption = new Option(
"--max-entries <n>",
"maximum entries to return (default: 200)"
).argParser((val) => parseInt(val, 10));

export function registerCopilotSessionContextCommand(parent: Command) {
parent
.command("copilot")
.description("Read Copilot CLI session transcript for the project")
.addOption(maxEntriesOption)
.option("--session-id <id>", "Specific session UUID to read")
.action(async (opts) => {
try {
const projectRoot = findProjectRoot();
const result = await readCopilotSession(projectRoot, {
maxEntries: opts.maxEntries,
sessionId: opts.sessionId,
});

if (!result.ok) {
logError(result.error);
await exitWith(1);
return;
}

console.log(formatJSON(result.data));
} catch (err) {
logError(err instanceof Error ? err.message : String(err));
await exitWith(1);
}
});
}
4 changes: 4 additions & 0 deletions src/commands/session-context/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import type { Command } from "@commander-js/extra-typings";

import { registerClaudeCodeSessionContextCommand } from "./claude-code";
import { registerCopilotSessionContextCommand } from "./copilot";
import { registerCursorSessionContextCommand } from "./cursor";
import { registerOpencodeSessionContextCommand } from "./opencode";

export function registerSessionContextCommand(program: Command) {
const sessionContext = program
.command("session-context")
.description("Read AI editor session transcripts");

registerClaudeCodeSessionContextCommand(sessionContext);
registerCopilotSessionContextCommand(sessionContext);
registerCursorSessionContextCommand(sessionContext);
registerOpencodeSessionContextCommand(sessionContext);
}
41 changes: 41 additions & 0 deletions src/commands/session-context/opencode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { Command } from "@commander-js/extra-typings";
import { Option } from "@commander-js/extra-typings";

import { exitWith } from "../../helpers/exit";
import { logError } from "../../helpers/log";
import { formatJSON } from "../../helpers/output";
import { findProjectRoot } from "../../helpers/paths";
import { readOpencodeSession } from "../../helpers/session-context-opencode";

const maxEntriesOption = new Option(
"--max-entries <n>",
"maximum entries to return (default: 200)"
).argParser((val) => parseInt(val, 10));

export function registerOpencodeSessionContextCommand(parent: Command) {
parent
.command("opencode")
.description("Read opencode session transcript for the project")
.addOption(maxEntriesOption)
.option("--session-id <id>", "Specific session ID to read")
.action(async (opts) => {
try {
const projectRoot = findProjectRoot();
const result = await readOpencodeSession(projectRoot, {
maxEntries: opts.maxEntries,
sessionId: opts.sessionId,
});

if (!result.ok) {
logError(result.error);
await exitWith(1);
return;
}

console.log(formatJSON(result.data));
} catch (err) {
logError(err instanceof Error ? err.message : String(err));
await exitWith(1);
}
});
}
31 changes: 31 additions & 0 deletions src/helpers/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,37 @@ export function opencodeAgentsDir(): string {
return join(base, "opencode", "agents");
}

/**
* Resolve the Copilot CLI session-state directory.
*
* Copilot CLI stores session data (workspace.yaml + events.jsonl) under
* `~/.copilot/session-state/<session-uuid>/`. Each session directory
* contains a `workspace.yaml` with a `cwd` field for project matching.
*
* Resolved at call time (not cached) so tests can override HOME.
*/
export function copilotSessionStateDir(): string {
return join(archgateHomeDir(), ".copilot", "session-state");
}

/**
* Resolve the opencode data storage directory.
*
* Opencode stores sessions, messages, and parts under
* `$XDG_DATA_HOME/opencode/storage/` (defaulting to
* `~/.local/share/opencode/storage/`). This is distinct from the
* config directory (`$XDG_CONFIG_HOME/opencode/`) used by
* `opencodeAgentsDir()`.
*
* Resolved at call time (not cached) so tests can override HOME /
* XDG_DATA_HOME.
*/
export function opencodeStorageDir(): string {
const xdg = usableEnv(Bun.env.XDG_DATA_HOME);
const base = xdg ?? join(archgateHomeDir(), ".local", "share");
return join(base, "opencode", "storage");
}

export const paths = { cacheFolder: internalPath("cache") } as const;

export function projectPath(projectRoot: string, ...path: string[]) {
Expand Down
Loading
Loading