Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
4302f45
feat(shell): customizable status line via /statusline
elkaix Jun 11, 2026
fe165e5
feat(subagents): concurrent foreground fan-out and batch findings rol…
elkaix Jun 11, 2026
032a1f5
chore: record agentic UX enhancement progress in tasks/todo.md
elkaix Jun 11, 2026
0d8a32c
chore: tick completed sub-items in tasks/todo.md
elkaix Jun 11, 2026
c92c346
feat(shell): blue bold highlight for recognized slash commands
elkaix Jun 11, 2026
d9c67bf
fix: harden review findings across agent batch and statusline
elkaix Jun 11, 2026
905cc97
feat(slash): add /learn self-improvement command
elkaix Jun 11, 2026
aad0d1b
refactor(background): move TaskOutput poll-escalation streak to the m…
elkaix Jun 11, 2026
465969e
fix(telemetry): suppress expected user-environment errors from Sentry
elkaix Jun 11, 2026
d05c1db
fix: harden statusline verb parsing, kill race, and finding roll-up
elkaix Jun 11, 2026
6f4f08a
test: pin prompts/learn.md in the PyInstaller datas list
elkaix Jun 11, 2026
2a0092c
feat(agent): adopt condensed best-practices profile by default
elkaix Jun 11, 2026
3d8b422
chore(tasks): record best-practices adoption and review-batch notes
elkaix Jun 11, 2026
89647c0
feat(statusline): add StatusLineColors theme palette
elkaix Jun 11, 2026
fa605e9
feat(statusline): config fields for v2 segments, style, bar width, bu…
elkaix Jun 11, 2026
7d4a5c6
feat(statusline): smooth eighth-block bar and usage gradient helpers
elkaix Jun 11, 2026
45e44d2
feat(statusline): StatusLineContext and segment registry skeleton
elkaix Jun 11, 2026
8bac449
test(statusline): update legacy resolver tests for the v2 default seg…
elkaix Jun 11, 2026
2feed00
feat(statusline): spinner, model, cost, speed, effort segment renderers
elkaix Jun 11, 2026
aa9ba3e
feat(statusline): cwd, git, diff, flags segment renderers
elkaix Jun 11, 2026
c670b64
feat(statusline): line-2 renderers and footer assembler with drop-ord…
elkaix Jun 11, 2026
5d670fe
feat(soul): session cost and cumulative in/out totals in StatusSnapshot
elkaix Jun 11, 2026
513f1f7
feat(statusline): token rate sampler and git shortstat parser
elkaix Jun 11, 2026
bcb9a68
feat(statusline): cached git diff shortstat helper
elkaix Jun 11, 2026
916a210
feat(statusline): render the v2 fancy footer from the segment registry
elkaix Jun 11, 2026
6befb32
feat(agentic-orchestration): consolidate agent specs, telemetry, and …
elkaix Jun 11, 2026
2845c74
test(statusline): drop orphaned DEFAULT_STATUSLINE_SEGMENTS import
elkaix Jun 11, 2026
b803c46
feat(statusline): /statusline style, bar-width, budget, and segment l…
elkaix Jun 11, 2026
d994b4d
docs(changelog): statusline v2 visual redesign
elkaix Jun 11, 2026
68fb92d
feat(agentic-orchestration): structured report blocks for agent findings
elkaix Jun 11, 2026
d8a63c6
feat(agentic-orchestration): refine agent specs, config, and telemetry
elkaix Jun 11, 2026
5792120
fix(agentic-orchestration): harden review-validated edge cases
elkaix Jun 11, 2026
3ee99b1
fix(tui): align RunAgents result rows and drop redundant names
elkaix Jun 11, 2026
8a0f695
docs: redirect root to /en/ and sync docs with current code
elkaix Jun 11, 2026
478aaf6
feat(agentic-orchestration): harden subagent review safety + TUI polish
elkaix Jun 11, 2026
82d86ea
feat(tui): mid-line slash suggest, input highlighting, footer polish
elkaix Jun 11, 2026
4f2e224
feat(agentic-orchestration): spec/profile truth + jail hardening
elkaix Jun 11, 2026
2547d5f
fix(agentic-orchestration): address branch review findings
elkaix Jun 11, 2026
00fa9ac
fix(hooks): changelog gate SIGPIPE false denial under pipefail
elkaix Jun 11, 2026
00c0fd8
chore(tasks): lesson from changelog-gate SIGPIPE incident
elkaix Jun 11, 2026
6c5a808
feat(agent): spec fidelity, partial-read hints, inline /command refs
elkaix Jun 11, 2026
08432e9
fix(statusline): drain killed status command so reap cannot deadlock
elkaix Jun 11, 2026
d81f045
test(diff-render): assert preview marker styles, not rendered ANSI
elkaix Jun 11, 2026
b300e71
chore(tasks): trim completed todo logs for repush
elkaix Jun 11, 2026
7fc0c58
chore(tasks): lessons from CI test failures (Rich style cache, pipe r…
elkaix Jun 11, 2026
763a824
chore(coderabbit): scope bot reviews to shipped code
elkaix Jun 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .claude/hooks/check-changelog.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,16 @@ done <<< "$changed"
[ "$touched" -eq 0 ] && exit 0

# Pass if ## Unreleased has at least one non-blank line.
# Checked inside awk (no pipe): `| grep -q` exits at the first match, and
# under pipefail the resulting SIGPIPE to awk reads as failure once the
# block outgrows the pipe buffer — denying exactly when the changelog is
# at its fullest.
if awk '
/^## Unreleased[[:space:]]*$/ { inblk=1; next }
inblk && /^## / { inblk=0 }
inblk { print }
' CHANGELOG.md 2>/dev/null | grep -q '[^[:space:]]'; then
inblk && /[^[:space:]]/ { found=1; exit }
END { exit !found }
' CHANGELOG.md 2>/dev/null; then
exit 0
fi

Expand Down
4 changes: 4 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ reviews:
- "!graphify-out/**"
- "!**/*.pyc"
- "!**/__pycache__/**"
# Prose and working-notes paths: keeps bot reviews focused on shipped
# code and large branches under the per-PR reviewed-file limit.
- "!docs/**"
- "!tasks/**"

path_instructions:
- path: "**/*.py"
Expand Down
34 changes: 34 additions & 0 deletions .github/workflows/release-pythinker-cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,40 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

register-bugsink-release:
name: Register release in Bugsink
needs: [validate, release]
# Registering the release at cut time (instead of waiting for the first
# event from that version) makes Bugsink's "resolved in next release"
# semantics flip exactly when the release ships. Telemetry must never
# gate a release: failures here are warnings, not job failures.
if: always() && needs.release.result == 'success'
runs-on: ubuntu-latest
steps:
- name: POST release to Bugsink
env:
VERSION: ${{ needs.validate.outputs.version }}
BUGSINK_TOKEN: ${{ secrets.BUGSINK_RELEASES_TOKEN }}
run: |
set -uo pipefail
if [[ -z "$BUGSINK_TOKEN" ]]; then
echo "::warning title=Bugsink::BUGSINK_RELEASES_TOKEN not set; skipping release registration"
exit 0
fi
body=$(jq -n --arg v "pythinker-code@${VERSION}" '{project: 1, version: $v}')
status=$(curl -sS -o /tmp/resp.json -w "%{http_code}" -m 30 \
-X POST "https://errors.pythinker.com/api/canonical/0/releases/" \
-H "Authorization: Bearer ${BUGSINK_TOKEN}" \
-H "Content-Type: application/json" \
-d "$body" || echo "000")
if [[ "$status" == "201" || "$status" == "200" ]]; then
echo "Registered pythinker-code@${VERSION} in Bugsink"
elif [[ "$status" == "400" ]] && grep -q "already exists" /tmp/resp.json; then
echo "Release pythinker-code@${VERSION} already registered (idempotent re-run)"
else
echo "::warning title=Bugsink::release registration failed (HTTP ${status}): $(cat /tmp/resp.json 2>/dev/null | head -c 200)"
fi

publish-python-testpypi:
name: Publish Python package to TestPyPI
needs: validate
Expand Down
37 changes: 36 additions & 1 deletion CHANGELOG.md

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ export default withMermaid(defineConfig({
],
},

transformHead({ pageData }) {
if (pageData.relativePath === 'index.md') {
return [['meta', { 'http-equiv': 'refresh', content: `0; url=${base}en/` }]]
}
},

vite: {
plugins: [llmstxt()],
},
Expand Down
3 changes: 2 additions & 1 deletion docs/en/configuration/config-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ The configuration file contains the following top-level configuration items:
| `skip_auto_prompt_injection` | `boolean` | Whether to suppress the auto-mode system reminder (defaults to `false`) |
| `default_plan_mode` | `boolean` | Whether to start new sessions in plan mode by default (defaults to `false`); resumed sessions preserve their existing state |
| `default_editor` | `string` | Default external editor command (e.g. `"vim"`, `"code --wait"`), auto-detects when empty |
| `theme` | `string` | Terminal color theme, either `"dark"` or `"light"` (defaults to `"dark"`) |
| `theme` | `string` | Terminal color theme: `"dark"`, `"light"`, or `"auto"` (detects the terminal background at startup, falling back to dark); defaults to `"dark"` |
| `show_thinking_stream` | `boolean` | Whether to stream the raw reasoning text in the live area as a 6-line scrolling preview and commit the full reasoning markdown to history when the block ends (defaults to `true`; set to `false` to show only the compact `Thinking ...` indicator and a one-line trace summary) |
| `prevent_idle_sleep` | `boolean` | Whether to prevent the computer from idle-sleeping while an agent turn is running (defaults to `false`; supported on macOS, Linux, and Windows) |
| `merge_all_available_skills` | `boolean` | Whether to merge skills from all brand directories (defaults to `true`); see [Skills configuration](../customization/skills.md) |
Expand All @@ -41,6 +41,7 @@ The configuration file contains the following top-level configuration items:
| `compact_prompt` | `string \| null` | Override the built-in compaction summarization prompt; `null`/unset keeps the default handoff-structured prompt (a `/compact` focus argument is still appended on top) |
| `background` | `table` | Background task runtime parameters |
| `services` | `table` | External service configuration (search, fetch) |
| `web` | `table` | Shared web fetch/search policy (e.g. `allowed_domains`) |
| `mcp` | `table` | MCP client configuration |

### Complete configuration example
Expand Down
12 changes: 6 additions & 6 deletions docs/en/configuration/env-vars.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ export OPENAI_ADMIN_KEY="sk-admin-xxx"
| --- | --- |
| `PYTHINKER_SHARE_DIR` | Customize the share directory path (default: `~/.pythinker`) |
| `PYTHINKER_CLI_NO_AUTO_UPDATE` | Disable proactive update checks and startup update notices |
| `PYTHINKER_CLI_PASTE_CHAR_THRESHOLD` | Character threshold for folding pasted text (default: `1000`) |
| `PYTHINKER_CLI_PASTE_LINE_THRESHOLD` | Line threshold for folding pasted text (default: `15`) |
| `PYTHINKER_CLI_PASTE_CHAR_THRESHOLD` | Character threshold for folding pasted text (default: `200`) |
| `PYTHINKER_CLI_PASTE_LINE_THRESHOLD` | Line threshold for folding pasted text (default: `5`) |

### `PYTHINKER_SHARE_DIR`

Expand Down Expand Up @@ -171,18 +171,18 @@ If you installed Pythinker Code via Nix or other package managers, this environm

### `PYTHINKER_CLI_PASTE_CHAR_THRESHOLD`

In Agent mode, when pasted text exceeds this character count, it is folded into a placeholder (e.g., `[Pasted text #1 +10 lines]`) and expanded to full content on submit. Default: `1000`.
In Agent mode, when pasted text exceeds this character count, it is folded into a placeholder (e.g., `[Pasted text #1 +10 lines]`) and expanded to full content on submit. Default: `200`.

```sh
export PYTHINKER_CLI_PASTE_CHAR_THRESHOLD="1000"
export PYTHINKER_CLI_PASTE_CHAR_THRESHOLD="200"
```

### `PYTHINKER_CLI_PASTE_LINE_THRESHOLD`

In Agent mode, when pasted text reaches this line count, it is folded into a placeholder. Default: `15`.
In Agent mode, when pasted text reaches this line count, it is folded into a placeholder. Default: `5`.

```sh
export PYTHINKER_CLI_PASTE_LINE_THRESHOLD="15"
export PYTHINKER_CLI_PASTE_LINE_THRESHOLD="5"
```

::: tip
Expand Down
2 changes: 1 addition & 1 deletion docs/en/configuration/overrides.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Environment variables can override provider and model settings without modifying
Environment variables take effect based on the current provider type:

- `pythinker` type providers: Use `PYTHINKER_*` environment variables
- `openai_legacy` or `openai_responses` type providers: Use `OPENAI_*` environment variables
- `openai_legacy`, `openai_responses`, or `openai_codex` type providers: Use `OPENAI_*` environment variables
- Other provider types: Environment variable overrides not supported

See [Environment Variables](./env-vars.md) for the complete list.
Expand Down
5 changes: 5 additions & 0 deletions docs/en/configuration/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ After configuration, Pythinker Code will automatically save settings to `~/.pyth
| Platform | Description |
| --- | --- |
| Pythinker | Pythinker platform, supports search and fetch services |
| OpenAI API | Official OpenAI API |
| OpenAI ChatGPT Codex | OpenAI managed account login |
| Pythinker AI Open Platform (pythinker-ai.cn) | China region API endpoint |
| Pythinker AI Open Platform (pythinker-ai.ai) | Global region API endpoint |
| LM Studio | Local models served via LM Studio |
| Ollama | Local models served via Ollama |

For other platforms, please manually edit the configuration file.

Expand All @@ -31,6 +35,7 @@ The `type` field in `providers` configuration specifies the API provider type. D
| `pythinker` | Pythinker API |
| `openai_legacy` | OpenAI Chat Completions API |
| `openai_responses` | OpenAI Responses API |
| `openai_codex` | OpenAI Responses API with managed account login (configured via `/login`, not by hand) |
| `anthropic` | Anthropic Claude API |
| `gemini` | Google Gemini API |
| `vertexai` | Google Vertex AI |
Expand Down
3 changes: 2 additions & 1 deletion docs/en/customization/agent-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ The toolset is both a registry and an execution boundary. It hides tools from th

## Subagent graph

The `Agent` tool lets only the root agent create or resume subagents. Subagents get isolated context and Wire files, but share session-level services such as approval state, notification infrastructure, background task management, and the root Wire hub.
The `Agent` tool lets only the root agent create or resume a single subagent, and the `RunAgents` tool launches a batch of subagents (up to 8) in one call. Both are root-only. Subagents get isolated context and Wire files, but share session-level services such as approval state, notification infrastructure, background task management, and the root Wire hub.

```mermaid
flowchart TB
Expand Down Expand Up @@ -306,6 +306,7 @@ Hooks are integrated at both turn and tool boundaries:
| `PostToolUseFailure` | After a tool raises an exception |
| `Stop` | After a turn finishes, with one re-trigger guard |
| `StopFailure` | After an agent step fails |
| `SessionStart` and `SessionEnd` | When a session is created/resumed and when it closes |
| `PreCompact` and `PostCompact` | Around context compaction |
| `Notification` | When pending notifications are delivered into LLM context |
| `SubagentStart` and `SubagentStop` | Around foreground subagent execution |
Expand Down
40 changes: 33 additions & 7 deletions docs/en/customization/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pythinker --agent okabe

The default agent, suitable for general use. Enabled tools:

`Agent`, `AskUserQuestion`, `SetTodoList`, `Shell`, `ReadFile`, `ReadMediaFile`, `Glob`, `Grep`, `WriteFile`, `StrReplaceFile`, `SearchWeb`, `FetchURL`, `EnterPlanMode`, `ExitPlanMode`, `TaskList`, `TaskOutput`, `TaskStop`
`Agent`, `RunAgents`, `ReadSkill`, `AskUserQuestion`, `SetTodoList`, `UpdateGoal`, `Progress`, `Suggest`, `Memory`, `Recall`, `Scratchpad`, `Shell`, `TaskList`, `TaskOutput`, `TaskInput`, `TaskHandoff`, `TaskStop`, `ReadFile`, `ReadMediaFile`, `Glob`, `Grep`, `SmartSearch`, `WriteFile`, `StrReplaceFile`, `SearchWeb`, `FetchURL`, `ListMcpResources`, `ReadMcpResource`, `EnterPlanMode`, `ExitPlanMode`

### `ask`

Expand All @@ -28,7 +28,7 @@ Primary mode for systematic failure diagnosis. It reproduces or inspects failure

### `okabe`

An experimental agent for testing new prompts and tools. Adds `SendDMail` on top of `default`.
An experimental agent for testing new prompts and tools. It inherits from `default` but defines its own tool list, which adds `SendDMail` (D-Mail checkpoint rollback).

## Repository markdown agents

Expand Down Expand Up @@ -187,19 +187,21 @@ The default agent configuration includes focused built-in subagent types with di
|------|---------|----------------|
| `coder` | General software engineering with judgment: read/write files, run commands, search code | Read/search tools, `Shell`, write tools, web tools |
| `implementer` | Scoped implementation with minimal edits and quick verification | Read/search tools, `Shell`, write tools, web tools |
| `explore` | Fast read-only codebase exploration: search, read, summarize | Read/search tools, `Shell`, web tools; no write tools |
| `explore` | Fast read-only codebase exploration: search, read, summarize | Read/search tools and `Shell`; no write tools |
| `plan` | Implementation planning and architecture design | Read/search tools and web tools; no write tools |
| `planner` | Read-only recon planner that decomposes broad work into parallel seeds | Read/search tools and `Shell`; no write tools |
| `scout` | Read-only external docs, dependency-source, and API freshness researcher | Read/search tools, `Shell`, web tools; no write tools |
| `review` | Read-only severity-scored code review | Read/search tools, `Shell`, web tools; no write tools |
| `code-reviewer` | Diff-focused code review for the current branch | Read/search tools, `Shell`, web tools; no write tools |
| `security-reviewer` | Diff-focused security review with validated findings | Read/search tools, `Shell`, web tools; no write tools |
| `review` | Read-only severity-scored code review | Read/search tools and `Shell`; no write tools |
| `code-reviewer` | Diff-focused code review for the current branch | Read/search tools and `Shell`; no write tools |
| `security-reviewer` | Diff-focused security review with validated findings | Read/search tools and `Shell`; no write tools |
| `debugger` | Root-cause analysis for failures, logs, and stack traces | Read/search tools and `Shell`; no write tools |
| `verifier` | Read-only validation runner for tests, lint, type checks, and builds | Read/search tools and `Shell`; no write tools |
| `judge` | Independent final quality gate for answers, reports, and code-change summaries | Read/search tools and `Shell`; no write tools |

All subagent types are prohibited from nesting the `Agent` tool (subagents cannot create their own subagents). The `Agent` tool is only available to the root agent.

Reviewer-class types (`review`, `code-reviewer`, `security-reviewer`, `debugger`, `judge`, `verifier`, `explore`) run offline by design: their permission profiles block network and external doc-lookup tools because the content they analyze is untrusted. Third-party claims they cannot verify from the repository come back under RISKS as `needs verification` items; the parent agent resolves those against live docs — directly or by dispatching `scout`, the online research type (`plan` also keeps web access for planning research).

## How subagents run

Subagents launched via the `Agent` tool run in an isolated context and return results to the main agent when complete. Each subagent instance maintains its own context history and metadata under `subagents/<agent_id>/` in the session directory, and can be resumed across multiple invocations. Advantages of this approach:
Expand All @@ -226,7 +228,31 @@ The following are all built-in tools in Pythinker Code.
| `model` | string | Optional model override |
| `resume` | string | Optional agent instance ID to resume an existing instance |
| `run_in_background` | bool | Whether to run in background, default false |
| `timeout` | int | Timeout in seconds, range 30–3600. Foreground defaults to no timeout (runs until completion), background defaults to 15 minutes; the task is stopped if the limit is exceeded |
| `timeout` | int | Timeout in seconds, range 30–3600. Foreground defaults to no timeout (runs until completion), background defaults to the configured limit (1 hour); the task is stopped if the limit is exceeded |
| `dependencies` | array | Optional background task IDs this task depends on. Metadata only — launch dependent tasks after their prerequisites are ready |
| `budget_seconds` | int | Optional time budget (seconds) recorded as planning/synthesis metadata |
| `isolation` | string | `none` (default) or `worktree`. `worktree` records a git-worktree isolation intent for background agents; ignored for foreground runs |

### `RunAgents`

- **Path**: `pythinker_code.tools.agent:RunAgents`
- **Description**: Launch a batch of subagents (1–8) in one call, sharing a common `base_prompt` and each running its own `prompt`. Foreground batches run the children concurrently and return all results inline; background batches return task IDs immediately, and if a background batch exceeds the available slots only the fitting prefix is launched while the rest are reported as deferred. Like `Agent`, this tool is only available to the root agent.

| Parameter | Type | Description |
|-----------|------|-------------|
| `summary` | string | Short summary of the multi-agent run |
| `base_prompt` | string | Shared context prepended to every child prompt |
| `agents` | array | Child agents to launch (1–8); each has its own objective |
| `agents[].name` | string | Stable short name for the child agent |
| `agents[].prompt` | string | Child-specific task prompt |
| `agents[].title` | string | Optional 3–5 word display title, defaults to `name` |
| `agents[].subagent_type` | string | Built-in subagent type for the child, default `coder` |
| `model` | string | Optional model override applied to every child |
| `run_in_background` | bool | Whether to run in background, default true |
| `timeout` | int | Optional per-agent timeout in seconds, range 30–3600 |
| `isolation` | string | `none` (default) or `worktree` for background children |

To keep parallel children distinguishable in the task list, tree, and notifications, any child whose name is generic (or collides with a sibling) is given a stable `adjective-noun` codename (for example `amber-falcon`), while its subagent type stays visible separately.

### `AskUserQuestion`

Expand Down
2 changes: 1 addition & 1 deletion docs/en/customization/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Pythinker Code supports 13 lifecycle events:
| `SubagentStop` | When subagent ends | Agent name | `agent_name`, `response` |
| `PreCompact` | Before context compaction | Trigger reason | `trigger`, `token_count` |
| `PostCompact` | After context compaction | Trigger reason | `trigger`, `estimated_token_count` |
| `Notification` | When notification is delivered | Sink name | `sink`, `notification_type`, `title`, `body`, `severity` |
| `Notification` | When notification is delivered | Notification type | `sink`, `notification_type`, `title`, `body`, `severity` |

## Configuring Hooks

Expand Down
Loading
Loading