Summary
Give the agent its own GitHub identity so comments appear as my-agent[bot] while commits remain attributed to the operator. Uses the GitHub App manifest flow for zero-config setup.
Motivation
Currently all GitHub activity (comments, commits) uses the operator's PAT, so everything appears as the operator. Bot status comments ("started run...", "implemented in...") should be visually distinct from human comments in PR threads.
Design
Two identity channels
| Action |
Token |
Shown as |
| Git push / commits |
Operator PAT (unchanged) |
Operator |
| Comments / status updates |
GitHub App installation token |
<bot-name>[bot] |
Fallback when no bot is configured
If no bot credentials exist, all API calls use the operator PAT — current behavior, zero change.
func (s *Server) commentClient() *github.Client {
if s.botClient != nil {
return s.botClient
}
return s.defaultClient
}
Implementation
1. rascal init --bot <name> (optional flag)
When present, adds to the existing init flow:
- Build GitHub App manifest (name, permissions, webhook URL — all derived from other flags)
- Open browser to
github.com/settings/apps/new?manifest=<JSON>
- User clicks "Create" (one click, no manual config)
- Catch redirect on temporary local HTTP server
- Store app ID + private key in credential store
- Install app on
--repo target
- Set
RASCAL_GITHUB_APP_ID, RASCAL_GITHUB_APP_PRIVATE_KEY, RASCAL_BOT_NAME in server env during deploy
When absent, nothing changes.
2. rascal bot subcommand (post-init management)
rascal bot create <name> # create GitHub App on already-running instance
rascal bot install <repo> # install app on additional repos
rascal bot status # show current bot config
rascal bot remove # revert to PAT-only
3. Config additions
Server env vars:
RASCAL_GITHUB_APP_ID — GitHub App ID
RASCAL_GITHUB_APP_PRIVATE_KEY — path or value of private key
RASCAL_BOT_NAME — display name in comment text (defaults to "Rascal")
ServerConfig fields:
GitHubAppID, GitHubAppPrivateKey, BotName
4. Dual GitHub client in orchestrator
- Construct a bot client from app credentials when present (handles hourly token refresh)
- Route all comment-posting calls through
commentClient() fallback
- Git push paths remain on operator PAT
5. Replace hardcoded "Rascal" in comment text
In internal/runsummary/runsummary.go, parameterize all instances of "Rascal" with BotName (resolved from config, defaults to "Rascal").
6. Webhook filtering
Auto-derive BotLogin from the app's slug (<name>[bot]) when a GitHub App is configured, so the bot ignores its own comment events.
Key files
cmd/rascal/main.go — init command, flag handling
cmd/rascal/infra.go — deploy flow, env upload
internal/config/config.go — ServerConfig
internal/orchestrator/service.go — Server struct, client setup
internal/orchestrator/notifications.go — comment posting
internal/orchestrator/webhook.go — isBotActor() filtering
internal/runsummary/runsummary.go — hardcoded "Rascal" text
internal/github/client.go — GitHub API client
App manifest permissions
{
"name": "<bot-name>",
"default_permissions": {
"contents": "write",
"issues": "write",
"pull_requests": "write"
},
"default_events": ["issues", "issue_comment", "pull_request", "pull_request_review", "pull_request_review_comment"]
}
Summary
Give the agent its own GitHub identity so comments appear as
my-agent[bot]while commits remain attributed to the operator. Uses the GitHub App manifest flow for zero-config setup.Motivation
Currently all GitHub activity (comments, commits) uses the operator's PAT, so everything appears as the operator. Bot status comments ("started run...", "implemented in...") should be visually distinct from human comments in PR threads.
Design
Two identity channels
<bot-name>[bot]Fallback when no bot is configured
If no bot credentials exist, all API calls use the operator PAT — current behavior, zero change.
Implementation
1.
rascal init --bot <name>(optional flag)When present, adds to the existing init flow:
github.com/settings/apps/new?manifest=<JSON>--repotargetRASCAL_GITHUB_APP_ID,RASCAL_GITHUB_APP_PRIVATE_KEY,RASCAL_BOT_NAMEin server env during deployWhen absent, nothing changes.
2.
rascal botsubcommand (post-init management)3. Config additions
Server env vars:
RASCAL_GITHUB_APP_ID— GitHub App IDRASCAL_GITHUB_APP_PRIVATE_KEY— path or value of private keyRASCAL_BOT_NAME— display name in comment text (defaults to "Rascal")ServerConfig fields:
GitHubAppID,GitHubAppPrivateKey,BotName4. Dual GitHub client in orchestrator
commentClient()fallback5. Replace hardcoded "Rascal" in comment text
In
internal/runsummary/runsummary.go, parameterize all instances of "Rascal" withBotName(resolved from config, defaults to "Rascal").6. Webhook filtering
Auto-derive
BotLoginfrom the app's slug (<name>[bot]) when a GitHub App is configured, so the bot ignores its own comment events.Key files
cmd/rascal/main.go— init command, flag handlingcmd/rascal/infra.go— deploy flow, env uploadinternal/config/config.go— ServerConfiginternal/orchestrator/service.go— Server struct, client setupinternal/orchestrator/notifications.go— comment postinginternal/orchestrator/webhook.go—isBotActor()filteringinternal/runsummary/runsummary.go— hardcoded "Rascal" textinternal/github/client.go— GitHub API clientApp manifest permissions
{ "name": "<bot-name>", "default_permissions": { "contents": "write", "issues": "write", "pull_requests": "write" }, "default_events": ["issues", "issue_comment", "pull_request", "pull_request_review", "pull_request_review_comment"] }