opencode-gitloops 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # Gitloops
2
+
3
+ A plugin for [OpenCode](https://opencode.ai) that lets you clone and explore any public GitHub repository locally. Ask questions about a repo's code, structure, and patterns — all without leaving your terminal.
4
+
5
+ Gitloops registers a read-only agent with three custom tools (`gitloops_clone`, `gitloops_refresh`, `gitloops_list`) and restricts itself to `read`, `grep`, `glob`, and `list` — no file modifications, no shell access.
6
+
7
+ ## Configuration
8
+
9
+ Gitloops auto-creates a config file on first load at:
10
+
11
+ ```
12
+ ~/.config/opencode/plugin/gitloops.json
13
+ ```
14
+
15
+ ```json
16
+ {
17
+ "$schema": "https://raw.githubusercontent.com/maharshi-me/gitloops/main/schema/config.schema.json",
18
+ "max_repos": 10,
19
+ "cache_loc": "~/.cache/gitloops/repos",
20
+ "eviction_strategy": "lru"
21
+ }
22
+ ```
23
+
24
+ | Option | Type | Default | Description |
25
+ |---|---|---|---|
26
+ | `max_repos` | `integer` | `10` | Maximum number of cached repos. When exceeded, repos are evicted automatically. |
27
+ | `cache_loc` | `string` | `~/.cache/gitloops/repos` | Directory where cloned repos are stored (`<cache_loc>/<owner>/<repo>/`). Supports `~`. |
28
+ | `eviction_strategy` | `string` | `"lru"` | Strategy for removing repos when `max_repos` is exceeded. |
29
+
30
+ ### Eviction strategies
31
+
32
+ | Strategy | Behavior |
33
+ |---|---|
34
+ | `lru` | Remove the least recently used repo (oldest modification time) |
35
+ | `fifo` | Remove the oldest cloned repo (oldest creation time) |
36
+ | `largest` | Remove the largest repo by disk size |
37
+
38
+ The `$schema` field enables autocompletion and validation in editors that support JSON Schema.
@@ -0,0 +1,25 @@
1
+ export type EvictionStrategy = "lru" | "fifo" | "largest";
2
+ export interface GitloopsConfig {
3
+ max_repos: number;
4
+ cache_loc: string;
5
+ eviction_strategy: EvictionStrategy;
6
+ }
7
+ /**
8
+ * Load the config from disk and merge with defaults.
9
+ * Result is cached after the first call.
10
+ */
11
+ export declare function getConfig(): Promise<GitloopsConfig>;
12
+ /**
13
+ * Reset the cached config so the next getConfig() call re-reads from disk.
14
+ */
15
+ export declare function resetConfigCache(): void;
16
+ /**
17
+ * Create the config file with defaults if it doesn't already exist.
18
+ * Returns true if a new file was created, false if it already existed.
19
+ */
20
+ export declare function ensureConfigFile(): Promise<boolean>;
21
+ /**
22
+ * Returns the config file path (for logging).
23
+ */
24
+ export declare function getConfigPath(): string;
25
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAA;AAEzD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,iBAAiB,EAAE,gBAAgB,CAAA;CACpC;AAiCD;;;GAGG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,cAAc,CAAC,CA6BzD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAyBzD;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
package/dist/config.js ADDED
@@ -0,0 +1,87 @@
1
+ import * as fs from "fs/promises";
2
+ import * as path from "path";
3
+ import * as os from "os";
4
+ const SCHEMA_URL = "https://raw.githubusercontent.com/maharshi-me/gitloops/main/schema/config.schema.json";
5
+ const CONFIG_PATH = path.join(os.homedir(), ".config", "opencode", "plugin", "gitloops.json");
6
+ const DEFAULT_CACHE_LOC = path.join(os.homedir(), ".cache", "gitloops", "repos");
7
+ const DEFAULTS = {
8
+ max_repos: 10,
9
+ cache_loc: DEFAULT_CACHE_LOC,
10
+ eviction_strategy: "lru",
11
+ };
12
+ /**
13
+ * Resolve ~ to the user's home directory.
14
+ */
15
+ function resolvePath(p) {
16
+ if (p.startsWith("~")) {
17
+ return path.join(os.homedir(), p.slice(1));
18
+ }
19
+ return path.resolve(p);
20
+ }
21
+ let _cached = null;
22
+ /**
23
+ * Load the config from disk and merge with defaults.
24
+ * Result is cached after the first call.
25
+ */
26
+ export async function getConfig() {
27
+ if (_cached)
28
+ return _cached;
29
+ let raw = {};
30
+ try {
31
+ const contents = await fs.readFile(CONFIG_PATH, "utf8");
32
+ raw = JSON.parse(contents);
33
+ }
34
+ catch {
35
+ // File doesn't exist or is invalid — use defaults
36
+ }
37
+ const merged = {
38
+ max_repos: typeof raw.max_repos === "number" && raw.max_repos >= 1
39
+ ? raw.max_repos
40
+ : DEFAULTS.max_repos,
41
+ cache_loc: raw.cache_loc
42
+ ? resolvePath(raw.cache_loc)
43
+ : DEFAULTS.cache_loc,
44
+ eviction_strategy: raw.eviction_strategy &&
45
+ ["lru", "fifo", "largest"].includes(raw.eviction_strategy)
46
+ ? raw.eviction_strategy
47
+ : DEFAULTS.eviction_strategy,
48
+ };
49
+ _cached = merged;
50
+ return merged;
51
+ }
52
+ /**
53
+ * Reset the cached config so the next getConfig() call re-reads from disk.
54
+ */
55
+ export function resetConfigCache() {
56
+ _cached = null;
57
+ }
58
+ /**
59
+ * Create the config file with defaults if it doesn't already exist.
60
+ * Returns true if a new file was created, false if it already existed.
61
+ */
62
+ export async function ensureConfigFile() {
63
+ try {
64
+ await fs.access(CONFIG_PATH);
65
+ return false; // already exists
66
+ }
67
+ catch {
68
+ // File doesn't exist — create it
69
+ }
70
+ const configDir = path.dirname(CONFIG_PATH);
71
+ await fs.mkdir(configDir, { recursive: true });
72
+ const defaultContent = {
73
+ $schema: SCHEMA_URL,
74
+ max_repos: DEFAULTS.max_repos,
75
+ cache_loc: "~/.cache/gitloops/repos",
76
+ eviction_strategy: DEFAULTS.eviction_strategy,
77
+ };
78
+ await fs.writeFile(CONFIG_PATH, JSON.stringify(defaultContent, null, 2) + "\n", "utf8");
79
+ return true;
80
+ }
81
+ /**
82
+ * Returns the config file path (for logging).
83
+ */
84
+ export function getConfigPath() {
85
+ return CONFIG_PATH;
86
+ }
87
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { GitloopsConfig } from "./config";
2
+ /**
3
+ * Evict repos if the total count exceeds max_repos.
4
+ * Removes repos according to the configured eviction strategy until
5
+ * the count is within the limit.
6
+ *
7
+ * @param config - The current gitloops config
8
+ * @param currentSlug - Optional slug to protect from eviction (e.g. the repo just cloned)
9
+ * @returns Array of evicted repo slugs
10
+ */
11
+ export declare function evictIfNeeded(config: GitloopsConfig, currentSlug?: string): Promise<string[]>;
12
+ //# sourceMappingURL=eviction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eviction.d.ts","sourceRoot":"","sources":["../src/eviction.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAoB,MAAM,UAAU,CAAA;AAwIhE;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC,CAuBnB"}
@@ -0,0 +1,148 @@
1
+ import * as fs from "fs/promises";
2
+ import * as path from "path";
3
+ /**
4
+ * Recursively compute the total size (in bytes) of a directory.
5
+ */
6
+ async function getDirSize(dirPath) {
7
+ let total = 0;
8
+ const entries = await fs.readdir(dirPath, { withFileTypes: true });
9
+ for (const entry of entries) {
10
+ const fullPath = path.join(dirPath, entry.name);
11
+ if (entry.isDirectory()) {
12
+ total += await getDirSize(fullPath);
13
+ }
14
+ else if (entry.isFile()) {
15
+ const stat = await fs.stat(fullPath);
16
+ total += stat.size;
17
+ }
18
+ }
19
+ return total;
20
+ }
21
+ /**
22
+ * Gather stats for all cached repos under the cache location.
23
+ */
24
+ async function gatherRepoStats(cacheLoc) {
25
+ const stats = [];
26
+ let owners;
27
+ try {
28
+ owners = await fs.readdir(cacheLoc);
29
+ }
30
+ catch {
31
+ return stats;
32
+ }
33
+ for (const owner of owners) {
34
+ const ownerPath = path.join(cacheLoc, owner);
35
+ let ownerStat;
36
+ try {
37
+ ownerStat = await fs.stat(ownerPath);
38
+ }
39
+ catch {
40
+ continue;
41
+ }
42
+ if (!ownerStat.isDirectory())
43
+ continue;
44
+ let repoNames;
45
+ try {
46
+ repoNames = await fs.readdir(ownerPath);
47
+ }
48
+ catch {
49
+ continue;
50
+ }
51
+ for (const repo of repoNames) {
52
+ const repoPath = path.join(ownerPath, repo);
53
+ try {
54
+ const gitDir = path.join(repoPath, ".git");
55
+ const gitStat = await fs.stat(gitDir);
56
+ if (!gitStat.isDirectory())
57
+ continue;
58
+ }
59
+ catch {
60
+ continue; // not a git repo
61
+ }
62
+ try {
63
+ const stat = await fs.stat(repoPath);
64
+ stats.push({
65
+ slug: `${owner}/${repo}`,
66
+ repoPath,
67
+ mtime: stat.mtime,
68
+ birthtime: stat.birthtime,
69
+ size: 0, // computed lazily for "largest" strategy
70
+ });
71
+ }
72
+ catch {
73
+ continue;
74
+ }
75
+ }
76
+ }
77
+ return stats;
78
+ }
79
+ /**
80
+ * Remove a cached repo directory and clean up empty parent owner directories.
81
+ */
82
+ async function removeRepo(repoPath, cacheLoc) {
83
+ await fs.rm(repoPath, { recursive: true, force: true });
84
+ // Clean up empty owner directory
85
+ const ownerDir = path.dirname(repoPath);
86
+ try {
87
+ const remaining = await fs.readdir(ownerDir);
88
+ if (remaining.length === 0) {
89
+ await fs.rmdir(ownerDir);
90
+ }
91
+ }
92
+ catch {
93
+ // Ignore — owner dir may already be gone
94
+ }
95
+ }
96
+ /**
97
+ * Sort repos by eviction priority (first element = first to evict).
98
+ */
99
+ async function sortByStrategy(repos, strategy) {
100
+ const sorted = [...repos];
101
+ switch (strategy) {
102
+ case "lru":
103
+ // Least recently modified first
104
+ sorted.sort((a, b) => a.mtime.getTime() - b.mtime.getTime());
105
+ break;
106
+ case "fifo":
107
+ // Oldest creation time first
108
+ sorted.sort((a, b) => a.birthtime.getTime() - b.birthtime.getTime());
109
+ break;
110
+ case "largest":
111
+ // Compute sizes then sort largest first
112
+ for (const repo of sorted) {
113
+ repo.size = await getDirSize(repo.repoPath);
114
+ }
115
+ sorted.sort((a, b) => b.size - a.size);
116
+ break;
117
+ }
118
+ return sorted;
119
+ }
120
+ /**
121
+ * Evict repos if the total count exceeds max_repos.
122
+ * Removes repos according to the configured eviction strategy until
123
+ * the count is within the limit.
124
+ *
125
+ * @param config - The current gitloops config
126
+ * @param currentSlug - Optional slug to protect from eviction (e.g. the repo just cloned)
127
+ * @returns Array of evicted repo slugs
128
+ */
129
+ export async function evictIfNeeded(config, currentSlug) {
130
+ const allRepos = await gatherRepoStats(config.cache_loc);
131
+ if (allRepos.length <= config.max_repos) {
132
+ return [];
133
+ }
134
+ const evictCount = allRepos.length - config.max_repos;
135
+ const sorted = await sortByStrategy(allRepos, config.eviction_strategy);
136
+ // Filter out the current repo from eviction candidates
137
+ const candidates = currentSlug
138
+ ? sorted.filter((r) => r.slug !== currentSlug)
139
+ : sorted;
140
+ const evicted = [];
141
+ for (let i = 0; i < evictCount && i < candidates.length; i++) {
142
+ const repo = candidates[i];
143
+ await removeRepo(repo.repoPath, config.cache_loc);
144
+ evicted.push(repo.slug);
145
+ }
146
+ return evicted;
147
+ }
148
+ //# sourceMappingURL=eviction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eviction.js","sourceRoot":"","sources":["../src/eviction.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AA+CjD,eAAO,MAAM,cAAc,EAAE,MA0E5B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAkDjD,eAAO,MAAM,cAAc,EAAE,MAoG5B,CAAA"}
package/dist/index.js CHANGED
@@ -1,12 +1,14 @@
1
1
  import { gitloops_clone, gitloops_refresh, gitloops_list } from "./tools";
2
2
  import { ensureRepo } from "./repo-manager";
3
+ import { ensureConfigFile, getConfig, getConfigPath } from "./config";
3
4
  import * as fs from "fs/promises";
4
5
  import * as path from "path";
5
6
  import * as os from "os";
6
- const AGENT_MD = `---
7
+ function buildAgentMD(cacheLoc) {
8
+ return `---
7
9
  description: Explore GitHub repositories locally. Clone any public repo and answer questions about its code, structure, and patterns.
8
10
  mode: all
9
- color: "#4078c0"
11
+ color: "#ed5f00"
10
12
  temperature: 0.1
11
13
  tools:
12
14
  read: true
@@ -25,7 +27,7 @@ permission:
25
27
  bash: deny
26
28
  ---
27
29
 
28
- You are GitLoops, a read-only agent for exploring public GitHub repositories locally.
30
+ You are Gitloops, a read-only agent for exploring public GitHub repositories locally.
29
31
 
30
32
  When a user asks about a repository:
31
33
  1. Parse the repo slug from their message (e.g. "facebook/react" or a full GitHub URL)
@@ -40,21 +42,47 @@ Important rules:
40
42
  - All file paths passed to read/grep/glob/list must be absolute paths under the repo's localPath.
41
43
  - When switching between repos in the same session, always call \`gitloops_clone\` again for the new repo.
42
44
 
43
- Repos are cached at: ~/.cache/gitloops/repos/<owner>/<repo>/
45
+ Repos are cached at: ${cacheLoc}/<owner>/<repo>/
44
46
  `;
47
+ }
45
48
  export const GitLoopsPlugin = async ({ client }) => {
46
49
  return {
47
- // Write agent definition to global config on server connect (idempotent)
50
+ // Write agent definition and ensure config on server connect (idempotent)
48
51
  "server.connected": async () => {
52
+ // Ensure the plugin config file exists (auto-create with defaults)
49
53
  try {
54
+ const created = await ensureConfigFile();
55
+ if (created) {
56
+ await client.app.log({
57
+ body: {
58
+ service: "opencode-gitloops",
59
+ level: "info",
60
+ message: `Config created with defaults at ${getConfigPath()}`,
61
+ },
62
+ });
63
+ }
64
+ }
65
+ catch (err) {
66
+ await client.app.log({
67
+ body: {
68
+ service: "opencode-gitloops",
69
+ level: "warn",
70
+ message: `Failed to create config: ${err.message || err}`,
71
+ },
72
+ });
73
+ }
74
+ // Write agent definition to global config
75
+ try {
76
+ const config = await getConfig();
77
+ const agentMD = buildAgentMD(config.cache_loc);
50
78
  const agentsDir = path.join(os.homedir(), ".config", "opencode", "agents");
51
79
  const agentPath = path.join(agentsDir, "gitloops.md");
52
80
  await fs.mkdir(agentsDir, { recursive: true });
53
81
  const existing = await fs
54
82
  .readFile(agentPath, "utf8")
55
83
  .catch(() => null);
56
- if (existing !== AGENT_MD) {
57
- await fs.writeFile(agentPath, AGENT_MD, "utf8");
84
+ if (existing !== agentMD) {
85
+ await fs.writeFile(agentPath, agentMD, "utf8");
58
86
  await client.app.log({
59
87
  body: {
60
88
  service: "opencode-gitloops",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,KAAK,EAAE,MAAM,aAAa,CAAA;AACjC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAA;AAExB,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsChB,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAW,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;IACzD,OAAO;QACL,yEAAyE;QACzE,kBAAkB,EAAE,KAAK,IAAI,EAAE;YAC7B,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CACzB,EAAE,CAAC,OAAO,EAAE,EACZ,SAAS,EACT,UAAU,EACV,QAAQ,CACT,CAAA;gBACD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;gBAErD,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;gBAE9C,MAAM,QAAQ,GAAG,MAAM,EAAE;qBACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;qBAC3B,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;gBAEpB,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;oBAC1B,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAA;oBAC/C,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;wBACnB,IAAI,EAAE;4BACJ,OAAO,EAAE,mBAAmB;4BAC5B,KAAK,EAAE,MAAM;4BACb,OAAO,EAAE,+BAA+B,SAAS,EAAE;yBACpD;qBACF,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;oBACnB,IAAI,EAAE;wBACJ,OAAO,EAAE,mBAAmB;wBAC5B,KAAK,EAAE,MAAM;wBACb,OAAO,EAAE,qCAAqC,GAAG,CAAC,OAAO,IAAI,GAAG,EAAE;qBACnE;iBACF,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QAED,2EAA2E;QAC3E,uCAAuC;QACvC,KAAK,EAAE,KAAK,EAAE,EAAE,KAAK,EAAiD,EAAE,EAAE;YACxE,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB;gBAAE,OAAM;YAE5C,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAA;gBAChC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,KAAK,UAAU;oBAAE,OAAM;gBAEtD,0CAA0C;gBAC1C,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,EAAE,KAAK,CACpC,oCAAoC,CACrC,CAAA;gBACD,IAAI,SAAS,EAAE,CAAC;oBACd,MAAM,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;oBAC9B,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;wBACnB,IAAI,EAAE;4BACJ,OAAO,EAAE,mBAAmB;4BAC5B,KAAK,EAAE,MAAM;4BACb,OAAO,EAAE,oBAAoB,SAAS,CAAC,CAAC,CAAC,EAAE;yBAC5C;qBACF,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,qDAAqD;YACvD,CAAC;QACH,CAAC;QAED,IAAI,EAAE;YACJ,cAAc;YACd,gBAAgB;YAChB,aAAa;SACd;KACF,CAAA;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -30,15 +30,16 @@ export declare function parseRepoSlug(input: string): ParsedRepo;
30
30
  /**
31
31
  * Get the local filesystem path where a repo is (or would be) cached.
32
32
  */
33
- export declare function getLocalPath(slug: string): string;
33
+ export declare function getLocalPath(slug: string): Promise<string>;
34
34
  /**
35
35
  * Clone a repo (or fetch latest if already cloned). Returns metadata about the repo.
36
36
  *
37
37
  * Respects GITLOOPS_FULL_CLONE env var — if truthy, clones without --depth=1.
38
+ * Enforces max_repos limit via the configured eviction strategy after cloning.
38
39
  */
39
40
  export declare function ensureRepo(input: string): Promise<RepoInfo>;
40
41
  /**
41
- * List all repos currently cached under ~/.cache/gitloops/repos/.
42
+ * List all repos currently cached under the configured cache location.
42
43
  */
43
44
  export declare function listCachedRepos(): Promise<CachedRepo[]>;
44
45
  //# sourceMappingURL=repo-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"repo-manager.d.ts","sourceRoot":"","sources":["../src/repo-manager.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb;AAID;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CA8CvD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGjD;AA0BD;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAoDjE;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CA8C7D"}
1
+ {"version":3,"file":"repo-manager.d.ts","sourceRoot":"","sources":["../src/repo-manager.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CA8CvD;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIhE;AA0BD;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwDjE;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAgD7D"}
@@ -1,8 +1,8 @@
1
1
  import { $ } from "bun";
2
2
  import * as fs from "fs/promises";
3
3
  import * as path from "path";
4
- import * as os from "os";
5
- const CACHE_ROOT = path.join(os.homedir(), ".cache", "gitloops", "repos");
4
+ import { getConfig } from "./config";
5
+ import { evictIfNeeded } from "./eviction";
6
6
  /**
7
7
  * Parse a repo slug or URL into its components.
8
8
  *
@@ -52,9 +52,10 @@ export function parseRepoSlug(input) {
52
52
  /**
53
53
  * Get the local filesystem path where a repo is (or would be) cached.
54
54
  */
55
- export function getLocalPath(slug) {
55
+ export async function getLocalPath(slug) {
56
56
  const { owner, repo } = parseRepoSlug(slug);
57
- return path.join(CACHE_ROOT, owner, repo);
57
+ const config = await getConfig();
58
+ return path.join(config.cache_loc, owner, repo);
58
59
  }
59
60
  /**
60
61
  * Check if a directory exists.
@@ -84,10 +85,12 @@ async function getLastCommit(repoPath) {
84
85
  * Clone a repo (or fetch latest if already cloned). Returns metadata about the repo.
85
86
  *
86
87
  * Respects GITLOOPS_FULL_CLONE env var — if truthy, clones without --depth=1.
88
+ * Enforces max_repos limit via the configured eviction strategy after cloning.
87
89
  */
88
90
  export async function ensureRepo(input) {
89
91
  const parsed = parseRepoSlug(input);
90
- const localPath = path.join(CACHE_ROOT, parsed.owner, parsed.repo);
92
+ const config = await getConfig();
93
+ const localPath = path.join(config.cache_loc, parsed.owner, parsed.repo);
91
94
  const fullClone = process.env.GITLOOPS_FULL_CLONE === "true";
92
95
  const depthArgs = fullClone ? [] : ["--depth=1"];
93
96
  if (await dirExists(path.join(localPath, ".git"))) {
@@ -120,6 +123,8 @@ export async function ensureRepo(input) {
120
123
  }
121
124
  throw new Error(`Failed to clone ${parsed.slug}: ${err.message || err}`);
122
125
  }
126
+ // Evict old repos if we've exceeded the max
127
+ await evictIfNeeded(config, parsed.slug);
123
128
  }
124
129
  const lastCommit = await getLastCommit(localPath);
125
130
  return {
@@ -132,22 +137,24 @@ export async function ensureRepo(input) {
132
137
  };
133
138
  }
134
139
  /**
135
- * List all repos currently cached under ~/.cache/gitloops/repos/.
140
+ * List all repos currently cached under the configured cache location.
136
141
  */
137
142
  export async function listCachedRepos() {
143
+ const config = await getConfig();
144
+ const cacheLoc = config.cache_loc;
138
145
  const repos = [];
139
- if (!(await dirExists(CACHE_ROOT))) {
146
+ if (!(await dirExists(cacheLoc))) {
140
147
  return repos;
141
148
  }
142
149
  let owners;
143
150
  try {
144
- owners = await fs.readdir(CACHE_ROOT);
151
+ owners = await fs.readdir(cacheLoc);
145
152
  }
146
153
  catch {
147
154
  return repos;
148
155
  }
149
156
  for (const owner of owners) {
150
- const ownerPath = path.join(CACHE_ROOT, owner);
157
+ const ownerPath = path.join(cacheLoc, owner);
151
158
  if (!(await dirExists(ownerPath)))
152
159
  continue;
153
160
  let repoNames;
@@ -1 +1 @@
1
- {"version":3,"file":"repo-manager.js","sourceRoot":"","sources":["../src/repo-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"repo-manager.js","sourceRoot":"","sources":["../src/repo-manager.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-gitloops",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "GitHub repo explorer agent and plugin for OpenCode. Clone and explore any public GitHub repo locally.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -12,7 +12,8 @@
12
12
  }
13
13
  },
14
14
  "files": [
15
- "dist/"
15
+ "dist/",
16
+ "schema/"
16
17
  ],
17
18
  "keywords": [
18
19
  "opencode",
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://raw.githubusercontent.com/maharshi-me/gitloops/main/schema/config.schema.json",
4
+ "title": "Gitloops Configuration",
5
+ "description": "Configuration for the opencode-gitloops plugin.",
6
+ "type": "object",
7
+ "properties": {
8
+ "$schema": {
9
+ "type": "string",
10
+ "description": "Path or URL to the JSON schema for this config file."
11
+ },
12
+ "max_repos": {
13
+ "type": "integer",
14
+ "minimum": 1,
15
+ "default": 10,
16
+ "description": "Maximum number of cached repositories. When exceeded, repos are evicted based on the eviction_strategy."
17
+ },
18
+ "cache_loc": {
19
+ "type": "string",
20
+ "default": "~/.cache/gitloops/repos",
21
+ "description": "Directory where cloned repositories are stored. Repos are placed directly at <cache_loc>/<owner>/<repo>/. Supports ~ for the home directory."
22
+ },
23
+ "eviction_strategy": {
24
+ "type": "string",
25
+ "enum": ["lru", "fifo", "largest"],
26
+ "default": "lru",
27
+ "description": "Strategy used to evict repos when max_repos is exceeded. 'lru' removes least recently used, 'fifo' removes oldest cloned, 'largest' removes the largest repo by disk size."
28
+ }
29
+ },
30
+ "additionalProperties": false
31
+ }