just-git 1.2.0 → 1.2.4
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 +40 -206
- package/dist/{hooks-Boa35Qx_.d.ts → hooks-4DvkF2xT.d.ts} +141 -4
- package/dist/index.d.ts +25 -72
- package/dist/index.js +336 -336
- package/dist/repo/index.d.ts +27 -1
- package/dist/repo/index.js +11 -11
- package/dist/server/index.d.ts +54 -116
- package/dist/server/index.js +46 -29
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -22,17 +22,24 @@ npm install just-git
|
|
|
22
22
|
import { createGit, MemoryFileSystem } from "just-git";
|
|
23
23
|
|
|
24
24
|
const fs = new MemoryFileSystem();
|
|
25
|
-
const git = createGit({
|
|
25
|
+
const git = createGit({
|
|
26
|
+
identity: { name: "Alice", email: "alice@example.com" },
|
|
27
|
+
credentials: (url) => ({ type: "bearer", token: process.env.GITHUB_TOKEN! }),
|
|
28
|
+
hooks: {
|
|
29
|
+
beforeCommand: ({ command }) => {
|
|
30
|
+
if (command === "push") return { reject: true, message: "push requires approval" };
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
});
|
|
26
34
|
|
|
27
35
|
await git.exec("git init", { fs, cwd: "/repo" });
|
|
36
|
+
await fs.writeFile("/repo/README.md", "# Hello\n");
|
|
28
37
|
await git.exec("git add .", { fs, cwd: "/repo" });
|
|
29
38
|
await git.exec('git commit -m "initial commit"', { fs, cwd: "/repo" });
|
|
30
39
|
await git.exec("git log --oneline", { fs, cwd: "/repo" });
|
|
31
40
|
```
|
|
32
41
|
|
|
33
|
-
`MemoryFileSystem` is a minimal in-memory filesystem
|
|
34
|
-
|
|
35
|
-
For a full virtual shell with file I/O, pipes, and scripting, pair with [just-bash](https://github.com/vercel-labs/just-bash):
|
|
42
|
+
`MemoryFileSystem` is a minimal in-memory filesystem for standalone use. Tokenization handles single and double quotes; pass `env` as a plain object when needed (e.g. `GIT_AUTHOR_NAME`). The `FileSystem` interface is built around [just-bash](https://github.com/vercel-labs/just-bash)'s implementations. For anything beyond bare git commands, it's recommended to use just-git as a custom command in just-bash:
|
|
36
43
|
|
|
37
44
|
```ts
|
|
38
45
|
import { Bash } from "just-bash";
|
|
@@ -52,10 +59,10 @@ await bash.exec("git add . && git commit -m 'initial commit'");
|
|
|
52
59
|
Stand up a git server with built-in storage (SQLite or [PostgreSQL](docs/SERVER.md#pgstorage)), branch protection, and push hooks:
|
|
53
60
|
|
|
54
61
|
```ts
|
|
55
|
-
import { createGitServer,
|
|
62
|
+
import { createGitServer, BunSqliteStorage } from "just-git/server";
|
|
56
63
|
import { Database } from "bun:sqlite";
|
|
57
64
|
|
|
58
|
-
const storage = new
|
|
65
|
+
const storage = new BunSqliteStorage(new Database("repos.sqlite"));
|
|
59
66
|
|
|
60
67
|
const server = createGitServer({
|
|
61
68
|
resolveRepo: (path) => storage.repo(path),
|
|
@@ -74,252 +81,79 @@ Bun.serve({ fetch: server.fetch });
|
|
|
74
81
|
// git clone http://localhost:3000/my-repo ← works with real git
|
|
75
82
|
```
|
|
76
83
|
|
|
77
|
-
Uses web-standard `Request`/`Response
|
|
84
|
+
Uses web-standard `Request`/`Response`. Works with Bun, Hono, Cloudflare Workers, or any fetch-compatible runtime. For Node.js, use `toNodeHandler(server)` with `http.createServer` and `BetterSqlite3Storage` for `better-sqlite3`. See [SERVER.md](docs/SERVER.md) for the full API.
|
|
78
85
|
|
|
79
|
-
##
|
|
86
|
+
## createGit options
|
|
80
87
|
|
|
81
88
|
`createGit(options?)` accepts:
|
|
82
89
|
|
|
83
|
-
| Option | Description
|
|
84
|
-
| --------------- |
|
|
85
|
-
| `identity` | Author/committer override. With `locked: true`, always wins over env vars and git config. Without `locked`, acts as a fallback.
|
|
86
|
-
| `credentials` | `(url) => HttpAuth \| null` callback for Smart HTTP transport auth.
|
|
87
|
-
| `disabled` | `GitCommandName[]` of subcommands to block (e.g. `["push", "rebase"]`).
|
|
88
|
-
| `network` | `{ allowed?: string[], fetch
|
|
89
|
-
| `config` | `{ locked?, defaults? }` config overrides. `locked` values always win over `.git/config`; `defaults` supply fallbacks when a key is absent.
|
|
90
|
-
| `hooks` |
|
|
91
|
-
| `resolveRemote` | `(url) => GitRepo \| null` callback for cross-VFS remote resolution
|
|
92
|
-
|
|
93
|
-
```ts
|
|
94
|
-
const git = createGit({
|
|
95
|
-
identity: { name: "Agent Bot", email: "bot@company.com", locked: true },
|
|
96
|
-
credentials: async (url) => ({ type: "bearer", token: "ghp_..." }),
|
|
97
|
-
disabled: ["rebase"],
|
|
98
|
-
network: false, // no HTTP access
|
|
99
|
-
config: {
|
|
100
|
-
locked: { "push.default": "nothing" },
|
|
101
|
-
defaults: { "merge.ff": "only" },
|
|
102
|
-
},
|
|
103
|
-
});
|
|
104
|
-
```
|
|
90
|
+
| Option | Description |
|
|
91
|
+
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
92
|
+
| `identity` | Author/committer override. With `locked: true`, always wins over env vars and git config. Without `locked`, acts as a fallback. |
|
|
93
|
+
| `credentials` | `(url) => HttpAuth \| null` callback for Smart HTTP transport auth. |
|
|
94
|
+
| `disabled` | `GitCommandName[]` of subcommands to block (e.g. `["push", "rebase"]`). |
|
|
95
|
+
| `network` | `{ allowed?: string[], fetch? }` to restrict HTTP access. Set to `false` to block all network access. |
|
|
96
|
+
| `config` | `{ locked?, defaults? }` config overrides. `locked` values always win over `.git/config`; `defaults` supply fallbacks when a key is absent. |
|
|
97
|
+
| `hooks` | Lifecycle hooks for pre/post command interception, commit gating, message enforcement, and audit logging. |
|
|
98
|
+
| `resolveRemote` | `(url) => GitRepo \| null` callback for cross-VFS remote resolution (multi-agent setups). |
|
|
105
99
|
|
|
106
|
-
|
|
100
|
+
See [CLIENT.md](docs/CLIENT.md) for detailed usage, config overrides, and multi-agent collaboration.
|
|
107
101
|
|
|
108
|
-
|
|
102
|
+
## Client hooks
|
|
109
103
|
|
|
110
|
-
Pre-hooks can reject the operation by returning `{ reject: true, message? }`. Post-hooks are observational
|
|
104
|
+
Hooks fire at specific points inside command execution. Pre-hooks can reject the operation by returning `{ reject: true, message? }`. Post-hooks are observational. All hook payloads include `repo: GitRepo` for [programmatic repo access](docs/REPO.md).
|
|
111
105
|
|
|
112
106
|
```ts
|
|
113
|
-
import { createGit
|
|
107
|
+
import { createGit } from "just-git";
|
|
114
108
|
import { getChangedFiles } from "just-git/repo";
|
|
115
109
|
|
|
116
110
|
const git = createGit({
|
|
117
111
|
hooks: {
|
|
118
|
-
// Block secrets from being committed
|
|
119
112
|
preCommit: ({ index }) => {
|
|
120
113
|
const forbidden = index.entries.filter((e) => /\.(env|pem|key)$/.test(e.path));
|
|
121
114
|
if (forbidden.length) {
|
|
122
115
|
return { reject: true, message: `Blocked: ${forbidden.map((e) => e.path).join(", ")}` };
|
|
123
116
|
}
|
|
124
117
|
},
|
|
125
|
-
|
|
126
|
-
// Enforce conventional commit messages
|
|
127
|
-
commitMsg: (event) => {
|
|
128
|
-
if (!/^(feat|fix|docs|refactor|test|chore)(\(.+\))?:/.test(event.message)) {
|
|
129
|
-
return { reject: true, message: "Commit message must follow conventional commits format" };
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
|
-
|
|
133
|
-
// Feed agent activity to your UI — with changed file list
|
|
134
118
|
postCommit: async ({ repo, hash, branch, parents }) => {
|
|
135
119
|
const files = await getChangedFiles(repo, parents[0] ?? null, hash);
|
|
136
120
|
onAgentCommit({ hash, branch, changedFiles: files });
|
|
137
121
|
},
|
|
138
|
-
|
|
139
|
-
// Audit log — record every command
|
|
140
|
-
afterCommand: ({ command, args, result }) => {
|
|
141
|
-
auditLog.push({ command: `git ${command}`, exitCode: result.exitCode });
|
|
142
|
-
},
|
|
143
|
-
|
|
144
|
-
// Gate pushes on human approval
|
|
145
|
-
beforeCommand: async ({ command }) => {
|
|
146
|
-
if (command === "push" && !(await getHumanApproval())) {
|
|
147
|
-
return { reject: true, message: "Push blocked — awaiting approval." };
|
|
148
|
-
}
|
|
149
|
-
},
|
|
150
122
|
},
|
|
151
123
|
});
|
|
152
124
|
```
|
|
153
125
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
```ts
|
|
157
|
-
import { createGit, composeGitHooks } from "just-git";
|
|
158
|
-
|
|
159
|
-
const git = createGit({
|
|
160
|
-
hooks: composeGitHooks(auditHooks, policyHooks, loggingHooks),
|
|
161
|
-
});
|
|
162
|
-
```
|
|
126
|
+
Combine multiple hook sets with `composeGitHooks(auditHooks, policyHooks, loggingHooks)`. See [HOOKS.md](docs/HOOKS.md) for the full type reference and [CLIENT.md](docs/CLIENT.md) for more examples.
|
|
163
127
|
|
|
164
|
-
|
|
128
|
+
## Repo module
|
|
165
129
|
|
|
166
|
-
|
|
130
|
+
`just-git/repo` provides programmatic access to git repositories: reading commits, diffing trees, creating objects, and merging, all without going through command execution.
|
|
167
131
|
|
|
168
|
-
|
|
132
|
+
Everything operates on `GitRepo`, a minimal `{ objectStore, refStore }` interface shared by the client and server. A `GitRepo` can be backed by a virtual filesystem, SQLite, Postgres, or any custom storage. The same helpers work inside both client-side hooks and server-side hooks, and `createWorktree` lets you spin up a full git client against a database-backed repo.
|
|
169
133
|
|
|
170
134
|
```ts
|
|
171
|
-
|
|
172
|
-
config: {
|
|
173
|
-
locked: {
|
|
174
|
-
"push.default": "nothing", // agent must always specify a refspec
|
|
175
|
-
"merge.conflictstyle": "diff3", // always show base in conflict markers
|
|
176
|
-
},
|
|
177
|
-
defaults: {
|
|
178
|
-
"pull.rebase": "true", // default to rebase-on-pull (agent can change)
|
|
179
|
-
"merge.ff": "only", // default to ff-only (agent can change)
|
|
180
|
-
},
|
|
181
|
-
},
|
|
182
|
-
});
|
|
183
|
-
```
|
|
135
|
+
import { readFileAtCommit, getChangedFiles, mergeTrees } from "just-git/repo";
|
|
184
136
|
|
|
185
|
-
- **`locked`** — values that take absolute precedence. The agent can run `git config set` (the write succeeds on the VFS), but the locked value always wins on every read. Useful for enforcing policies.
|
|
186
|
-
- **`defaults`** — fallback values when a key is absent from `.git/config`. The agent _can_ override these with `git config set`. Useful for sensible defaults without restricting the agent.
|
|
187
|
-
|
|
188
|
-
Applied transparently via `getConfigValue()` — all commands respect overrides automatically. Any dotted config key works (e.g. `"merge.ff"`, `"push.default"`, `"pull.rebase"`, `"merge.conflictstyle"`, `"branch.autoSetupMerge"`).
|
|
189
|
-
|
|
190
|
-
## Repo module
|
|
191
|
-
|
|
192
|
-
`just-git/repo` provides a high-level API for working with repositories programmatically — reading commits, diffing trees, creating objects, and merging — without going through command execution. This is what you use inside hooks (all hook payloads include `repo: GitRepo`) and anywhere else you need direct repo access.
|
|
193
|
-
|
|
194
|
-
```ts
|
|
195
|
-
import {
|
|
196
|
-
readCommit,
|
|
197
|
-
readFileAtCommit,
|
|
198
|
-
getChangedFiles,
|
|
199
|
-
resolveRef,
|
|
200
|
-
listBranches,
|
|
201
|
-
diffTrees,
|
|
202
|
-
flattenTree,
|
|
203
|
-
createCommit,
|
|
204
|
-
writeBlob,
|
|
205
|
-
writeTree,
|
|
206
|
-
mergeTrees,
|
|
207
|
-
checkoutTo,
|
|
208
|
-
readonlyRepo,
|
|
209
|
-
} from "just-git/repo";
|
|
210
|
-
|
|
211
|
-
// Read a file at a specific commit
|
|
212
137
|
const content = await readFileAtCommit(repo, commitHash, "src/index.ts");
|
|
213
|
-
|
|
214
|
-
// Diff two commits
|
|
215
138
|
const changes = await getChangedFiles(repo, parentHash, commitHash);
|
|
216
|
-
|
|
217
|
-
// Merge two branches at the tree level (no worktree needed)
|
|
218
139
|
const result = await mergeTrees(repo, oursCommit, theirsCommit);
|
|
219
|
-
if (!result.clean) console.log("conflicts:", result.conflicts);
|
|
220
140
|
```
|
|
221
141
|
|
|
222
|
-
|
|
142
|
+
See [REPO.md](docs/REPO.md) for the full API, the `GitRepo` interface, and the hybrid worktree pattern.
|
|
223
143
|
|
|
224
144
|
## Multi-agent collaboration
|
|
225
145
|
|
|
226
|
-
Multiple agents can
|
|
227
|
-
|
|
228
|
-
```ts
|
|
229
|
-
import { Bash, InMemoryFs } from "just-bash";
|
|
230
|
-
import { createGit, findRepo } from "just-git";
|
|
231
|
-
|
|
232
|
-
// Origin repo on its own filesystem
|
|
233
|
-
const originFs = new InMemoryFs();
|
|
234
|
-
const setupBash = new Bash({
|
|
235
|
-
fs: originFs,
|
|
236
|
-
cwd: "/repo",
|
|
237
|
-
customCommands: [
|
|
238
|
-
createGit({ identity: { name: "Setup", email: "setup@example.com", locked: true } }),
|
|
239
|
-
],
|
|
240
|
-
});
|
|
241
|
-
await setupBash.exec("git init");
|
|
242
|
-
await setupBash.exec("echo 'hello' > README.md");
|
|
243
|
-
await setupBash.exec("git add . && git commit -m 'initial'");
|
|
244
|
-
|
|
245
|
-
const alice = new Bash({
|
|
246
|
-
fs: new InMemoryFs(),
|
|
247
|
-
cwd: "/repo",
|
|
248
|
-
customCommands: [
|
|
249
|
-
createGit({
|
|
250
|
-
identity: { name: "Alice", email: "alice@example.com", locked: true },
|
|
251
|
-
resolveRemote: () => findRepo(originFs, "/repo"),
|
|
252
|
-
}),
|
|
253
|
-
],
|
|
254
|
-
});
|
|
146
|
+
Multiple agents can clone, fetch, push, and pull across isolated in-memory filesystems within the same process via the `resolveRemote` option, without needing a network or shared filesystem. Concurrent pushes are automatically serialized with proper non-fast-forward rejection. See [CLIENT.md](docs/CLIENT.md#multi-agent-collaboration) and [`examples/multi-agent.ts`](examples/multi-agent.ts).
|
|
255
147
|
|
|
256
|
-
|
|
257
|
-
fs: new InMemoryFs(),
|
|
258
|
-
cwd: "/repo",
|
|
259
|
-
customCommands: [
|
|
260
|
-
createGit({
|
|
261
|
-
identity: { name: "Bob", email: "bob@example.com", locked: true },
|
|
262
|
-
resolveRemote: () => findRepo(originFs, "/repo"),
|
|
263
|
-
}),
|
|
264
|
-
],
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
await alice.exec("git clone /origin /repo");
|
|
268
|
-
await bob.exec("git clone /origin /repo");
|
|
269
|
-
|
|
270
|
-
// Alice and Bob work independently, push to origin, fetch each other's changes
|
|
271
|
-
```
|
|
148
|
+
## Commands
|
|
272
149
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
See [`examples/multi-agent.ts`](examples/multi-agent.ts) for a full working example with a coordinator agent that merges feature branches.
|
|
276
|
-
|
|
277
|
-
## Command coverage
|
|
278
|
-
|
|
279
|
-
See [CLI.md](docs/CLI.md) for full usage details.
|
|
280
|
-
|
|
281
|
-
| Command | Flags / options |
|
|
282
|
-
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
283
|
-
| `init [<dir>]` | `--bare`, `--initial-branch` |
|
|
284
|
-
| `clone <repo> [<dir>]` | `--bare`, `-b <branch>`, `--depth` |
|
|
285
|
-
| `blame <file>` | `-L <start>,<end>`, `-l`/`--long`, `-e`/`--show-email`, `-s`/`--suppress`, `-p`/`--porcelain`, `--line-porcelain` |
|
|
286
|
-
| `add <paths>` | `.`, `--all`/`-A`, `--update`/`-u`, `--force`/`-f`, `-n`/`--dry-run`, glob pathspecs |
|
|
287
|
-
| `rm <paths>` | `--cached`, `-r`, `-f`, `-n`/`--dry-run`, glob pathspecs |
|
|
288
|
-
| `mv <src> <dst>` | `-f`, `-n`/`--dry-run`, `-k` |
|
|
289
|
-
| `commit` | `-m`, `-F <file>` / `-F -`, `--allow-empty`, `--amend`, `--no-edit`, `-a` |
|
|
290
|
-
| `status` | `-s`/`--short`, `--porcelain`, `-b`/`--branch` |
|
|
291
|
-
| `log` | `--oneline`, `-n`, `--all`, `--reverse`, `--decorate`, `--graph`, `--format`/`--pretty`, `-p`/`--patch`, `--stat`, `--name-status`, `--name-only`, `--shortstat`, `--numstat`, `A..B`, `A...B`, `-- <path>`, `--author=`, `--grep=`, `--since`/`--after`, `--until`/`--before` |
|
|
292
|
-
| `show [<object>]` | Commits (with diff), annotated tags, trees, blobs |
|
|
293
|
-
| `diff` | `--cached`/`--staged`, `<commit>`, `<commit> <commit>`, `A..B`, `A...B`, `-- <path>`, `--stat`, `--shortstat`, `--numstat`, `--name-only`, `--name-status` |
|
|
294
|
-
| `branch` | `-d`, `-D`, `-m`, `-M`, `-r`, `-a`/`--all`, `-v`/`-vv`, `-u`/`--set-upstream-to` |
|
|
295
|
-
| `tag [<name>] [<commit>]` | `-a -m` (annotated), `-d`, `-l <pattern>`, `-f` |
|
|
296
|
-
| `switch` | `-c`/`-C` (create/force-create), `--detach`/`-d`, `--orphan`, `-` (previous branch), `--guess`/`--no-guess` |
|
|
297
|
-
| `restore` | `-s`/`--source`, `-S`/`--staged`, `-W`/`--worktree`, `-S -W` (both), `--ours`/`--theirs`, pathspec globs |
|
|
298
|
-
| `checkout` | `-b`, `-B`, `--orphan`, `--detach`/`-d`, detached HEAD, `-- <paths>`, `--ours`/`--theirs`, pathspec globs |
|
|
299
|
-
| `reset [<commit>]` | `-- <paths>`, `--soft`, `--mixed`, `--hard`, pathspec globs |
|
|
300
|
-
| `merge <branch>` | `--no-ff`, `--ff-only`, `--squash`, `-m`, `--abort`, `--continue`, conflict markers |
|
|
301
|
-
| `revert <commit>` | `--abort`, `--continue`, `-n`/`--no-commit`, `--no-edit`, `-m`/`--mainline` |
|
|
302
|
-
| `cherry-pick <commit>` | `--abort`, `--continue`, `--skip`, `-x`, `-m`/`--mainline`, `-n`/`--no-commit`, preserves original author |
|
|
303
|
-
| `rebase <upstream>` | `--onto <newbase>`, `--abort`, `--continue`, `--skip` |
|
|
304
|
-
| `stash` | `push`, `pop`, `apply`, `list`, `drop`, `show`, `clear`, `-m`, `-u`/`--include-untracked`, `stash@{N}` |
|
|
305
|
-
| `remote` | `add`, `remove`/`rm`, `rename`, `set-url`, `get-url`, `-v` |
|
|
306
|
-
| `config` | `get`, `set`, `unset`, `list`, `--list`/`-l`, `--unset`, `--get-all`, `--add` |
|
|
307
|
-
| `fetch [<remote>] [<refspec>...]` | `--all`, `--tags`, `--prune`/`-p`, `--depth`, `--unshallow` |
|
|
308
|
-
| `push [<remote>] [<refspec>...]` | `--force`/`-f`, `-u`/`--set-upstream`, `--all`, `--tags`, `--delete`/`-d` |
|
|
309
|
-
| `pull [<remote>] [<branch>]` | `--ff-only`, `--no-ff`, `--rebase`/`-r`, `--no-rebase`, `--depth`, `--unshallow` |
|
|
310
|
-
| `bisect` | `start`, `bad`/`good`/`new`/`old`, `skip`, `reset`, `log`, `replay`, `run`, `terms`, `visualize`/`view`, `--term-new`/`--term-old`, `--no-checkout`, `--first-parent` |
|
|
311
|
-
| `clean` | `-f`, `-n`/`--dry-run`, `-d`, `-x`, `-X`, `-e`/`--exclude` |
|
|
312
|
-
| `reflog` | `show [<ref>]`, `exists`, `-n`/`--max-count` |
|
|
313
|
-
| `gc` | `--aggressive` |
|
|
314
|
-
| `repack` | `-a`/`--all`, `-d`/`--delete` |
|
|
315
|
-
| `rev-parse` | `--verify`, `--short`, `--abbrev-ref`, `--symbolic-full-name`, `--show-toplevel`, `--git-dir`, `--is-inside-work-tree`, `--is-bare-repository`, `--show-prefix`, `--show-cdup` |
|
|
316
|
-
| `ls-files` | `-c`/`--cached`, `-m`/`--modified`, `-d`/`--deleted`, `-o`/`--others`, `-u`/`--unmerged`, `-s`/`--stage`, `--exclude-standard`, `-z`, `-t` |
|
|
150
|
+
34 commands: `init`, `clone`, `fetch`, `push`, `pull`, `add`, `rm`, `mv`, `commit`, `status`, `log`, `show`, `diff`, `blame`, `branch`, `tag`, `checkout`, `switch`, `restore`, `reset`, `merge`, `rebase`, `cherry-pick`, `revert`, `stash`, `remote`, `config`, `bisect`, `clean`, `reflog`, `gc`, `repack`, `rev-parse`, `ls-files`. See [CLI.md](docs/CLI.md) for full usage details.
|
|
317
151
|
|
|
318
152
|
### Transport
|
|
319
153
|
|
|
320
|
-
- **Local paths
|
|
321
|
-
- **Cross-VFS
|
|
322
|
-
- **Smart HTTP
|
|
154
|
+
- **Local paths**: direct filesystem transfer between repositories.
|
|
155
|
+
- **Cross-VFS**: clone, fetch, and push between isolated in-memory filesystems via `resolveRemote`. See [CLIENT.md](docs/CLIENT.md#multi-agent-collaboration).
|
|
156
|
+
- **Smart HTTP**: clone, fetch, and push against real Git servers (e.g. GitHub) via Git Smart HTTP protocol. Auth via `credentials` option or `GIT_HTTP_BEARER_TOKEN` / `GIT_HTTP_USER` + `GIT_HTTP_PASSWORD` env vars.
|
|
323
157
|
|
|
324
158
|
### Internals
|
|
325
159
|
|