Git version control for the iOS Scripting app, powered by isomorphic-git (pure JS, no native binary).
- iOS Scripting projects live in iCloud-synced folders. Letting
.gitsit inside the workdir would dump tens of MB of loose objects into iCloud and slow sync to a crawl. - This skill splits the layout: workdir stays in iCloud,
.gitis moved to the App Group shared container.
<workdir> <App Group>/git-repos/
├── (iCloud-synced project files) ├── repo-map.json ← workdir → repoName
└── (no .git here) └── <repoName>/
├── HEAD
├── objects/
└── refs/
- Gitdir:
FileManager.appGroupDocumentsDirectory/git-repos/<repoName>/ - Workdir: caller-provided absolute path
- Mapping:
git-repos/repo-map.json— created on first command, written only on first map for a workdir or whenrepoNameis explicitly changed (short-circuit; read-only commands never re-write it)
vendor/index.umd.min.js— isomorphic-git v1.38.1 UMD bundle (~258 KB, self-contained)vendor/buffer-bundle.js— npmbuffer@6UMD as globalBufferpolyfillscripts/polyfills.ts— customTextEncoder/TextDecoderfor Scripting's JS runtime- HTTP transport: Scripting
fetch+Data.fromUint8Array()for binary request bodies
isomorphic-git/
├── SKILL.md ← invocation reference (consumed by LLM agents)
├── README.md ← this file (developer reference)
├── schema.json ← input validation for queryparameters
├── spec.md ← internal design notes
├── scripts/
│ ├── git.ts ← skill entry
│ ├── git-auth-page.tsx ← Keychain auth prompt UI (used for push/pull/clone)
│ ├── polyfills.ts ← Buffer/TextEncoder polyfills
│ └── __tests__/ ← test scripts (not loaded at runtime)
│ ├── test-local-git.ts
│ ├── test-auth-page.tsx
│ └── _probe_walk.ts
└── vendor/ ← UMD bundles
For full parameter reference and the per-command quick-reference table, read SKILL.md. The pattern is always:
scripting-ts run <skill_dir>/scripts/git.ts --queryparameters '{"command":"<cmd>", ...}' --timeout <sec>A minimal cycle:
# init → stage all → commit
scripting-ts run <skill_dir>/scripts/git.ts --queryparameters '{"command":"init","dir":"/path/proj","name":"proj"}' --timeout 30
scripting-ts run <skill_dir>/scripts/git.ts --queryparameters '{"command":"add","dir":"/path/proj","filepath":"."}' --timeout 30
scripting-ts run <skill_dir>/scripts/git.ts --queryparameters '{"command":"commit","dir":"/path/proj","message":"init"}' --timeout 30push / pull / clone resolve credentials in this priority:
- Inline —
params.auth = { username, password }(no UI, suitable for scripted / CI flows) - Keychain —
isomorphic_git_username+isomorphic_git_token(auto-populated on first prompt success) - Prompt page —
scripts/git-auth-page.tsxopens, accepts user input, saves to Keychain
- Go to GitHub Settings → Developer settings → Personal access tokens
- Generate a new token with the
reposcope (full control of private repos) - When prompted by the auth page, paste the token; username defaults to
x-access-token
| Provider | Username | Password |
|---|---|---|
| GitHub | x-access-token (or your username) |
PAT with repo scope |
| GitLab | your username | PAT with api scope |
| Bitbucket | your username | App Password with repository:write |
| Generic | HTTP Basic Auth | HTTP Basic Auth |
To clear stored credentials, delete the Keychain entries isomorphic_git_username and isomorphic_git_token.
Test scripts live in scripts/__tests__/ and are never loaded by the main skill entry. Run them ad-hoc:
# Auth page (opens UI; cancel to test the null path)
scripting-ts run <skill_dir>/scripts/__tests__/test-auth-page.tsx --timeout 60
# Local end-to-end (init → add → commit → log → status). DEPRECATED — functionality is now covered by scripts/git.ts.
scripting-ts run <skill_dir>/scripts/__tests__/test-local-git.ts --timeout 60
# Probe which isomorphic-git APIs the UMD bundle exposes
scripting-ts run <skill_dir>/scripts/__tests__/_probe_walk.ts --timeout 60diffworking-tree mode usesgit.statusMatrixfor recursive 3-way comparison (HEAD × index × workdir).diffref-to-ref mode usesgit.walkwith twoTREEwalkers, comparing blob OIDs. A customresolveReflikeresolvesHEAD~N/<ref>^Nsyntax to concrete commit OIDs sinceTREE({ref})doesn't parse relative refs.revertis implemented viaresetIndexto the parent tree + a new commit (isomorphic-git has no native revert).- Stash depends on isomorphic-git's
GitStashManagerreading files with theread(path, 'utf8')shape — our FS adapter'sreadFile(filepath, opts)accepts both string-encoding and object-encoding opts.
- No ref-to-ref text diff (only OID-level change list).
cloneof large or deeply nested repos may exceed practical timeouts on iOS.- The HTTP transport buffers each response body fully in memory before yielding (necessary because Scripting's
fetchreturns a completeData).