add AGENTS.md and update README.md
This commit is contained in:
220
AGENTS.md
Normal file
220
AGENTS.md
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
## Protected README preamble
|
||||||
|
|
||||||
|
The notice at the very top of `README.md` stating that the entire repository is
|
||||||
|
AI-generated, including the adjacent placeholder for the repository owner's
|
||||||
|
personal comments, is intentional and permanent.
|
||||||
|
|
||||||
|
**Do not remove, replace, relocate, soften, or rewrite that preamble or its
|
||||||
|
owner-comment placeholder.** Only the repository owner may fill in or edit the
|
||||||
|
placeholder. Changes elsewhere in the README must preserve this section
|
||||||
|
verbatim and keep it before the project title.
|
||||||
|
|
||||||
|
## Repository purpose
|
||||||
|
|
||||||
|
`diple` is a keyboard-first terminal UI for people receiving GitHub pull
|
||||||
|
request reviews. It is a Go 1.24 application built with Bubble Tea and
|
||||||
|
Lip Gloss. It uses GitHub's GraphQL and REST APIs, authenticates through the
|
||||||
|
GitHub CLI or token environment variables, and keeps optional cache, draft,
|
||||||
|
read-state, and local-AI data on disk.
|
||||||
|
|
||||||
|
The module path is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
git.pablu.de/Pablu/diple
|
||||||
|
```
|
||||||
|
|
||||||
|
The application is one `package main`. There is no internal package hierarchy,
|
||||||
|
so keep new code close to the feature it serves and avoid introducing
|
||||||
|
abstractions without a concrete second use.
|
||||||
|
|
||||||
|
## Product boundaries
|
||||||
|
|
||||||
|
- The primary user is the PR author or assignee responding to a review, not the
|
||||||
|
reviewer submitting one.
|
||||||
|
- Reading must remain useful when some GitHub subsections fail or cached data
|
||||||
|
is temporarily stale.
|
||||||
|
- Mutations must be explicit, permission-aware, confirmed where destructive,
|
||||||
|
and protected against stale PR heads where applicable.
|
||||||
|
- Local AI findings and discussions are local-only. They must never be
|
||||||
|
published to GitHub implicitly.
|
||||||
|
- AI providers must not receive local checkout contents. Current AI context
|
||||||
|
comes from authenticated GitHub PR data and filtered diffs.
|
||||||
|
- Never run code, hooks, tools, or repository commands on behalf of an AI
|
||||||
|
provider. Preserve the hardened, tool-free provider boundary.
|
||||||
|
- The UI is keyboard-first. Similar actions should use the same configurable
|
||||||
|
keybinding groups across screens.
|
||||||
|
- Narrow terminals, wrapped content, Unicode grapheme clusters, no-color mode,
|
||||||
|
and high-contrast mode are supported behavior, not optional polish.
|
||||||
|
|
||||||
|
## Important files
|
||||||
|
|
||||||
|
- `main.go`: startup, configuration application, service wiring, persistence,
|
||||||
|
and Bubble Tea program creation.
|
||||||
|
- `cli.go`: CLI help and Bash, Zsh, and Fish completion generators.
|
||||||
|
- `config.go`: TOML schema, defaults, lookup paths, and validation.
|
||||||
|
- `keybindings.go`: configurable key groups, defaults, help labels, and
|
||||||
|
contextual conflict validation.
|
||||||
|
- `github.go`: GitHub queries, pagination, mutations, capabilities, rate-limit
|
||||||
|
reporting, and service interfaces.
|
||||||
|
- `cache.go`: immediate cached reads, offline fallback, content-aware writes,
|
||||||
|
and bounded pruning.
|
||||||
|
- `tui.go`: main application state, updates, screens, rendering, refresh
|
||||||
|
coordination, and contextual help.
|
||||||
|
- `pr_editor.go`, `text_editor.go`, `branch_completion.go`: PR metadata editor,
|
||||||
|
reusable text editing, Vim-style motions/visual mode, and target-branch
|
||||||
|
completion.
|
||||||
|
- `markdown.go`, `markdown_editor_highlight.go`: GitHub-flavored comment
|
||||||
|
rendering and non-destructive editor highlighting.
|
||||||
|
- `highlight.go`, `suggestions.go`: syntax-highlighted diff hunks and GitHub
|
||||||
|
suggestion previews.
|
||||||
|
- `theme.go`: built-in, custom, high-contrast, and no-color palettes.
|
||||||
|
- `health.go`: component health, stable status, rate limits, and session event
|
||||||
|
history.
|
||||||
|
- `conflicts.go`: read-only conflicting-file discovery in a temporary bare Git
|
||||||
|
repository; it must not depend on or modify the current Git/Jujutsu checkout.
|
||||||
|
- `drafts.go`, `persistence.go`: versioned, atomic local state.
|
||||||
|
- `ai.go`, `ai_diff.go`, `ai_codex.go`, `ai_store.go`, `ai_tui.go`:
|
||||||
|
experimental local-only AI review, filtering, provider isolation, local
|
||||||
|
storage, and UI.
|
||||||
|
- `types.go`: shared domain models and capability flags.
|
||||||
|
- `TODO.md`: future work; keep completed behavior out of open TODO sections.
|
||||||
|
|
||||||
|
Most source files have a corresponding `_test.go`. Add focused regression
|
||||||
|
tests beside the code being changed.
|
||||||
|
|
||||||
|
## Build and validation
|
||||||
|
|
||||||
|
Use the package, not an individual source file:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
go run .
|
||||||
|
go test ./...
|
||||||
|
go test -race ./...
|
||||||
|
go vet ./...
|
||||||
|
go build ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `gofmt` on changed Go files. A normal implementation should at least pass
|
||||||
|
`go test ./...`; changes involving asynchronous refreshes, provider progress,
|
||||||
|
or shared persistence should also pass the race detector.
|
||||||
|
|
||||||
|
Do not use `go run main.go`: this repository relies on the other files in the
|
||||||
|
same package.
|
||||||
|
|
||||||
|
Do not run Git commands or alter repository history unless the user explicitly
|
||||||
|
asks. Preserve unrelated working-tree changes.
|
||||||
|
|
||||||
|
## Architecture and state flow
|
||||||
|
|
||||||
|
`App` is the Bubble Tea model. GitHub operations return typed messages to
|
||||||
|
`Update`; rendering belongs in `View` and feature-specific view helpers.
|
||||||
|
Network calls, subprocesses, and disk reads must not block the update loop.
|
||||||
|
Long operations should expose stable progress and support cancellation where
|
||||||
|
possible.
|
||||||
|
|
||||||
|
GitHub access is expressed through narrow service interfaces. Keep compile-time
|
||||||
|
interface assertions in `main.go` when implementations change. The cached
|
||||||
|
service must preserve the capability behavior of the live service rather than
|
||||||
|
silently bypassing write gates.
|
||||||
|
|
||||||
|
Refreshes are intentionally incremental:
|
||||||
|
|
||||||
|
- Render cached core data immediately when available.
|
||||||
|
- Replace it with live core data without blanking the current screen.
|
||||||
|
- Enrich checks, annotations, and conflict details independently.
|
||||||
|
- Retain the last complete subsection when one enrichment fails.
|
||||||
|
- Ignore results from superseded requests.
|
||||||
|
|
||||||
|
Do not turn partial failures into an all-or-nothing screen failure.
|
||||||
|
|
||||||
|
## GitHub correctness and write safety
|
||||||
|
|
||||||
|
- Paginate list-like GitHub data or make any remaining bound visible.
|
||||||
|
- Treat GraphQL partial data and errors deliberately.
|
||||||
|
- Use the authenticated endpoint consistently, including GitHub Enterprise
|
||||||
|
Server URL derivation.
|
||||||
|
- Respect rate limits, retry windows, and adaptive polling.
|
||||||
|
- Check the exposed capability gate before showing or executing a mutation.
|
||||||
|
- Preserve drafts if a mutation or post-mutation refresh fails.
|
||||||
|
- Require confirmation for merge, auto-merge, and other consequential actions.
|
||||||
|
- Use expected head OIDs where GitHub supports them; reject stale prepared
|
||||||
|
actions instead of applying them to a changed PR.
|
||||||
|
- Sanitize untrusted GitHub and subprocess text before terminal rendering.
|
||||||
|
- Never interpolate untrusted content into shell commands.
|
||||||
|
|
||||||
|
## Local persistence
|
||||||
|
|
||||||
|
Cache, state, drafts, and local-AI files are user data:
|
||||||
|
|
||||||
|
- Keep formats versioned.
|
||||||
|
- Write atomically.
|
||||||
|
- Use restrictive permissions for sensitive or user-authored content.
|
||||||
|
- Avoid rewriting unchanged files.
|
||||||
|
- Bound cache growth and preserve corrupt-file diagnostics in Health.
|
||||||
|
- Do not silently delete recoverable drafts or local review state.
|
||||||
|
|
||||||
|
## Text, Markdown, and terminal behavior
|
||||||
|
|
||||||
|
- Terminal width is a runtime constraint. Wrap help, errors, paths, Markdown,
|
||||||
|
editor lines, and modal content without losing structural prefixes.
|
||||||
|
- Measure display cells, not bytes or rune counts.
|
||||||
|
- Editing and selections must operate on grapheme boundaries.
|
||||||
|
- Soft-wrapped editor rows are virtual display rows: navigation may traverse
|
||||||
|
them, but saved GitHub Markdown must reconstruct the original logical lines.
|
||||||
|
- Syntax and Markdown highlighting must not insert, remove, or replace editable
|
||||||
|
characters.
|
||||||
|
- Keep the active pane visually distinguishable.
|
||||||
|
- Compact footers show only the first configured key for each action; the help
|
||||||
|
popup may show all configured alternatives.
|
||||||
|
- Add new actions to contextual help and keybinding validation.
|
||||||
|
|
||||||
|
## Themes
|
||||||
|
|
||||||
|
Do not hard-code feature colors outside the theme palette. New UI elements must
|
||||||
|
remain legible in built-in dark/light themes, custom themes, `high-contrast`,
|
||||||
|
and `no-color`. Syntax and Markdown highlighting should follow the selected
|
||||||
|
theme rather than an independent fixed palette.
|
||||||
|
|
||||||
|
## Experimental AI rules
|
||||||
|
|
||||||
|
The provider abstraction is intentionally broader than the current Codex CLI
|
||||||
|
implementation. Keep provider-specific parsing in its adapter.
|
||||||
|
|
||||||
|
- AI remains disabled by default.
|
||||||
|
- Every inference run requires an explicit user action and scope confirmation.
|
||||||
|
- The inference-free status check and quota-consuming provider test must remain
|
||||||
|
visibly distinct.
|
||||||
|
- Filter excluded/sensitive files, redact secret-like values, and enforce byte,
|
||||||
|
file, call, output, and result-count limits.
|
||||||
|
- Treat paths, code, PR text, and comments as untrusted prompt data.
|
||||||
|
- Validate findings against changed diff lines and the prepared head.
|
||||||
|
- Pin one exact model for a run; never silently fall back.
|
||||||
|
- Reject attempted tool, command, or file-change events.
|
||||||
|
- Only display provider-exposed reasoning summaries. Never request, infer, log,
|
||||||
|
or display hidden chain-of-thought.
|
||||||
|
- Store findings locally with deterministic deduplication and mark them
|
||||||
|
outdated when the PR head changes.
|
||||||
|
|
||||||
|
Any future provider that sends data to a direct API needs explicit privacy and
|
||||||
|
retention semantics documented before implementation.
|
||||||
|
|
||||||
|
## Change discipline
|
||||||
|
|
||||||
|
Prefer small, idiomatic changes that preserve current behavior. Correctness
|
||||||
|
comes before API consistency, and API consistency comes before refactoring.
|
||||||
|
Do not rewrite working subsystems merely for style.
|
||||||
|
|
||||||
|
When behavior changes:
|
||||||
|
|
||||||
|
1. Identify the active screen and input context.
|
||||||
|
2. Update state transitions and cancellation behavior.
|
||||||
|
3. Update rendering, contextual help, and capability explanations.
|
||||||
|
4. Add or update regression tests.
|
||||||
|
5. Update `README.md` for user-visible configuration or workflow changes.
|
||||||
|
6. Update `TODO.md` only when work is genuinely completed or newly deferred.
|
||||||
|
|
||||||
|
If a product decision would materially affect persistence compatibility,
|
||||||
|
GitHub writes, AI data exposure, destructive behavior, or default keybindings,
|
||||||
|
ask the repository owner rather than guessing.
|
||||||
657
README.md
657
README.md
@@ -1,21 +1,99 @@
|
|||||||
|
> [!IMPORTANT]
|
||||||
|
> **This entire repository is AI-generated.** The source code, tests, and
|
||||||
|
> documentation were produced through AI-assisted development.
|
||||||
|
>
|
||||||
|
> **Repository owner's two cents:**
|
||||||
|
> Like the previous text says this Repo is entirely slop coded.
|
||||||
|
> I guided the ai (gpt5.6-sol) as best as I could and got out the program I desired.
|
||||||
|
> Use this at your own risk, especially the AI integration.
|
||||||
|
> _No AI Agents were harmed during creation of this Program_
|
||||||
|
|
||||||
# diple
|
# diple
|
||||||
|
|
||||||
A terminal UI for people receiving GitHub pull-request reviews. It
|
`diple` is a keyboard-first terminal interface for reading and responding to
|
||||||
shows open PRs and a scrollable PR dashboard with the description, branches,
|
GitHub pull request reviews. It is designed primarily for the person receiving
|
||||||
review state, merge conflicts and affected files, checks, people, labels,
|
a review: it keeps the PR description, status, changed code, review threads,
|
||||||
milestone, activity, change statistics, thread totals, submitted reviews, and
|
and the actions needed to address feedback in one terminal application.
|
||||||
the PR conversation. Review threads and comments are paginated rather than
|
|
||||||
silently stopping at the first page. The
|
The project is under active development. GitHub write actions are guarded by
|
||||||
thread viewer includes highlighted diff hunks, comment authors, and read-only
|
the permissions reported for the current user and ask for confirmation where
|
||||||
reaction counts on individual comments. Resolved threads start folded. GitHub suggestion blocks are shown as
|
the result is consequential. The optional AI review feature is experimental,
|
||||||
syntax-highlighted remove/add previews. Comments and PR descriptions render
|
disabled by default, and local-only.
|
||||||
GitHub Flavored Markdown, including quoted replies, inline and fenced code,
|
|
||||||
lists and tasks, links, tables, emphasis, strikethrough, emoji, and GitHub
|
## What diple does
|
||||||
alerts. The current PR is refreshed in the background.
|
|
||||||
|
### Pull request picker
|
||||||
|
|
||||||
|
- Loads open PRs assigned to the authenticated user across repositories.
|
||||||
|
- Groups the picker by repository.
|
||||||
|
- Can be restricted to one `owner/repository`.
|
||||||
|
- Can show every open PR in a selected repository.
|
||||||
|
- Uses a disk cache to display a recent snapshot immediately while live data
|
||||||
|
loads.
|
||||||
|
|
||||||
|
### Dashboard
|
||||||
|
|
||||||
|
- Shows the title, Markdown description, branches, author, assignees,
|
||||||
|
reviewers, labels, milestone, merge state, review decision, checks, change
|
||||||
|
statistics, submitted reviews, timeline activity, and PR conversation.
|
||||||
|
- Reports whether the PR has conflicts.
|
||||||
|
- Attempts to identify conflicting files with a read-only temporary Git
|
||||||
|
analysis. This does not inspect or modify the current Git or Jujutsu
|
||||||
|
checkout.
|
||||||
|
- Shows check-run annotations independently so a failure in one subsection
|
||||||
|
does not blank the rest of the dashboard.
|
||||||
|
- Provides a Health popup containing API, cache, persistence, conflict-scan,
|
||||||
|
rate-limit, write-capability, and AI-provider diagnostics.
|
||||||
|
|
||||||
|
### Review threads
|
||||||
|
|
||||||
|
- Displays review comments beside the exact review-time diff hunk when GitHub
|
||||||
|
provides it, even when the file has since changed.
|
||||||
|
- Syntax-highlights code using the file path to choose a lexer.
|
||||||
|
- Highlights the reviewed line range and exact changed spans.
|
||||||
|
- Wraps long source lines as continuation rows without inventing line numbers.
|
||||||
|
- Renders GitHub Flavored Markdown, including quoted replies, inline and
|
||||||
|
fenced code, lists, task lists, tables, links, emphasis, strikethrough,
|
||||||
|
emoji, and GitHub alerts.
|
||||||
|
- Renders GitHub suggestion blocks as syntax-highlighted removal/addition
|
||||||
|
previews.
|
||||||
|
- Shows deterministic per-author colors and read-only reaction counts.
|
||||||
|
- Folds resolved threads by default and distinguishes unread or updated local
|
||||||
|
state.
|
||||||
|
- Supports fuzzy path search; whitespace-separated terms may match separate
|
||||||
|
portions of the same path.
|
||||||
|
- Supports configurable status and within-status ordering.
|
||||||
|
|
||||||
|
### GitHub write actions
|
||||||
|
|
||||||
|
When GitHub reports that the authenticated user has permission, diple can:
|
||||||
|
|
||||||
|
- reply to review threads;
|
||||||
|
- resolve and unresolve review threads;
|
||||||
|
- edit the PR title, Markdown description, and target branch;
|
||||||
|
- enable or disable auto-merge; and
|
||||||
|
- merge immediately when the PR is eligible.
|
||||||
|
|
||||||
|
The UI explains unavailable actions through its write-capability gate.
|
||||||
|
Metadata and reply drafts are persisted locally so cancellation or a restart
|
||||||
|
does not silently discard work.
|
||||||
|
|
||||||
|
Reactions are currently read-only. Assigning reviewers, assignees, labels, or
|
||||||
|
milestones is not implemented yet.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Go 1.24 or newer to build from source.
|
||||||
|
- An authenticated [GitHub CLI](https://cli.github.com/) installation, or a
|
||||||
|
supported GitHub token environment variable.
|
||||||
|
- Git 2.38 or newer for conflicting-file discovery. The rest of the PR remains
|
||||||
|
usable if that optional scan cannot run.
|
||||||
|
- A terminal with reasonable Unicode support.
|
||||||
|
- Optional: an authenticated Codex CLI for experimental local AI review.
|
||||||
|
|
||||||
## Install and run
|
## Install and run
|
||||||
|
|
||||||
Requires Go 1.24+, Git 2.38+, and an authenticated GitHub CLI:
|
From a source checkout:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
go install .
|
go install .
|
||||||
@@ -23,127 +101,255 @@ gh auth login
|
|||||||
diple
|
diple
|
||||||
```
|
```
|
||||||
|
|
||||||
To run directly from a source checkout instead:
|
Run without installing:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
go run .
|
go run .
|
||||||
```
|
```
|
||||||
|
|
||||||
Use `go run .`, not `go run main.go`: the latter compiles only `main.go` and
|
Use `go run .`, not `go run main.go`. The latter omits the other Go files in
|
||||||
omits the other files in the package.
|
the package.
|
||||||
|
|
||||||
For automation, `GH_TOKEN` or `GITHUB_TOKEN` can still be provided and takes
|
By default, diple finds open PRs assigned to the authenticated user across all
|
||||||
precedence over the GitHub CLI credential. Enterprise token environment
|
repositories:
|
||||||
variables are also supported.
|
|
||||||
|
|
||||||
By default the PR picker searches all repositories for open PRs assigned to the
|
```sh
|
||||||
authenticated user and groups the results by repository. Use `--repo` to limit
|
diple
|
||||||
the picker to one repository:
|
```
|
||||||
|
|
||||||
|
Limit the picker to one repository:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
diple --repo owner/repository
|
diple --repo owner/repository
|
||||||
```
|
```
|
||||||
|
|
||||||
With a repository selected, pass `--all` to include every open PR in that
|
Include every open PR in that repository:
|
||||||
repository:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
diple --repo owner/repository --all --poll 15s
|
diple --repo owner/repository --all
|
||||||
```
|
```
|
||||||
|
|
||||||
GitHub Enterprise Server can be used after authenticating that host:
|
Adjust polling or inspect all command-line options:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
diple --poll 15s
|
||||||
|
diple --help
|
||||||
|
```
|
||||||
|
|
||||||
|
Command-line options override configuration values. `GH_REPO` supplies the
|
||||||
|
default repository only when `--repo` is absent.
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
Credential lookup uses the first available value in this order:
|
||||||
|
|
||||||
|
1. `GH_TOKEN`
|
||||||
|
2. `GITHUB_TOKEN`
|
||||||
|
3. `GH_ENTERPRISE_TOKEN`
|
||||||
|
4. `GITHUB_ENTERPRISE_TOKEN`
|
||||||
|
5. the token returned by `gh auth token` for the endpoint host
|
||||||
|
|
||||||
|
For normal interactive use:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gh auth login
|
||||||
|
diple
|
||||||
|
```
|
||||||
|
|
||||||
|
For GitHub Enterprise Server, authenticate the host and provide its GraphQL
|
||||||
|
endpoint:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
gh auth login --hostname github.example.com
|
gh auth login --hostname github.example.com
|
||||||
diple --repo owner/repository \
|
diple \
|
||||||
|
--repo owner/repository \
|
||||||
--endpoint https://github.example.com/api/graphql
|
--endpoint https://github.example.com/api/graphql
|
||||||
```
|
```
|
||||||
|
|
||||||
## Shell completion
|
The token must have sufficient access to read the selected repositories.
|
||||||
|
Write actions additionally depend on the permissions GitHub reports for the
|
||||||
|
particular PR or thread.
|
||||||
|
|
||||||
`diple` generates completion scripts without contacting GitHub or loading the
|
## Navigation
|
||||||
configuration. Choose the command for your shell:
|
|
||||||
|
|
||||||
```sh
|
The defaults are Vim-like and every binding is configurable.
|
||||||
# Bash: current session
|
|
||||||
source <(diple completion bash)
|
|
||||||
|
|
||||||
# Zsh: current session
|
- `j` / `k`: move down / up
|
||||||
source <(diple completion zsh)
|
- `h` / `l`: switch panes or move left / right in the active context
|
||||||
|
- `enter`: open or toggle the selected item
|
||||||
|
- `b`: go back outside text editing
|
||||||
|
- `d`: open the dashboard
|
||||||
|
- `tab`: hide or show the thread list
|
||||||
|
- `/`: fuzzy-search thread file paths
|
||||||
|
- `n` / `N`: next / previous unread thread
|
||||||
|
- `c`: reply to the selected thread
|
||||||
|
- `R`: resolve or unresolve the selected thread
|
||||||
|
- `r`: refresh
|
||||||
|
- `H`: open Health
|
||||||
|
- `A`: open the experimental local AI menu
|
||||||
|
- `?`: show all bindings for the current screen
|
||||||
|
- `q`: quit
|
||||||
|
|
||||||
# Fish: install for the current user
|
Compact footers show only the first configured key for each action. The
|
||||||
diple completion fish > ~/.config/fish/completions/diple.fish
|
contextual help popup shows all alternatives and is the authoritative in-app
|
||||||
```
|
reference.
|
||||||
|
|
||||||
For persistent Bash completion, write the generated output to a directory
|
The PR description editor defaults to Vim-style modal editing, including
|
||||||
loaded by your distribution's `bash-completion` package. For persistent Zsh
|
Normal, Insert, and Visual modes, word/find motions, deletion, system clipboard
|
||||||
completion, write it to a file named `_diple` in a directory on `$fpath`, then
|
yank/paste, and soft-wrap-aware movement. Set `editing.mode = "standard"` for a
|
||||||
run `compinit`. `diple completion --help` lists the supported shells, while
|
non-modal editor. Target-branch completion uses `ctrl+n` and `ctrl+p`.
|
||||||
`diple --help` shows grouped command-line options, defaults, configuration
|
|
||||||
precedence, and authentication behavior.
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
The optional TOML configuration is loaded from
|
Configuration is optional TOML. diple checks:
|
||||||
`$DIPLE_CONFIG`, `$XDG_CONFIG_HOME/diple/config.toml`, or the operating
|
|
||||||
system's user configuration directory at `diple/config.toml`.
|
|
||||||
On Linux this is normally `~/.config/diple/config.toml`. On macOS,
|
|
||||||
`~/Library/Application Support/diple/config.toml` is preferred, with
|
|
||||||
`~/.config/diple/config.toml` automatically used as a fallback when it
|
|
||||||
exists.
|
|
||||||
|
|
||||||
For migration, `GH_THREADS_CONFIG` and existing `gh-threads` configuration or
|
1. `--config FILE`;
|
||||||
cache directories remain fallback locations when their new `diple`
|
2. `DIPLE_CONFIG`;
|
||||||
counterparts do not yet exist.
|
3. `GH_THREADS_CONFIG` as a migration fallback;
|
||||||
|
4. `$XDG_CONFIG_HOME/diple/config.toml`;
|
||||||
|
5. the operating-system configuration directory; and
|
||||||
|
6. legacy `gh-threads` paths when no diple configuration exists.
|
||||||
|
|
||||||
|
Common default paths:
|
||||||
|
|
||||||
|
- Linux: `~/.config/diple/config.toml`
|
||||||
|
- macOS: `~/Library/Application Support/diple/config.toml`
|
||||||
|
- macOS fallback: `~/.config/diple/config.toml`
|
||||||
|
|
||||||
|
Unknown settings and invalid values are rejected at startup instead of being
|
||||||
|
silently ignored.
|
||||||
|
|
||||||
|
### Example configuration
|
||||||
|
|
||||||
|
All settings below show their normal defaults unless noted otherwise:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
theme = "dark" # built-in name, "custom", or an accessibility mode
|
theme = "dark"
|
||||||
refresh_interval = "10s"
|
refresh_interval = "10s" # minimum 2s
|
||||||
repository = "" # optional owner/repository default
|
repository = "" # optional "owner/repository"
|
||||||
show_all = false # requires repository
|
show_all = false # requires repository
|
||||||
limit = 50
|
limit = 50 # 1-1000
|
||||||
endpoint = "https://api.github.com/graphql"
|
endpoint = "https://api.github.com/graphql"
|
||||||
|
|
||||||
[display]
|
[display]
|
||||||
fold_resolved = true
|
fold_resolved = true
|
||||||
thread_list_width_percent = 33 # 20-60
|
thread_list_width_percent = 33 # 20-60
|
||||||
dashboard_mode = "hotkey" # "hotkey" or "intermediate"
|
dashboard_mode = "hotkey" # "hotkey" or "intermediate"
|
||||||
compact_reviews = true # aggregate submitted review history
|
compact_reviews = true
|
||||||
|
|
||||||
[paths]
|
[paths]
|
||||||
scroll = false
|
scroll = false
|
||||||
scroll_interval = "350ms" # minimum 50ms
|
scroll_interval = "350ms" # minimum 50ms
|
||||||
|
|
||||||
[threads]
|
[threads]
|
||||||
# Each status must occur exactly once. "outdated" means unresolved and outdated;
|
# Each category must occur exactly once. Resolved wins over outdated.
|
||||||
# resolved threads remain in "resolved" even when they are also outdated.
|
|
||||||
status_order = ["unresolved", "outdated", "resolved"]
|
status_order = ["unresolved", "outdated", "resolved"]
|
||||||
within_status = "file" # "file" or "timestamp" (oldest first)
|
within_status = "file" # "file" or "timestamp"
|
||||||
|
|
||||||
[cache]
|
[cache]
|
||||||
enabled = true # instant stale view plus offline fallback
|
enabled = true
|
||||||
max_age = "168h" # 7 days; 0 means no age limit
|
max_age = "168h" # 7 days; 0 disables offline expiry
|
||||||
directory = "" # defaults to the OS user cache directory
|
directory = "" # empty uses the OS cache directory
|
||||||
max_entries = 200 # bounded oldest-first pruning; 10-10000
|
max_entries = 200 # 10-10000
|
||||||
|
|
||||||
[editing]
|
[editing]
|
||||||
mode = "vim" # "vim" or "standard"; description field only for now
|
mode = "vim" # "vim" or "standard"
|
||||||
|
|
||||||
[ai]
|
[ai]
|
||||||
# Experimental and local-only. Disabled unless explicitly enabled. Each run
|
|
||||||
# still requires confirmation after its exact scope and redactions are shown.
|
|
||||||
enabled = false
|
enabled = false
|
||||||
provider = "codex-cli" # provider abstraction; only Codex CLI is implemented
|
provider = "codex-cli" # currently the only implemented provider
|
||||||
model = "" # empty uses the provider default for the whole run
|
model = "" # empty selects the provider default
|
||||||
command = "codex"
|
command = "codex"
|
||||||
timeout = "3m"
|
timeout = "3m"
|
||||||
max_calls = 8
|
max_calls = 8
|
||||||
max_request_bytes = 180000
|
max_request_bytes = 180000
|
||||||
max_run_bytes = 900000
|
max_run_bytes = 900000
|
||||||
max_file_bytes = 150000
|
max_file_bytes = 150000
|
||||||
store_directory = "" # defaults beside config.toml, mode 0700/0600
|
store_directory = ""
|
||||||
exclude = ["*.lock", "go.sum", "package-lock.json", "vendor/", "node_modules/", "dist/", "build/", "generated/", "coverage/", "*.generated.*", "*_generated.*", "*.min.js", "*.map", ".env", ".env.*", "*.pem", "*.key", "*.p12", "*.pfx", "*credentials*"]
|
exclude = [
|
||||||
|
"*.lock", "go.sum", "package-lock.json", "vendor/", "node_modules/",
|
||||||
|
"dist/", "build/", "generated/", "coverage/", "*.generated.*",
|
||||||
|
"*_generated.*", "*.min.js", "*.map", ".env", ".env.*", "*.pem",
|
||||||
|
"*.key", "*.p12", "*.pfx", "*credentials*",
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
`dashboard_mode = "hotkey"` opens threads directly from the picker and leaves
|
||||||
|
the dashboard on `d`. `"intermediate"` places the dashboard between the picker
|
||||||
|
and thread viewer.
|
||||||
|
|
||||||
|
`compact_reviews = true` summarizes the submitted-review history instead of
|
||||||
|
showing every repeated `COMMENTED` event.
|
||||||
|
|
||||||
|
Thread categories are:
|
||||||
|
|
||||||
|
- `unresolved`: current unresolved threads;
|
||||||
|
- `outdated`: unresolved threads attached to outdated code; and
|
||||||
|
- `resolved`: all resolved threads, including resolved-and-outdated threads.
|
||||||
|
|
||||||
|
Within a category, `"file"` keeps paths together and `"timestamp"` sorts by
|
||||||
|
the time the thread was opened.
|
||||||
|
|
||||||
|
### Themes
|
||||||
|
|
||||||
|
Built-in themes:
|
||||||
|
|
||||||
|
- `dark`
|
||||||
|
- `light`
|
||||||
|
- `catppuccin` / `catppuccin-mocha`
|
||||||
|
- `catppuccin-latte`
|
||||||
|
- `gruvbox` / `gruvbox-dark`
|
||||||
|
- `gruvbox-light`
|
||||||
|
- `one-dark-pro`
|
||||||
|
- `github` / `github-dark`
|
||||||
|
- `github-light`
|
||||||
|
- `high-contrast`
|
||||||
|
- `no-color`
|
||||||
|
|
||||||
|
The selected palette also controls Markdown and source-code syntax
|
||||||
|
highlighting.
|
||||||
|
|
||||||
|
For a custom theme, set `theme = "custom"` and override any subset of a
|
||||||
|
built-in base:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
theme = "custom"
|
||||||
|
|
||||||
|
[custom_theme]
|
||||||
|
base = "catppuccin"
|
||||||
|
mode = "dark"
|
||||||
|
title = "#f5c2e7"
|
||||||
|
dim = "#7f849c"
|
||||||
|
text = "#cdd6f4"
|
||||||
|
active_foreground = "#11111b"
|
||||||
|
active_background = "#89b4fa"
|
||||||
|
success = "#a6e3a1"
|
||||||
|
warning = "#f9e2af"
|
||||||
|
error = "#f38ba8"
|
||||||
|
editor_foreground = "#cdd6f4"
|
||||||
|
editor_background = "#313244"
|
||||||
|
pane_inactive = "#585b70"
|
||||||
|
pane_active = "#89b4fa"
|
||||||
|
quote = "#94e2d5"
|
||||||
|
selection_background = "#45475a"
|
||||||
|
suggestion_remove_background = "#3b1f2b"
|
||||||
|
suggestion_add_background = "#193b2a"
|
||||||
|
changed_remove_background = "#4b1f2b"
|
||||||
|
changed_add_background = "#1d4b32"
|
||||||
|
author_palette = ["#89b4fa", "#cba6f7", "#94e2d5", "#f9e2af"]
|
||||||
|
syntax_theme = "catppuccin-mocha"
|
||||||
|
```
|
||||||
|
|
||||||
|
Colors must use `#RRGGBB`. `mode` is `dark` or `light`; `syntax_theme` must be
|
||||||
|
an installed Chroma style. Omitted custom values inherit from `base`.
|
||||||
|
|
||||||
|
### Keybindings
|
||||||
|
|
||||||
|
Each action accepts one or more Bubble Tea key names. Defining an action
|
||||||
|
replaces its default list; omitted actions retain their defaults. Configuration
|
||||||
|
validation rejects conflicting assignments within the same active context.
|
||||||
|
|
||||||
|
```toml
|
||||||
[keybindings.general]
|
[keybindings.general]
|
||||||
quit = ["q", "ctrl+c"]
|
quit = ["q", "ctrl+c"]
|
||||||
help = ["?", "f1"]
|
help = ["?", "f1"]
|
||||||
@@ -153,7 +359,6 @@ confirm = ["y"]
|
|||||||
reject = ["n", "esc"]
|
reject = ["n", "esc"]
|
||||||
|
|
||||||
[keybindings.navigation]
|
[keybindings.navigation]
|
||||||
# Shared by the picker, dashboard, thread panes, help, and Vim Normal/Visual modes.
|
|
||||||
down = ["j", "down"]
|
down = ["j", "down"]
|
||||||
up = ["k", "up"]
|
up = ["k", "up"]
|
||||||
left = ["h", "left"]
|
left = ["h", "left"]
|
||||||
@@ -231,235 +436,127 @@ repeat_find = [";"]
|
|||||||
repeat_find_reverse = [","]
|
repeat_find_reverse = [","]
|
||||||
```
|
```
|
||||||
|
|
||||||
Themes are compiled into `diple`; they do not require a separate download.
|
Printable bindings do not steal ordinary text while an input field, search, or
|
||||||
Available names are `dark`, `light`, `catppuccin` (`catppuccin-mocha`),
|
Insert mode owns that key.
|
||||||
`catppuccin-latte`, `gruvbox` (`gruvbox-dark`), `gruvbox-light`,
|
|
||||||
`one-dark-pro`, `github` (`github-dark`), `github-light`, `high-contrast`,
|
|
||||||
and `no-color`.
|
|
||||||
|
|
||||||
Set `theme = "custom"` to inherit a built-in palette and replace only the
|
## Cache and local data
|
||||||
roles you care about:
|
|
||||||
|
|
||||||
```toml
|
The read cache is designed for fast startup and offline fallback:
|
||||||
theme = "custom"
|
|
||||||
|
|
||||||
[custom_theme]
|
- core picker and PR snapshots are stored separately;
|
||||||
base = "catppuccin-mocha" # defaults to "dark"
|
- unchanged content is not rewritten on every refresh;
|
||||||
mode = "dark" # "dark" or "light"; controls Markdown rendering
|
- changed files are replaced atomically;
|
||||||
title = "#F5C2E7"
|
- old entries are pruned at `cache.max_entries`; and
|
||||||
active_foreground = "#1E1E2E"
|
- live data automatically replaces the visible cached snapshot.
|
||||||
active_background = "#89B4FA"
|
|
||||||
selection_background = "#313244"
|
|
||||||
author_palette = ["#89B4FA", "#CBA6F7", "#94E2D5", "#F9E2AF"]
|
|
||||||
syntax_theme = "catppuccin-mocha"
|
|
||||||
```
|
|
||||||
|
|
||||||
Every color override uses `#RRGGBB`. The complete set of roles is `title`,
|
Cached data is labelled when first shown. A normal refresh does not repeatedly
|
||||||
`dim`, `text`, `active_foreground`, `active_background`, `success`, `warning`,
|
reintroduce the cached header.
|
||||||
`error`, `editor_foreground`, `editor_background`, `pane_inactive`,
|
|
||||||
`pane_active`, `quote`, `selection_background`,
|
|
||||||
`suggestion_remove_background`, `suggestion_add_background`,
|
|
||||||
`changed_remove_background`, and `changed_add_background`.
|
|
||||||
`author_palette` accepts one or more colors. `syntax_theme` accepts an installed
|
|
||||||
Chroma style name; invalid colors, bases, and syntax styles are reported as
|
|
||||||
configuration errors at startup. The `[custom_theme]` table is ignored unless
|
|
||||||
`theme = "custom"`.
|
|
||||||
|
|
||||||
Every command binding accepts one or more Bubble Tea key names. Omitted
|
Read state and recoverable drafts live beside the configuration file as
|
||||||
settings retain their defaults, while an explicitly configured action replaces
|
`state.json` and `drafts.json`. Experimental AI data defaults to the `ai`
|
||||||
its default keys. Printable keys remain text in Insert mode, reply drafts, and
|
directory beside the configuration. These files are versioned and written
|
||||||
search queries; command bindings apply in the appropriate non-text context.
|
atomically; sensitive user-authored state uses restrictive permissions.
|
||||||
The contextual `?` popup and compact screen footers use the configured keys.
|
|
||||||
Configuration loading also checks each active context independently. A key may
|
|
||||||
be reused on unrelated screens, but assigning it to two different actions that
|
|
||||||
can be active together reports the context and both conflicting actions.
|
|
||||||
|
|
||||||
## Experimental local AI review
|
## Experimental local AI review
|
||||||
|
|
||||||
Set `ai.enabled = true` to expose the `A` menu on the dashboard and thread
|
Enable the feature explicitly:
|
||||||
screens. The initial provider uses the authenticated Codex CLI, so run
|
|
||||||
`codex login` first. A full review creates clearly labelled `LOCAL AI · LOCAL
|
|
||||||
ONLY` threads; it may also attach local-only context to unresolved GitHub
|
|
||||||
threads. Pressing the normal reply key on a local AI thread starts a discussion
|
|
||||||
with the same configured model. Resolving or unresolving those threads changes
|
|
||||||
only the permission-restricted local per-PR state file. For small,
|
|
||||||
self-contained replacements the model can include a standard GitHub-style
|
|
||||||
suggestion in its local comment. These use the existing syntax-aware
|
|
||||||
remove/add preview and remain local; diple does not apply or publish them.
|
|
||||||
|
|
||||||
Every model run is manually confirmed. The preview shows the head commit,
|
```toml
|
||||||
model, files, byte budget, call count, exclusions, and redaction count. Input
|
[ai]
|
||||||
comes exclusively from GitHub's authenticated PR diff and PR metadata: diple
|
enabled = true
|
||||||
does not read the local checkout for AI review. Secret-like values are
|
provider = "codex-cli"
|
||||||
redacted, binary/generated/vendor/lock/oversized files are excluded, and the
|
command = "codex"
|
||||||
provider subprocess receives a small environment allowlist. Codex is launched
|
```
|
||||||
ephemerally in an empty temporary directory with project instructions ignored,
|
|
||||||
read-only sandboxing, approvals disabled, and all supported tool surfaces
|
|
||||||
disabled. Any attempted tool event or malformed/out-of-range structured result
|
|
||||||
fails the run closed.
|
|
||||||
|
|
||||||
The AI menu distinguishes the inference-free provider status refresh from a
|
Authenticate Codex separately before opening diple:
|
||||||
provider test that makes one deliberately small structured model call. The
|
|
||||||
test requires its own confirmation, consumes provider quota, and sends no PR
|
|
||||||
content or local files. Preparing and running a review displays animated,
|
|
||||||
stable progress; multi-chunk reviews report completed model calls. When the
|
|
||||||
provider exposes a reasoning summary, diple shows a bounded, sanitized summary
|
|
||||||
beside the progress bar. It never requests or displays hidden chain-of-thought.
|
|
||||||
|
|
||||||
PR content is untrusted and is explicitly delimited as data in the model
|
```sh
|
||||||
prompt. Results are validated against changed paths and lines, deduplicated,
|
codex login
|
||||||
and retained as outdated when the PR head moves. No AI result is published to
|
```
|
||||||
GitHub. Publishing proposed replies and additional providers remain future
|
|
||||||
work; a future direct API provider must require no-training and zero-data-
|
|
||||||
retention guarantees.
|
|
||||||
|
|
||||||
When cached data exists, the picker and PR details are rendered immediately
|
The `A` menu can:
|
||||||
from that snapshot while a live GitHub refresh runs in the background. Cached
|
|
||||||
screens are labelled with their save time and are replaced automatically when
|
|
||||||
fresh data arrives. Core PR and review data is rendered before check
|
|
||||||
annotations and conflict-file analysis finish. A failed subsection keeps its
|
|
||||||
last complete value, is marked partial, and does not discard the rest of a
|
|
||||||
successful refresh. Check annotations are fetched separately only for failed
|
|
||||||
checks and are reused by immutable check ID.
|
|
||||||
|
|
||||||
The cache uses separate JSON files for the picker and each visited PR. Cache
|
- review the current PR and create local-only review threads;
|
||||||
content is hashed before writing: unchanged responses do not rewrite their
|
- discuss an existing local AI thread with the same selected model;
|
||||||
files. Their modification time is touched at most once per day (or half the
|
- add local-only context to existing unresolved GitHub threads;
|
||||||
configured maximum age, when shorter) so recently validated snapshots remain
|
- produce small GitHub-style suggestion blocks for contained changes;
|
||||||
usable without writing on every poll. Changed files are replaced atomically,
|
- refresh provider status without making an inference call; and
|
||||||
and oldest cache entries are pruned at the configured bound. Read state and
|
- run one explicitly confirmed, minimal provider test that consumes quota but
|
||||||
recoverable reply/metadata drafts use versioned, atomic files beside the
|
sends no PR contents.
|
||||||
configuration.
|
|
||||||
|
|
||||||
Polling adapts to GitHub's reported rate-limit budget. It backs off as the
|
Before a review, diple shows the exact head commit, selected model, included and
|
||||||
remaining budget gets low, honors server retry windows, and adds jitter to
|
excluded files, byte count, maximum model-call count, and redaction count.
|
||||||
avoid synchronized clients. Opening another PR or starting another refresh
|
Every run requires confirmation.
|
||||||
cancels the superseded request.
|
|
||||||
|
|
||||||
GitHub's public APIs report whether a PR conflicts but do not expose its
|
AI input comes from the authenticated GitHub PR diff and PR metadata, not from
|
||||||
conflicting file paths. For conflicting PRs only, `diple` performs a
|
the local checkout. diple excludes configured sensitive, generated, vendored,
|
||||||
read-only `git merge-tree` analysis in a temporary bare repository. It never
|
lock, binary, and oversized files; redacts secret-like values; chunks bounded
|
||||||
touches or inspects the current checkout, so Git, Jujutsu (`jj`), and directories
|
requests; and validates findings against lines changed in the prepared head.
|
||||||
without a local repository behave identically. The analysis fetches the exact
|
|
||||||
remote base branch and pull-request head ref using the existing GitHub
|
|
||||||
credential. Results are memoized by the base and head commit, and failed scans
|
|
||||||
are retried after one minute.
|
|
||||||
|
|
||||||
Command-line flags override the configuration. `GH_REPO` overrides the
|
The Codex process runs ephemerally in an empty temporary directory with:
|
||||||
configured repository when `--repo` is not provided. The corresponding flags
|
|
||||||
include `--config`, `--theme`, `--poll`, `--fold-resolved`,
|
|
||||||
`--thread-list-width`, `--dashboard-mode`, `--compact-reviews`,
|
|
||||||
`--path-scroll`, and `--path-scroll-interval`, plus `--cache`,
|
|
||||||
`--cache-max-age`, `--cache-dir`, and `--editor-mode`.
|
|
||||||
Boolean settings can be disabled explicitly, for
|
|
||||||
example `--compact-reviews=false`.
|
|
||||||
|
|
||||||
With the default `dashboard_mode = "hotkey"`, opening a PR goes directly to its
|
- repository instructions ignored;
|
||||||
review threads and `d` opens the dashboard only when requested. Set
|
- a read-only sandbox;
|
||||||
`dashboard_mode = "intermediate"` to follow picker → dashboard → review
|
- approvals disabled;
|
||||||
threads instead.
|
- a restricted environment;
|
||||||
|
- tools, commands, browser, network, plugins, memories, and multi-agent
|
||||||
|
features disabled; and
|
||||||
|
- a strict structured-output schema.
|
||||||
|
|
||||||
Compact reviews aggregate submission counts by state and author. Reviews with
|
Attempted tool or file-change events fail the run. Provider output is bounded
|
||||||
a written summary retain a compact one-line body, while timestamps and commit
|
and sanitized. Progress may display a provider-exposed reasoning summary, but
|
||||||
SHAs are omitted. Set `compact_reviews = false` to restore the complete review
|
diple neither requests nor displays hidden chain-of-thought.
|
||||||
history and metadata.
|
|
||||||
|
|
||||||
## Default keys
|
AI findings are stored locally, deduplicated deterministically, and marked
|
||||||
|
outdated when the PR head changes. Resolving a local AI thread remains local.
|
||||||
|
diple never publishes an AI finding or discussion to GitHub automatically.
|
||||||
|
|
||||||
| Key | Action |
|
Only the Codex CLI provider is currently implemented. The interface permits
|
||||||
| --- | --- |
|
future providers, but their privacy and retention behavior must be defined
|
||||||
| `h` / `l` | Focus the thread list / thread detail |
|
before they are added.
|
||||||
| `j` / `k` | Move between items or scroll the dashboard/focused detail |
|
|
||||||
| `?` | Show contextual keybinding help |
|
|
||||||
| `H` | Open application health and diagnostics |
|
|
||||||
| `d` | Open the current pull request dashboard |
|
|
||||||
| `e` | Edit the current PR title, target branch, and description from its dashboard |
|
|
||||||
| `a` | Enable or disable auto-merge from the dashboard |
|
|
||||||
| `M` | Merge now when GitHub reports that all represented requirements are satisfied |
|
|
||||||
| `/` | Fuzzy-search paths and filter with `status:`, `author:`, `updated:true` |
|
|
||||||
| `F` | Clear active thread filters |
|
|
||||||
| `n` / `N` | Next / previous thread with a new update |
|
|
||||||
| `c` | Compose a reply to the selected thread |
|
|
||||||
| `R` | Resolve or unresolve the selected thread |
|
|
||||||
| `ctrl-p` / `ctrl-n` | Choose the previous / next fuzzy-search or branch-completion match |
|
|
||||||
| `g` / `G` | First / last item |
|
|
||||||
| `enter` / `l` | Open the selected PR dashboard or its review threads |
|
|
||||||
| `enter` | Toggle the selected review thread |
|
|
||||||
| `za` | Toggle the selected thread |
|
|
||||||
| `ctrl-d` / `ctrl-u` | Scroll thread detail or page through lists |
|
|
||||||
| `tab` | Hide or reveal the thread list |
|
|
||||||
| `b` / `esc` | Return to the previous screen |
|
|
||||||
| `r` | Refresh now |
|
|
||||||
| `q` | Quit |
|
|
||||||
|
|
||||||
The Health modal reports the interactive loop, configuration, GitHub API,
|
## Shell completion
|
||||||
rate-limit budget and reset/retry time, disk cache, unread-state persistence,
|
|
||||||
draft recovery, core PR data, and secondary enrichment. Session warnings and
|
|
||||||
errors are retained there with their component and timestamp. Long diagnostics
|
|
||||||
wrap to the modal width. Refresh activity occupies a stable informational row
|
|
||||||
so polling does not reorder the report. Press `H` from the picker, dashboard,
|
|
||||||
or thread view; `b` or `esc` closes it without changing the underlying scroll
|
|
||||||
position.
|
|
||||||
|
|
||||||
The reply composer appears inline beneath the selected thread so its code and
|
Generate completion without contacting GitHub or loading configuration:
|
||||||
comments remain visible while writing. It supports multiple lines: `enter`
|
|
||||||
inserts a newline, `ctrl-s` opens the rendered confirmation preview, and `esc`
|
|
||||||
cancels. Replies and resolution changes require an explicit `y` confirmation.
|
|
||||||
Write keys remain disabled for cached snapshots, during refreshes, and whenever
|
|
||||||
GitHub does not grant the corresponding capability.
|
|
||||||
|
|
||||||
Auto-merge and immediate merge actions are available from the dashboard and
|
```sh
|
||||||
always require confirmation. The selected method is the repository's first
|
# Bash, current session
|
||||||
available method in `squash`, `merge`, then `rebase` preference order. Both
|
source <(diple completion bash)
|
||||||
mutations include the currently displayed head commit OID, so a force-push or
|
|
||||||
new commit prevents a stale merge. “Merge now” is gated for drafts, conflicts,
|
|
||||||
required reviews, required checks, unresolved required conversations, closed
|
|
||||||
PRs, and branches that require a merge queue; GitHub performs the final
|
|
||||||
permission and mergeability validation.
|
|
||||||
|
|
||||||
The dashboard editor works with raw Markdown so template checklists can be
|
# Zsh, current session
|
||||||
updated directly. The active line is highlighted without inserting a
|
source <(diple completion zsh)
|
||||||
layout-changing block character. It opens with the description focused;
|
|
||||||
`tab` and `shift-tab` move between the description, title, and target branch.
|
|
||||||
When the target branch is focused, repository branches are recommended using
|
|
||||||
the typed text, likely branch names, the current/default branch, and each
|
|
||||||
branch's latest commit time. The list updates as you type. Use `ctrl-p` and
|
|
||||||
`ctrl-n` to select the previous or next result, then `tab` or `enter` to complete it;
|
|
||||||
pressing `tab` again moves to the description.
|
|
||||||
|
|
||||||
With the default `editing.mode = "vim"`, the description starts in Normal mode.
|
# Fish, persistent user installation
|
||||||
It supports `hjkl`, `0`, `^`, `$`, `gg`, `G`, `w`/`W`, `b`/`B`, `e`/`E`,
|
diple completion fish > ~/.config/fish/completions/diple.fish
|
||||||
`f`/`F`/`t`/`T` with `;` and `,`, `i`/`a`/`I`/`A`, `o`/`O`, `s`, and
|
```
|
||||||
`x`/`X`. `s` removes the character under the cursor and enters Insert mode.
|
|
||||||
Soft-wrapped rows behave as visual editor lines for vertical and line-local
|
|
||||||
motions, but do not add newlines to the Markdown submitted to GitHub.
|
|
||||||
`ctrl-d` and `ctrl-u` move the cursor and viewport down or up by half a page,
|
|
||||||
including while extending a Visual selection.
|
|
||||||
`v` starts character-wise Visual mode and `V` starts visual-line selection;
|
|
||||||
`d` or `x` deletes the selection, `y` copies it to the system clipboard, and
|
|
||||||
`p` pastes from the system clipboard. Normal mode uses a block cursor, while
|
|
||||||
Insert mode uses the terminal's hardware bar cursor at the boundary between
|
|
||||||
characters without hiding or shifting either character.
|
|
||||||
The description retains its raw Markdown while headings, emphasis, inline
|
|
||||||
code, links, quote markers, and HTML comments receive syntax highlighting.
|
|
||||||
Highlighting consists only of zero-width terminal styling and cannot alter
|
|
||||||
wrapping, selection, clipboard contents, cursor offsets, or submitted text.
|
|
||||||
`esc` returns from Insert to Normal mode; a second `esc` cancels the editor.
|
|
||||||
Set `editing.mode = "standard"` for direct insertion with arrow,
|
|
||||||
`home`, and `end` navigation. Title and target branch remain standard inputs
|
|
||||||
in either mode. `ctrl-s` opens an explicit confirmation. If the title,
|
|
||||||
description, or target branch changes remotely while the editor is open,
|
|
||||||
submission is blocked rather than overwriting the newer metadata.
|
|
||||||
|
|
||||||
## Current scope
|
For persistent Zsh completion, save the output as `_diple` in a directory on
|
||||||
|
`$fpath` and ensure `compinit` runs. The generated Zsh script also initializes
|
||||||
|
completion when sourced directly:
|
||||||
|
|
||||||
The application can reply to review threads, resolve or unresolve them, update
|
```sh
|
||||||
the PR title, target branch, and description, enable or disable auto-merge, and
|
mkdir -p ~/.zfunc
|
||||||
merge an eligible PR immediately. Comment reactions remain read-only. Other
|
diple completion zsh > ~/.zfunc/_diple
|
||||||
write operations remain disabled. The dashboard shows the capability gate,
|
fpath=(~/.zfunc $fpath)
|
||||||
including why each action is unavailable. Read state
|
autoload -Uz compinit
|
||||||
persists beside the configuration, and recent PR data is cached for offline
|
compinit
|
||||||
fallback. Check contexts and annotations are paginated. GitHub features which
|
```
|
||||||
depend on server-side context, such as unfurling issue references or displaying
|
|
||||||
uploaded images, are represented textually in the terminal. See
|
Run `diple completion --help` for the supported shells.
|
||||||
[`TODO.md`](TODO.md) for remaining read-only work and write-support preparation.
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
The module path is `git.pablu.de/Pablu/diple`. The repository is a single Go
|
||||||
|
`package main` built around Bubble Tea, Lip Gloss, Chroma, and Glamour.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gofmt -w path/to/changed.go
|
||||||
|
go test ./...
|
||||||
|
go test -race ./...
|
||||||
|
go vet ./...
|
||||||
|
go build ./...
|
||||||
|
```
|
||||||
|
|
||||||
|
Repository architecture, safety invariants, and contributor guidance are
|
||||||
|
documented in [AGENTS.md](AGENTS.md). Planned work is tracked in
|
||||||
|
[TODO.md](TODO.md).
|
||||||
|
|||||||
Reference in New Issue
Block a user