Skip to content
97 linesCodeBlameRaw
1import { FileText, ScrollText, ShieldCheck } from "lucide-react";
2import { Link } from "react-router";
3
4import type { RepoInstructions } from "@g1t/contracts";
5
6import { Idle } from "./agents";
7import { TimeAgo } from "./ui";
8import { Card } from "./ui/card";
9import { Hint } from "./ui/hint";
10
11const ROLE: Record<RepoInstructions["files"][number]["role"], string> = {
12 root: "Every run",
13 directory: "Runs that touch this directory",
14 review: "Reviews",
15};
16
17/**
18 * The files every run of g1t in a project reads as the repository's
19 * instructions, as they are on its default branch: which, what they say,
20 * when they last changed, and where to change them.
21 */
22export function AgentInstructions({ instructions, base }: { instructions: RepoInstructions; base: string }) {
23 const { branch, files, limits } = instructions;
24 return (
25 <section id="instructions" className="mt-10 scroll-mt-20">
26 <div className="flex items-baseline justify-between">
27 <h3 className="flex items-center gap-2 text-sm font-medium">
28 <ScrollText size={15} className="text-muted" />
29 Instructions
30 </h3>
31 <span className="text-xs text-muted">
32 {files.length === 0 ? "None yet" : `${files.length} ${files.length === 1 ? "file" : "files"} on ${branch}`}
33 </span>
34 </div>
35 <p className="mt-1.5 max-w-2xl text-sm text-muted">
36 Every agent run here reads the repository's <code className="font-mono text-xs">AGENTS.md</code> and{" "}
37 <code className="font-mono text-xs">CLAUDE.md</code> from {branch}: the ones at the root, and the nearest
38 ones above the files its task touches. Reviews also read{" "}
39 <code className="font-mono text-xs">.g1t/review.md</code>. Each file is cut at{" "}
40 {limits.fileChars.toLocaleString()} characters, and all of them at {limits.totalChars.toLocaleString()}.
41 </p>
42 <p className="mt-2 flex max-w-2xl items-start gap-2 text-xs text-faint">
43 <ShieldCheck size={13} className="mt-px shrink-0" />
44 Only {branch} and the repository's own branches are followed. A pull request from a fork that changes these
45 files is reviewed as a change, never followed as instructions.
46 </p>
47 {files.length === 0 ? (
48 <div className="mt-3">
49 <Idle>
50 No instructions yet. Commit an AGENTS.md to {branch} with how to build, test and work in this repository,
51 and every agent run reads it.
52 </Idle>
53 </div>
54 ) : (
55 <ul className="mt-3 space-y-3">
56 {files.map((file) => (
57 <Card asChild key={file.path}>
58 <li>
59 <details>
60 <summary className="flex cursor-pointer flex-wrap items-center gap-x-3 gap-y-1 px-4 py-3 text-sm">
61 <FileText size={14} className="text-muted" />
62 <span className="font-mono font-medium">{file.path}</span>
63 <span className="rounded-full bg-raised px-2 py-px text-xs text-muted">{ROLE[file.role]}</span>
64 {file.truncated && <span className="text-xs text-warn">Longer than agents are given</span>}
65 <span className="ml-auto flex items-center gap-2 text-xs text-faint">
66 {file.lastChanged && (
67 <>
68 <Hint label={file.lastChanged.message}>
69 <Link to={`${base}/commit/${file.lastChanged.commit}`} className="font-mono hover:text-fg">
70 {file.lastChanged.commit.slice(0, 7)}
71 </Link>
72 </Hint>
73 <span>by {file.lastChanged.author}</span>
74 <TimeAgo at={file.lastChanged.at} />
75 </>
76 )}
77 <Link to={`${base}/blob/${encodeURIComponent(branch)}/${file.path}`} className="text-muted hover:text-fg">
78 Open in code
79 </Link>
80 </span>
81 </summary>
82 <pre className="max-h-96 overflow-auto border-t border-line px-4 py-3 font-mono text-xs whitespace-pre-wrap text-muted">
83 {file.text || "(empty)"}
84 </pre>
85 </details>
86 </li>
87 </Card>
88 ))}
89 </ul>
90 )}
91 <p className="mt-3 text-xs text-faint">
92 To change them, edit the files in the repository and merge the change into {branch}. Agents read the new version
93 from their next run.
94 </p>
95 </section>
96 );
97}