Coding assistants write the code. A Submilli agent more often needs to
read it. An agent on the support line hears about a bug or a feature
request, and the fastest way to triage it is the repository itself. The
agent finds where the feature lives and says how deep the change goes.
Repositories also hold more than code. Notes and memory kept in Git get
history, diffs, and review for free, so some memory frameworks store an
agent’s memory that way. In a program, submilli:git does the repository
work and submilli:code the finding and editing, both inside the
program’s filesystem. The Blueprint decides which repository, which
directory, and whether the program may commit at all.
This guide shows you how to let a program clone a repository, search and
edit it, and commit. The example clones GitHub’s Hello-World repository
into /repo. Substitute your remote and paths.
Start from an empty Blueprint
Section titled “Start from an empty Blueprint”submilli blueprint init coder✓ created blueprint.yaml (name: coder)Set the identity
Section titled “Set the identity”submilli:git is off until the Blueprint gives it an identity, because
the Blueprint, not the program, authors the commits it makes. The
module speaks HTTPS and not SSH, so the identity also carries the
username a remote will ask for:
submilli blueprint git set --name "Support Agent" --email agent@acme.example --username agentConfigured Git in blueprint.yaml. Configure grants with `submilli blueprint capability add`.git: identity: name: Support Agent email: agent@acme.example username: agentWhen a remote asks for credentials, Submilli sends the secret named
GIT_TOKEN with that username, and the program never sees it. Declare it
and put the value in the store. A public repository never asks, and the
token goes unused:
submilli blueprint secret add GIT_TOKEN --store git_tokensubmilli secret put git_token✓ declared secret 'GIT_TOKEN' (store: git_token) in blueprint.yamlValue for 'git_token': [hidden]Stored secret 'git_token'If you want the session recorded in the author, a value may include a
variable, as in --name 'Support Agent (${vars.customerId})'. Single
quotes keep the shell from expanding it. submilli blueprint git show
prints the identity and whether GIT_TOKEN is declared, without the
value. git remove drops the block and leaves the secret and the rules in place.
What programs can do with it
Section titled “What programs can do with it”A program works on a repository through the Repository class of
submilli:git:
submilli docs submilli:gitsubmilli:git — Capability-controlled VFS repositories: history, staging, commits, branches and HTTPS fetch.…class Repository { static clone(url: string, path: string, options?: null | { branch?: string }): Repository; static init(path: string, options?: null | { branch?: string }): Repository; static open(path: string): Repository; add(paths: string[]): void; commit(message: string): string; status(): { branch: string | null; clean: boolean; entries: { … }[] }; log(options?: null | { limit?: number; offset?: number }): { commits: { … }[]; nextOffset: number | null }; diff(options?: null | { from?: string; mode?: string; to?: string }): { binaryPaths: string[]; patch: string }; fetch(remote?: string, branch?: string): { branches: string[] }; pull(remote?: string, branch?: string): { current: string; previous: string }; …}Git has four capabilities:
submilli blueprint capability list submilli:gitsubmilli:git git.init — Create a local repository and its VFS directory fields: path: string example filter: path == "/repo" git.clone — Clone an HTTPS repository into a VFS directory fields: path: string, remoteName: string, remote: string, branch: string example filter: path == "/repo" and remote == "https://github.com/acme/project.git" git.fetch — Fetch or pull HTTPS remote branches into an existing repository fields: path: string, remoteName: string, remote: string, branch: string example filter: path == "/repo" and remote == "https://github.com/acme/project.git" git.commit — Commit staged changes with blueprint identity fields: path: string, branch: string example filter: path == "/repo" and branch == "main"The workspace tools
Section titled “The workspace tools”submilli:code finds and changes code. It has the workspace tools a
coding agent expects, such as numbered reads, search, tree, and anchored
edits that return a diff:
submilli docs submilli:codesubmilli:code — Workspace tools: numbered reads, search, glob, tree, anchored edits and unified diffs.…function read(path: string, offset?: number, limit?: number): { lines: { line: number; text: string }[]; path: string; truncated: boolean };function search(pattern: string, options?: null | { caseSensitive?: boolean; context?: number; exclude?: string[]; include?: string[]; limit?: number; mode?: string; path?: string }): { … };function tree(path: string, depth?: number): { entries: { depth: number; kind: string; modifiedAt: number; path: string }[]; truncated: boolean };function edit(path: string, oldString: string, newString: string, replaceAll?: boolean, nearLine?: number): { changed: boolean; diagnostics: { … }[]; diff: string; success: boolean };…It has no capabilities of its own. Reads use fs.read, navigation uses
fs.list and fs.stat, and edits use fs.read and fs.write.
Grant the operations
Section titled “Grant the operations”Let the program clone one repository into /repo and commit there, and
read, list, and edit under it:
submilli blueprint capability add git.clone \ --filter 'path == "/repo" and remote == "https://github.com/octocat/Hello-World.git"'submilli blueprint capability add git.commit --filter 'path == "/repo"'submilli blueprint capability add fs.read --filter 'path == "/repo" or path glob "/repo/*"'submilli blueprint capability add fs.list --filter 'path == "/repo" or path glob "/repo/*"'submilli blueprint capability add fs.write --filter 'path glob "/repo/*"'submilli blueprint capability add fs.stat✓ added allow git.clone (filter: path == "/repo" and remote == "https://github.com/octocat/Hello-World.git") to caller 'main' in blueprint.yaml Clone an HTTPS repository into a VFS directory filter fields: path: string, remoteName: string, remote: string, branch: string✓ added allow git.commit (filter: path == "/repo") to caller 'main' in blueprint.yaml Commit staged changes with blueprint identity filter fields: path: string, branch: string✓ added allow fs.read (filter: path == "/repo" or path glob "/repo/*") to caller 'main' in blueprint.yaml Read files and code workspace content (including search and ignore rules) filter fields: path: string, length: number, chunkSize: number, recursive: boolean✓ added allow fs.list (filter: path == "/repo" or path glob "/repo/*") to caller 'main' in blueprint.yaml List directory entries (including code search, glob and tree) filter fields: path: string, recursive: boolean✓ added allow fs.write (filter: path glob "/repo/*") to caller 'main' in blueprint.yaml Create, write, append, or apply code edits to files filter fields: path: string, length: number, max_bytes: number, diff: string✓ added allow fs.stat to caller 'main' in blueprint.yaml Inspect metadata (including code workspace discovery) filter fields: path: string, recursive: booleanEach operation needs its own rule and no other. git.clone creates and
fills /repo with no fs rule. Reading history, staging, creating or
switching branches, and adding remotes need no rule at all. fs.stat is
left unfiltered because the workspace tools look for ignore files up to
the root before a search, and stat reveals only metadata. remote is
the full HTTPS URL. Refer to permissions
for how it is normalized and for filtering on branch.
If the program should fetch or pull later, grant git.fetch for the same
path:
submilli blueprint capability add git.fetch --filter 'path == "/repo"'✓ added allow git.fetch (filter: path == "/repo") to caller 'main' in blueprint.yaml Fetch or pull HTTPS remote branches into an existing repository filter fields: path: string, remoteName: string, remote: string, branch: stringRun a program
Section titled “Run a program”Create review.ts. It clones the repository, searches it for the text a
customer mentioned, and records what it found in a commit:
import { Repository } from "submilli:git";import * as code from "submilli:code";
function main(): string { const repo = Repository.clone("https://github.com/octocat/Hello-World.git", "/repo", { branch: "master" }); const hits = code.search("Hello", { path: "/repo" }).matches.length; const edit = code.edit("/repo/README", "Hello World!", "Hello World! Reviewed by the support agent."); repo.add(["."]); const commit = repo.commit("Note the review"); return `${hits} match, committed ${commit.slice(0, 7)}\n${edit.diff}`;}submilli run --blueprint blueprint.yaml review.ts1 match, committed 3324dc2--- a+++ b@@ -1,1 +1,1 @@-Hello World!+Hello World! Reviewed by the support agent.The repository lives in the program’s filesystem, so the vfs mode
decides how long the commit lasts. Refer to Keep files and
state.
The result
Section titled “The result”kind: blueprintname: codersecrets: GIT_TOKEN: store: git_tokengit: identity: name: Support Agent email: agent@acme.example username: agentdefault: denypermissions: main: - capability: git.clone filter: path == "/repo" and remote == "https://github.com/octocat/Hello-World.git" action: allow - capability: git.commit filter: path == "/repo" action: allow - capability: fs.read filter: path == "/repo" or path glob "/repo/*" action: allow - capability: fs.list filter: path == "/repo" or path glob "/repo/*" action: allow - capability: fs.write filter: path glob "/repo/*" action: allow - capability: fs.stat action: allow