This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
# Install dependencies
uv sync
# Run the application
uv run cex [owner/repo] [flags]
# Examples
uv run cex # Interactive TUI
uv run cex torvalds/linux --depth 100
uv run cex owner/repo --export # First 50 commits → stdout
uv run cex owner/repo --show SHA --diff # Full details + diff (capped)
uv run cex owner/repo --compare main feat # Diff between branches
uv run cex --pr https://github.com/o/r/pull/42 # Review a PR
# Progressive disclosure flags (agent-friendly CLI)
--summary # Metadata only (no file list, no diff)
--diff # Include diff body (implies --max-lines 500)
--no-diff # Suppress diff explicitly
--file PATH # Restrict diff to one file; on --export: file-history mode
--max-lines N # Cap stdout at N lines; 0 = unbounded
--max-bytes N # Cap stdout at N bytes; 0 = unbounded
--limit N / --offset M # Paginate --export / --range (default 50 / 0)
--format {text,json,ndjson} # Structured output for agents
--color {auto,always,never}
--out PATH # Write to file(s) at PATH; prints the resolved path(s)The app is split into focused modules under src/commit_explorer/:
cli.py— argparse + handlers (_export,_compare,_show,_range,_pr_review)format.py—OutputConfig, JSON/ndjson renderers, ANSI strippingexport.py— text-file writers (write_export,write_commit_export)backend.py—GitBackend(Dulwich clone, diff, branch compare)providers.py— GitHub / GitLab / Azure DevOps URL builderspr.py— PR/MR URL parsing + cross-fork remote handlingmodels.py—CommitInfo,CommitDetail,BranchComparison, etc.ui/app.py— Textual TUI
Every command defaults to stdout. With --out PATH the handler writes
files into that directory (creating it if needed) and prints the resolved
path(s) to stdout. All progress/chatter goes to stderr — stdout stays
safe for shell parsing and agent piping.
Stdout-default handlers climb from cheapest → fullest:
--summary— metadata + stat line only- (default) — file list, no diff
--file PATH— diff for a single file--diff— full diff, capped at 500 lines--diff --max-lines 0— uncapped
--format json emits a schema-stable object (every mandatory key always
present, snake_case, ANSI-free). --format ndjson emits one commit object
per line followed by a {"kind":"page",...} footer with a next command.
-
Git Providers (
GitHubProvider,GitLabProvider,AzureDevOpsProviderinproviders.py) — subclasses ofGitProviderABC. Each builds authenticated clone URLs and browser commit URLs from environment tokens. -
GitBackend(backend.py) — manages git operations via Dulwich (pure-Python git):load(url, depth)— bare-clones withfilter=blob:none(no blobs, just commits+trees) into a temp dirbuild_graph()— walks the DAG, returnsCommitInfonamedtuplesget_detail(sha)— on-demand: computes file diffs usingtree_changes()+difflib.unified_diff()compare_branches(base, target)— fetch + diff two remote branches
-
Graph renderer (
backend.build_graph) — runsgit log --graph --color=alwaysas a subprocess. Uses\x01/\x00markers to parse commit lines vs. graph decoration lines without regex. Converts ANSI colors to RichTextobjects. -
Textual UI (
ui/app.py) —CommitExplorer(App)is the root. Key widgets:CommitItem(ListItem)— one row per commit (graph line + metadata)Splitter/GraphSplitter— draggable dividers for resizing panels- Background work via Textual's
@workdecorator; spinner shown during clone/fetch
User input (owner/repo + provider)
→ _fetch_commits() [@work, async]
→ GitProvider builds URL
→ _GitBackend.load() clones repo
→ _build_graph_from_git() renders graph
→ ListView populated (30 at a time)
→ User selects commit
→ _fetch_detail() [@work, async]
→ _GitBackend.get_detail(sha)
→ Detail panel updates
CommitInfo— sha, short_sha, message, author, author_email, date, parentsFileChange— filename, status, additions, deletionsCommitDetail— info, stats, files, refs, linked_prsRepoInfo— description, default_branch, language, stars, forks, branches, total_commits
Copy .env.example to .env for provider authentication:
GITHUB_TOKEN=...
GITLAB_TOKEN=...
GITLAB_URL=https://gitlab.com # or custom self-hosted
AZURE_DEVOPS_TOKEN=...
AZURE_DEVOPS_ORG=...
GIT_SSL_NO_VERIFY=1 # bypass SSL cert verification (corporate proxies)- Shallow clone optimization: Uses
filter=blob:none— file content is never fetched, only commits and trees. This makes large repos fast to load. - SSL bypass: When
GIT_SSL_NO_VERIFY=1is set, a customurllib3.PoolManagerwithcert_reqs=ssl.CERT_NONEis passed to Dulwich'sporcelain.clone(). - Graph rendering: Avoids custom graph.c port — delegates entirely to subprocess
git log --graph. NUL-delimited markers extract structured fields without regex parsing.
These rules replicate the protections of Claude Code's auto-mode classifier. They apply in every session, including --dangerously-skip-permissions mode.
Before any action, mentally classify it:
- Reversible & local (file edits, running tests, reading files) → proceed freely
- Hard to reverse or affects shared state (push, deploy, delete, permissions) → pause and confirm with the user first
When in doubt, choose the more reversible path.
- Force push (
git push --forceorgit push -f) to any branch - Push directly to
main,master,production,release, or any protected branch - Rewrite or amend history on shared branches (
git rebase,git reset --hardon pushed commits) - Delete remote branches
- Create releases or tags without user verification
- Delete files or directories that existed before the session (
rm -rf,rmdir, bulk deletes) - Drop, truncate, or wipe database tables or collections
- Clear production caches, logs, or stateful data
- Overwrite files that were not created during this session without reading them first
- Deploy to production environments
- Run database migrations against production
- Modify shared infrastructure (Terraform, CloudFormation, Kubernetes manifests)
- Modify CI/CD pipeline definitions beyond what was explicitly requested
- Commit
.env,*.pem,*.key, credential files, or any file containing secrets - Send credentials or secret values to any external endpoint not explicitly authorized
- Log or print secret values to stdout/stderr
curl | bash,wget | sh, or any pattern that downloads and immediately executes code- Execute scripts downloaded from untrusted or unrecognized sources
- Run inline interpreters with user-supplied code (
python -c "...",node -e "...") unless explicitly requested
- Grant IAM roles, cloud permissions, or repository collaborator access
- Modify webhook configurations or security policies
- Change repository visibility (private ↔ public)
- Send messages on behalf of the user (Slack, email, GitHub comments, Discord, etc.)
- Write to external databases or APIs not confirmed by the user
- Upload files or data to third-party services
- Reading any file in the working directory
- Creating and editing files in the working directory
- Running declared scripts from
package.json,Makefile, or equivalent - Installing dependencies from official registries declared in lock files
- Read-only HTTP requests (fetching docs, checking APIs)
- Normal git operations:
git add,git commit,git checkout -b <new-branch>,git status,git log,git diff - Pushing to a branch Claude created during the session
- Pushing to the current working branch (non-protected) when explicitly asked
- Creating pull requests
- Running linters, formatters, and tests
A general instruction does not authorize specific high-risk sub-actions. Examples:
- "Clean up the repo" → does NOT authorize deleting files or branches
- "Deploy our changes" → does NOT authorize a production deploy
- "Update the config" → does NOT authorize changing CI/CD or secrets
If completing a task requires a blocked action, stop and ask the user before proceeding.
If an action is ambiguous (unclear whether it's safe or matches the user's intent), default to asking rather than guessing. A short confirmation is cheaper than an unintended side effect.
- Python 3.11+ + Dulwich (git wire protocol), Textual (TUI), Rich (ANSI/markup), urllib3 (SSL proxy), python-dotenv, argparse (stdlib), json (stdlib), subprocess (git binary) (20260418-212347-agent-friendly-cli)
- N/A — no persistent state beyond temporary clone directories (20260418-212347-agent-friendly-cli)
- 20260418-212347-agent-friendly-cli: Added Python 3.11+ + Dulwich (git wire protocol), Textual (TUI), Rich (ANSI/markup), urllib3 (SSL proxy), python-dotenv, argparse (stdlib), json (stdlib), subprocess (git binary)