Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Git protocol implementation patterns using gitoxide for Guts repository operations
.claude/skills/aiskillstore-git-protocol/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-13 | ✗→✓ | ▲ Improved | 50% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 36% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 20% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 59% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 54% | 0% |
You are implementing Git-compatible repository operations using gitoxide (gix).
Gitoxide is a pure-Rust Git implementation. Key crates:
gix: High-level Git operationsgix-object: Git object typesgix-hash: Object ID handlinggix-pack: Pack file operationsgix-transport: Git protocol transportrustuse gix::Repository; use std::path::Path; pub async fn open_or_create(path: &Path) -> Result<Repository> { match gix::open(path) { Ok(repo) => Ok(repo), Err(_) => { // Create new bare repository gix::init_bare(path)? } } }
rustuse gix::ObjectId; use gix::object::Kind; pub struct ObjectStore { repo: Repository, } impl ObjectStore { pub fn get_object(&self, id: &ObjectId) -> Result<Object> { let object = self.repo.find_object(id)?; match object.kind { Kind::Blob => self.decode_blob(object), Kind::Tree => self.decode_tree(object), Kind::Commit => self.decode_commit(object), Kind::Tag => self.decode_tag(object), } } pub fn write_blob(&self, data: &[u8]) -> Result<ObjectId> { let id = self.repo.write_blob(data)?; Ok(id) } }
rustuse gix::actor::Signature; pub struct CommitBuilder<'a> { repo: &'a Repository, tree: ObjectId, parents: Vec<ObjectId>, message: String, author: Signature, } impl<'a> CommitBuilder<'a> { pub fn new(repo: &'a Repository) -> Self { let now = gix::date::Time::now_local_or_utc(); let default_sig = Signature { name: "Guts User".into(), email: "user@guts.local".into(), time: now, }; Self { repo, tree: ObjectId::null(), parents: vec![], message: String::new(), author: default_sig, } } pub fn tree(mut self, tree: ObjectId) -> Self { self.tree = tree; self } pub fn parent(mut self, parent: ObjectId) -> Self { self.parents.push(parent); self } pub fn message(mut self, msg: impl Into<String>) -> Self { self.message = msg.into(); self } pub fn commit(self) -> Result<ObjectId> { let commit = gix::objs::CommitRef { tree: self.tree, parents: self.parents.into(), author: self.author.clone(), committer: self.author, encoding: None, message: self.message.into(), extra_headers: vec![], }; let id = self.repo.write_object(&commit)?; Ok(id) } }
rustuse axum::{Router, routing::post, extract::Path}; pub fn git_http_router() -> Router { Router::new() .route("/:owner/:repo/git-upload-pack", post(upload_pack)) .route("/:owner/:repo/git-receive-pack", post(receive_pack)) .route("/:owner/:repo/info/refs", get(info_refs)) } async fn upload_pack( Path((owner, repo)): Path<(String, String)>, body: Bytes, ) -> Result<impl IntoResponse> { let repo = get_repository(&owner, &repo).await?; // Parse want/have lines let request = parse_upload_pack_request(&body)?; // Generate packfile with requested objects let packfile = generate_packfile(&repo, &request).await?; Ok(( [(header::CONTENT_TYPE, "application/x-git-upload-pack-result")], packfile, )) } async fn receive_pack( Path((owner, repo)): Path<(String, String)>, body: Bytes, ) -> Result<impl IntoResponse> { let repo = get_repository(&owner, &repo).await?; // Parse commands and packfile let (commands, packfile) = parse_receive_pack(&body)?; // Verify permissions verify_push_permissions(&owner, &repo).await?; // Apply packfile apply_packfile(&repo, &packfile).await?; // Update refs for cmd in commands { update_ref(&repo, &cmd).await?; } Ok(( [(header::CONTENT_TYPE, "application/x-git-receive-pack-result")], "ok\n", )) }
rustuse gix::pack; pub async fn generate_packfile( repo: &Repository, wants: &[ObjectId], haves: &[ObjectId], ) -> Result<Vec<u8>> { // Find all objects to include let objects = repo.rev_walk(wants) .sorting(Sorting::ByCommitTimeNewestFirst) .ancestors() .filter(|id| !haves.contains(id)) .collect::<Vec<_>>(); // Create pack file let mut pack_data = Vec::new(); let mut writer = pack::data::output::bytes::Writer::new(&mut pack_data); for oid in objects { let object = repo.find_object(oid)?; writer.write_entry(object)?; } writer.finish()?; Ok(pack_data) }
rustpub struct RefStore { repo: Repository, } impl RefStore { pub fn list_refs(&self) -> Result<Vec<(String, ObjectId)>> { let refs = self.repo.references()?; refs.all()? .map(|r| { let r = r?; Ok((r.name().to_string(), r.target().id())) }) .collect() } pub fn update_ref(&self, name: &str, new_id: ObjectId, old_id: Option<ObjectId>) -> Result<()> { let ref_log_message = format!("guts: update {}", name); if let Some(old) = old_id { // Atomic compare-and-swap self.repo .reference(name, new_id, PreviousValue::MustExistAndMatch(old.into()))?; } else { // Create new ref self.repo .reference(name, new_id, PreviousValue::MustNotExist)?; } Ok(()) } pub fn get_head(&self) -> Result<ObjectId> { let head = self.repo.head_commit()?; Ok(head.id) } }
rust/// Extended commit with Guts-specific metadata #[derive(Debug, Clone)] pub struct GutsCommit { /// Standard Git commit pub git_commit: gix::Commit, /// Ed25519 signature of commit hash pub signature: Signature, /// Signer's public key pub signer: PublicKey, /// Consensus round when commit was accepted pub consensus_round: Option<u64>, } impl GutsCommit { pub fn verify(&self) -> Result<bool> { let commit_hash = self.git_commit.id.as_bytes(); self.signer.verify(commit_hash, &self.signature) } }
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-03 | pass→pass | 13,791 | 11,092 | -20% | 1 | 1 | 0% | 2,689 | 4,139 | +54% | 0 | 0 | — |
case-04 | pass→pass | 16,493 | 13,375 | -19% | 1 | 1 | 0% | 3,262 | 4,617 | +42% | 0 | 0 | — |
case-01 | pass→pass | 19,985 | 9,153 | -54% | 1 | 1 | 0% | 3,777 | 3,597 | -5% | 0 | 0 | — |
case-02 | fail→fail | 20,766 | 12,869 | -38% | 1 | 1 | 0% | 4,229 | 4,608 | +9% | 0 | 0 | — |
case-05 | pass→pass | 11,137 | 4,891 | -56% | 1 | 1 | 0% | 1,797 | 2,678 | +49% | 0 | 0 | — |
case-06 | pass→pass | 13,064 | 10,928 | -16% | 1 | 1 | 0% | 2,502 | 4,052 | +62% | 0 | 0 | — |
case-07 | pass→pass | 7,308 | 1,958 | -73% | 1 | 1 | 0% | 1,377 | 2,260 | +64% | 0 | 0 | — |
case-08 | pass→pass | 12,246 | 4,008 | -67% | 1 | 1 | 0% | 2,294 | 2,586 | +13% | 0 | 0 | — |
case-09 | pass→pass | 16,349 | 9,856 | -40% | 1 | 1 | 0% | 2,699 | 3,509 | +30% | 0 | 0 | — |
case-10 | fail→fail | 15,110 | 9,809 | -35% | 1 | 1 | 0% | 2,754 | 3,576 | +30% | 0 | 0 | — |
case-11 | fail→fail | 14,244 | 8,364 | -41% | 1 | 1 | 0% | 2,611 | 3,465 | +33% | 0 | 0 | — |
case-12 | pass→pass | 8,997 | 5,215 | -42% | 1 | 1 | 0% | 1,486 | 2,796 | +88% | 0 | 0 | — |
case-13 | fail→pass | 14,120 | 9,244 | -35% | 1 | 1 | 0% | 2,398 | 3,591 | +50% | 0 | 0 | — |
case-14 | fail→pass | 9,465 | 2,243 | -76% | 1 | 1 | 0% | 1,657 | 2,261 | +36% | 0 | 0 | — |
case-15 | fail→pass | 12,886 | 2,456 | -81% | 1 | 1 | 0% | 2,014 | 2,420 | +20% | 0 | 0 | — |
case-16 | fail→pass | 8,675 | 1,588 | -82% | 1 | 1 | 0% | 1,363 | 2,171 | +59% | 0 | 0 | — |
case-17 | pass→pass | 16,009 | 11,387 | -29% | 1 | 1 | 0% | 2,669 | 3,809 | +43% | 0 | 0 | — |
case-18 | pass→pass | 13,590 | 7,483 | -45% | 1 | 1 | 0% | 2,137 | 3,206 | +50% | 0 | 0 | — |
case-19 | pass→pass | 14,885 | 8,564 | -42% | 1 | 1 | 0% | 2,417 | 3,354 | +39% | 0 | 0 | — |
case-20 | pass→pass | 8,582 | 6,958 | -19% | 1 | 1 | 0% | 1,452 | 3,131 | +116% | 0 | 0 | — |
case-21 | pass→pass | 14,164 | 12,271 | -13% | 1 | 1 | 0% | 2,541 | 4,252 | +67% | 0 | 0 | — |
case-22 | pass→pass | 4,353 | 4,265 | -2% | 1 | 1 | 0% | 819 | 2,690 | +228% | 0 | 0 | — |
case-23 | pass→pass | 17,133 | 15,271 | -11% | 1 | 1 | 0% | 3,369 | 4,901 | +45% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +17 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.