Files
ironclaw/tools-src/github
firat.sertgoz 27d53f5153 docs(skills): code-review v2 + GitHub endpoint fixes + minor text updates (#2528)
* feat(skills): paranoid-architect code-review skill v2

Rewrite the code-review skill from a 6-bullet checklist into a
paranoid-architect workflow that handles both local diffs and GitHub
PRs end-to-end:

- Two input shapes: local `git diff` or `owner/repo N` /
  `github.com/.../pull/N` URLs.
- Step 1 wraps GitHub fetches in `async def` + `FINAL(await ...)` to
  avoid the closure-capture quirk that kept tripping LLMs (see the
  paired codeact preamble update); reads metadata, diff, and files
  via three sequential awaits instead of `asyncio.gather`.
- Step 2 reads each changed file in full (raw media type, no base64
  module needed) so reviews account for surrounding context.
- Step 3 runs the change through six lenses: correctness, edge cases,
  security (with a real adversarial checklist), test coverage, docs,
  architecture.
- Step 4 renders findings as a severity table and asks which to post.
- Step 5 posts line-level comments via the PR comments endpoint with
  the captured head SHA, falling back to issue comments for
  multi-file findings.

Bumps `requires.skills` to include `github` so the activation pulls
in the GitHub API recipes via the chain-loader.

Adds a live e2e test (`e2e_live_code_review.rs`) plus a recorded
trace fixture (PR #2483) so the workflow is replayable without
hitting GitHub.

* docs(github): clarify search endpoints, response envelope, @me queries

LLMs kept inventing a `search_issues` action and looping over
`/repos/{owner}/{repo}/pulls` for "my PRs" queries. Clarify the
GitHub tool surface in three places:

- `tools-src/github/src/lib.rs` and `registry/tools/github.json`:
  enumerate the three real search actions and call out that
  `search_issues_pull_requests` covers both. Add the canonical
  `is:pr author:@me sort:updated-desc` recipe for cross-repo "my PRs".

- `skills/github/SKILL.md`: add an "Authenticated User & Cross-Repo
  Queries" section with copy-paste recipes for `@me`, the search
  endpoints with proper URL encoding, and the response-envelope
  contract (`body` is parsed JSON for application/json, raw `str` for
  diff endpoints — never call `json.loads()` on it, never write
  `.get("body", body)` as a fallback).

* fix: resolve CI failures — clippy useless_conversion + missing test harness methods

- Remove `.into_iter()` on `details` in catalog.rs (clippy::useless_conversion)
- Add `with_skills_dir` to `LiveTestHarnessBuilder` for e2e_live_code_review test
- Add `active_skill_names` to `TestRig` extracting from SkillActivated status events

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(skills): address zmanian + gemini review — URL encoding, multi-line comments, description trimming (#2528)

- URL-encode file paths in GitHub API content URLs
- Add start_line/start_side to multi-line comment example
- Add 'locally' keyword override for mode detection
- Trim overly long schema descriptions
- Remove duplicated /search/issues note from Common Mistakes
- Fetch PR title from trace fixture instead of hard-coding

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix(test): propagate skills_dir into TestRig config (#2528)

LiveTestHarnessBuilder::with_skills_dir() stored a PathBuf but only
used it as an is_some() flag — the actual SkillRegistry always pointed
at an empty temp directory. Now the stored path flows through
TestRigBuilder::with_skills_dir() into config.skills.local_dir and
the SkillRegistry constructor.

Also generalizes the hardcoded nearai/ironclaw repo name in the
github skill's response-handling example to {owner}/{repo}.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Illia Polosukhin <ilblackdragon@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 23:11:59 +09:00
..

GitHub Tool for IronClaw

WASM tool for GitHub integration. It covers repositories, issues, pull requests, search, branches, file reads and writes, releases, and workflows.

Features

  • Repositories - Get repo details, list user repos, create repositories
  • Search - Search repositories, code, and issues/PRs
  • Branches - List branches and create new branches from an existing ref
  • Issues - List/create/get issues, list/add issue comments
  • Pull Requests - List/create/get PRs, review files, create reviews, list/reply review comments, merge PRs
  • File Content - Read files and create/update/delete repository files
  • Releases - List releases and create new releases
  • Workflows - Trigger GitHub Actions, check run status

Setup

  1. Create a GitHub Personal Access Token at https://github.com/settings/tokens

  2. Required scopes: repo, workflow, read:org

  3. Store the token:

    ironclaw secret set github_token YOUR_TOKEN
    

Usage Examples

Get Repository Info

{
  "action": "get_repo",
  "owner": "nearai",
  "repo": "ironclaw"
}

Create Repository

{
  "action": "create_repo",
  "name": "infra-playground",
  "description": "Scratch repo for release automation",
  "private": true,
  "auto_init": true
}

List Open Issues

{
  "action": "list_issues",
  "owner": "nearai",
  "repo": "ironclaw",
  "state": "open",
  "limit": 10
}

Create Issue

{
  "action": "create_issue",
  "owner": "nearai",
  "repo": "ironclaw",
  "title": "Bug: Something is broken",
  "body": "Detailed description...",
  "labels": ["bug", "help wanted"]
}

List Pull Requests

{
  "action": "list_pull_requests",
  "owner": "nearai",
  "repo": "ironclaw",
  "state": "open",
  "limit": 5
}

Search Code

{
  "action": "search_code",
  "query": "repo:nearai/ironclaw tool_info",
  "limit": 5
}

Search Issues and Pull Requests

{
  "action": "search_issues_pull_requests",
  "query": "repo:nearai/ironclaw is:pr label:bug",
  "limit": 10
}

Review PR

{
  "action": "create_pr_review",
  "owner": "nearai",
  "repo": "ironclaw",
  "pr_number": 42,
  "body": "LGTM! Great work.",
  "event": "APPROVE"
}

Create Pull Request

{
  "action": "create_pull_request",
  "owner": "nearai",
  "repo": "ironclaw",
  "title": "feat: add event-driven routines",
  "head": "feat/event-routines",
  "base": "main",
  "body": "Implements system_event trigger + event_emit tool."
}

Merge Pull Request

{
  "action": "merge_pull_request",
  "owner": "nearai",
  "repo": "ironclaw",
  "pr_number": 42,
  "merge_method": "squash"
}

List Issue Comments

{
  "action": "list_issue_comments",
  "owner": "nearai",
  "repo": "ironclaw",
  "issue_number": 42,
  "limit": 10
}

Add Issue Comment

{
  "action": "create_issue_comment",
  "owner": "nearai",
  "repo": "ironclaw",
  "issue_number": 42,
  "body": "Thanks for reporting this!"
}

List PR Review Comments

{
  "action": "list_pull_request_comments",
  "owner": "nearai",
  "repo": "ironclaw",
  "pr_number": 42,
  "limit": 30
}

Reply to PR Review Comment

{
  "action": "reply_pull_request_comment",
  "owner": "nearai",
  "repo": "ironclaw",
  "comment_id": 123456789,
  "body": "Fixed in the latest commit."
}

Get PR Reviews

{
  "action": "get_pull_request_reviews",
  "owner": "nearai",
  "repo": "ironclaw",
  "pr_number": 42
}

Get Combined Status

{
  "action": "get_combined_status",
  "owner": "nearai",
  "repo": "ironclaw",
  "ref": "main"
}

Get File Content

{
  "action": "get_file_content",
  "owner": "nearai",
  "repo": "ironclaw",
  "path": "README.md",
  "ref": "main"
}

Create or Update a File

{
  "action": "create_or_update_file",
  "owner": "nearai",
  "repo": "ironclaw",
  "path": "docs/example.txt",
  "message": "docs: add example",
  "content": "Hello from IronClaw"
}

When updating an existing file, include the current blob sha.

Delete a File

{
  "action": "delete_file",
  "owner": "nearai",
  "repo": "ironclaw",
  "path": "docs/example.txt",
  "message": "docs: remove example",
  "sha": "0123456789abcdef0123456789abcdef01234567"
}

List Branches

{
  "action": "list_branches",
  "owner": "nearai",
  "repo": "ironclaw",
  "limit": 20
}

Create Branch

{
  "action": "create_branch",
  "owner": "nearai",
  "repo": "ironclaw",
  "branch": "feature/github-tool-audit",
  "from_ref": "main"
}

List Releases

{
  "action": "list_releases",
  "owner": "nearai",
  "repo": "ironclaw",
  "limit": 10
}

Create Release

{
  "action": "create_release",
  "owner": "nearai",
  "repo": "ironclaw",
  "tag_name": "v1.2.3",
  "name": "v1.2.3",
  "generate_release_notes": true
}

Trigger Workflow

{
  "action": "trigger_workflow",
  "owner": "nearai",
  "repo": "ironclaw",
  "workflow_id": "ci.yml",
  "ref": "main",
  "inputs": {
    "environment": "staging"
  }
}

Check Workflow Runs

{
  "action": "get_workflow_runs",
  "owner": "nearai",
  "repo": "ironclaw",
  "limit": 5
}

List Workflow Runs (Pagination)

{
  "action": "get_workflow_runs",
  "owner": "nearai",
  "repo": "ironclaw",
  "limit": 5,
  "page": 2
}

Error Handling

Errors are returned as strings in the error field of the response.

Rate Limit Exceeded

When the GitHub API rate limit is exceeded (and retries fail), you might see:

GitHub API error 429: { "message": "API rate limit exceeded for user ID ...", ... }

The tool automatically logs warnings when the rate limit is low (<10 remaining) and retries on 429/5xx errors.

Invalid Parameters

Invalid event: 'INVALID'. Must be one of: APPROVE, REQUEST_CHANGES, COMMENT

Missing Token

GitHub token not found in secret store. Set it with: ironclaw secret set github_token <token>...

Troubleshooting

"GitHub API error 404: Not Found"

  • Check that the owner and repo are correct.
  • Ensure the github_token has access to the repository (especially for private repos).
  • Verify the token scopes include repo and read:org.

"GitHub API error 401: Bad credentials"

  • The token might be invalid or expired.
  • Update the token: ironclaw secret set github_token NEW_TOKEN.

Rate Limiting

  • The tool logs a warning when remaining requests drop below 10.
  • Check logs for "GitHub API rate limit low".
  • If you hit the limit, wait for the reset time (usually 1 hour).

Building

cd tools-src/github
cargo build --target wasm32-wasi --release

License

MIT/Apache-2.0