Skip to content
Closed
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
009dcb7
feat(subagents): integrate the external pi-subagents package (engine …
dreadster3 Sep 28, 2026
6698643
chore(npm): rebrand fork for @dreadster3/pi-web publish (v0.0.1) (#4)
dreadster3 Sep 28, 2026
1b4d00e
feat(sidebar): local branch quick switching in the worktree dropdown …
dreadster3 Sep 29, 2026
00b90e3
fix(agents): correct subagent running status in the Agents menu (#5) …
dreadster3 Sep 29, 2026
7520576
Merge remote-tracking branch 'upstream/main' into chore/sync-upstream
dreadster3 Sep 29, 2026
46f8be7
chore(demo): mirror upstream markdown list continuation into the demo…
dreadster3 Sep 29, 2026
78be0d9
Merge pull request #9 from dreadster3/chore/sync-upstream
dreadster3 Sep 29, 2026
83f8668
Release v0.0.2 (#10)
dreadster3 Sep 29, 2026
f44284c
feat(themes): Catppuccin Latte + Mocha themes (#11)
dreadster3 Sep 30, 2026
1063399
Merge remote-tracking branch 'upstream/main' into chore/sync-upstream-2
dreadster3 Sep 30, 2026
be66efc
fix(sidebar): keep handleDefaultCwd next to the worktree handlers
dreadster3 Sep 30, 2026
0db5112
chore(demo): mirror the upstream model-default selectors byte-identic…
dreadster3 Sep 30, 2026
38eee82
chore(demo): port upstream's feature hunks into the adapted copies
dreadster3 Sep 30, 2026
8964a93
chore(demo): stub PUT /api/models/default in the mock
dreadster3 Sep 30, 2026
7284778
chore(demo): validate default-model mock like the real route
dreadster3 Sep 30, 2026
39e4dde
chore: sync upstream (agegr/pi-web @ 433d09e) — model-default persist…
dreadster3 Sep 30, 2026
53007cb
feat(nix): add flake with packaged app, overlay, dev shell (#13)
dreadster3 Sep 30, 2026
cc437ff
Release v0.0.3 (#14)
dreadster3 Sep 30, 2026
21eea1c
chore: ignore .pi/ in .gitignore (#15)
dreadster3 Sep 30, 2026
64a427e
chore: sync upstream (agegr/pi-web @ eceac13)
dreadster3 Sep 30, 2026
6c194f8
chore: sync upstream (agegr/pi-web @ b9622a1)
dreadster3 Sep 30, 2026
6488f77
chore: sync upstream (agegr/pi-web @ 2bb48f5)
dreadster3 Sep 30, 2026
d411afd
Merge pull request #17 from dreadster3/chore/sync-upstream-3
dreadster3 Sep 30, 2026
c608b92
feat(cli): add --version flag to pi-web (#16)
dreadster3 Sep 30, 2026
c3cf3a6
feat(agents): live-refresh subagents panel (poll + activate-on-focus)…
dreadster3 Sep 30, 2026
49b62dc
Release v0.0.4 (#19)
dreadster3 Sep 30, 2026
f221701
chore: sync upstream (agegr/pi-web @ 5d4c0b5)
dreadster3 Oct 2, 2026
71f340f
chore(demo): carry the sync's client-side mirrors and mock Settings ›…
dreadster3 Oct 2, 2026
281ce88
chore: sync upstream (agegr/pi-web @ 6fcd7d4)
dreadster3 Oct 2, 2026
7b965bd
fix(agents): split a jammed line after conflict merge
dreadster3 Oct 2, 2026
e0e1db7
chore(demo): re-mirror the i18n messages after the second sync
dreadster3 Oct 2, 2026
27bb039
chore: sync upstream (agegr/pi-web @ 5d4c0b5) (#20)
dreadster3 Oct 2, 2026
c365925
feat(settings): add Context tab for editing agent context files (#21)
dreadster3 Oct 2, 2026
9afea64
feat(context): delete any of the seven context files (#23)
dreadster3 Oct 3, 2026
dd0a766
fix(deps): bump the earendil SDK to 1.0.1; build nix deps from import…
dreadster3 Oct 3, 2026
111ead1
build(release): release-please-managed releases, owner-approved via s…
dreadster3 Oct 3, 2026
1dac30c
chore(main): release 0.1.0 (#26)
github-actions[bot] Oct 3, 2026
1fcb78c
chore(renovate): enable renovate (#48)
dreadster3 Oct 5, 2026
96c846c
chore(renovate): update configurations (#49)
dreadster3 Oct 5, 2026
5149664
chore(release): add demo to version release (#52)
dreadster3 Oct 5, 2026
9b47a70
chore(ci): consolidate GitHub Actions updates and pin to minor releas…
dreadster3 Oct 5, 2026
6042339
chore(deps): pin dependencies (#63)
dreadster3-renovate[bot] Oct 5, 2026
d028906
chore(deps): update dependency node to v24 (#61)
dreadster3-renovate[bot] Oct 5, 2026
7607ebe
chore(deps): update dependency undici to v8.11.2 (#34)
dreadster3-renovate[bot] Oct 5, 2026
0c03988
feat(projects): delete a project's sessions (#27)
dreadster3 Oct 5, 2026
0766d6c
fix(deps): repair incomplete bundled-dep entries in demo/package-lock…
dreadster3 Oct 6, 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
14 changes: 7 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22.19.0
node-version: 24.21.0
cache: npm
- run: npm ci
- run: npm run lint
Expand All @@ -31,18 +31,18 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22.19.0
node-version: 24.21.0
cache: npm
- run: npm ci
- run: npx playwright install --with-deps chromium
- run: npm run build
- run: npm run test:e2e
env:
E2E_SERVER_MODE: start
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: failure()
with:
name: e2e-failure
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/demo-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,23 @@ jobs:
run:
working-directory: demo
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22.19.0
node-version: 24.21.0
cache: npm
cache-dependency-path: demo/package-lock.json
- id: pages
if: github.event_name != 'pull_request'
uses: actions/configure-pages@v5
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
- run: npm ci
- run: npm run lint
- run: npm run build
env:
# "/<repo>" for a project site, empty for a custom domain.
PAGES_BASE_PATH: ${{ steps.pages.outputs.base_path }}
- if: github.event_name != 'pull_request'
uses: actions/upload-pages-artifact@v3
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
path: demo/out

Expand All @@ -59,4 +59,4 @@ jobs:
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
144 changes: 144 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
name: Release

# release-please keeps ONE accumulating release pull request. It does the version
# bookkeeping; the OWNER decides WHEN by choosing when to merge that PR.
#
# What the bot does on its own, on every push to main:
# - reads the conventional commits since the last release and computes the next
# version (or opens nothing while a release PR is already pending),
# - opens/updates a single PR that bumps package.json + package-lock.json and
# writes CHANGELOG.md.
# It never pushes to main and never publishes.
#
# What happens when the OWNER merges that PR — in the SAME run that sees the merge:
# - release-please commits the version, pushes the tag vX.Y.Z and creates the
# GitHub release; job `release-please` reports release_created=true + the tag.
# - job `publish`, gated by `needs: release-please`, then checks out that tag,
# builds, tests and STAGES the tarball on npm via OIDC trusted publishing (no
# stored NPM_TOKEN) with provenance attached.
#
# OWNER control: hold a release back by leaving the release PR open; ship it by
# merging. Merging releases the metadata (tag + GitHub release) and stages the
# artifact, but NOTHING IS INSTALLABLE until the OWNER approves the staged version
# on npmjs.com (package → "Staged Packages" tab → Approve, 2FA) or runs
# `npm stage approve <stage-id>`; that approval is the only way a version goes live.
# The "staged with id <uuid>" line is written into the workflow run summary. The
# one-time prerequisite is a STAGE-ONLY npm trusted publisher registration
# (environment `release`, this file's name) — see docs/release.md.
#
# Trusted publisher, STAGE-ONLY: register it with staged publishing allowed and
# direct publishing DISALLOWED (npmjs.com → package → Settings → Trusted Publisher,
# or `npm trust github … --allow-stage-publish` without `--allow-publish`). npm then
# rejects `npm publish` from this workflow, so a compromised run could stage a
# tarball but could never move a version live — the OWNER's 2FA click is the only
# way. Staged publishing needs npm >= 11.15.0; the node-24 toolcache image
# setup-node installs bundles npm >= 11.16, so the floor is met with no pin
# (https://docs.npmjs.com/staged-publishing). If a future image ever shipped an
# older npm, `npm stage publish` fails as an unknown command — the playbook in
# docs/release.md names that failure. The dist-tag is IMMUTABLE: whatever
# tag the stage carries (`latest` here, the default for a stable version) is the tag
# the version goes live with on approval; there is no separate promotion step.
#
# Token: the default GITHUB_TOKEN. The release PR is therefore authored by
# github-actions[bot], and a PR opened with GITHUB_TOKEN deliberately does NOT trigger
# other workflows. Accepted here because
# (a) publish is needs-chained, not event-chained: it runs in the same workflow run
# that saw the merge, so no tag-push-triggered workflow has to fire,
# (b) this repository's ruleset (Default: deletion, non-fast-forward, pull_request;
# empty bypass actors; NO required status checks — verified via the API) does
# not need the PR to carry checks to be mergeable,
# (c) release PRs are mechanically trivial — version fields plus changelog; the nix
# side needs no hash maintenance any more (importNpmLock, see docs/release.md).
# Forward-compat: if required status checks are ever added to the ruleset, give this
# job an App token (actions/create-github-app-token) so the release PR triggers them.
on:
push:
branches: [main]
workflow_dispatch: # re-runs and maintenance; same two jobs, same gates

permissions:
contents: read

jobs:
release-please:
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: write # read the manifest config and the commits
pull-requests: write # open/update the release PR
# One release PR at a time. A queued run is not cancelled: canceling mid-flight
# can leave a label/PR state that the next run has to untangle.
concurrency:
group: release-please
cancel-in-progress: false
outputs:
release_created: ${{ steps.release.outputs.release_created }}
tag_name: ${{ steps.release.outputs.tag_name }}
steps:
# No `token:`: the action defaults it to `${{ github.token }}` — from its
# action.yml, `token: ... default: ${{ github.token }}`. The release PR is thus
# github-actions[bot]-authored and triggers no other workflow; the header says
# why that is fine and what to change if that stops being true.
#
# Manifest mode: no `release-type` here, the config file carries it.
# v5 is additive-only over v4 (same inputs, same `${{ github.token }}` default);
# it bundles release-please 17.6 (was 17.3), so the first bot PR is the smoke test.
- uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5
id: release
with:
config-file: release-please-config.json
manifest-file: .release-please-manifest.json

# STAGES the release the job above just created — it does not publish anything
# live. Runs only when a release was actually created, i.e. in the same workflow
# run that saw the owner merge the release PR. On a run that only opens/updates the
# PR this job is skipped.
publish:
needs: release-please
if: needs.release-please.outputs.release_created == 'true'
runs-on: ubuntu-latest
timeout-minutes: 30
# Must match the Trusted Publisher registered on npmjs.com for @dreadster3/pi-web,
# and the `release` environment must exist in repo settings (see docs/release.md).
# The registration must be STAGE-ONLY — staged publishing allowed, direct
# publishing disallowed — so this job cannot bypass the owner's approval.
environment: release
permissions:
contents: read
id-token: write # OIDC for npm trusted publishing; provenance follows from it
steps:
# The tag release-please just pushed, so the build is of the released commit.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ needs.release-please.outputs.tag_name }}

# Node 24 for trusted publishing; staged publishing also needs Node >= 22.14.
# package-manager-cache: false — no cache for a job holding an OIDC publish
# token (supply-chain hardening; the input exists from setup-node v5 on).
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24
package-manager-cache: false

# npm floor: staged publishing requires npm >= 11.15.0, and the node-24
# toolcache this setup-node installs bundles npm >= 11.16 — no pin needed
# (https://docs.npmjs.com/staged-publishing; the header says what to do if a
# future image ever ships an older npm).
- run: npm ci

# Required, not --if-present: the tarball ships .next and next.config.ts bakes
# NEXT_PUBLIC_APP_VERSION from package.json, so a skipped build would publish
# an empty artifact with a wrong version.
- run: npm run build

- run: npm test

# Stages the built tarball for the owner's review — no NPM_TOKEN, the trusted
# publisher grants this run the right to stage (and, stage-only, nothing more).
# `--provenance`/`--access` are ordinary `npm publish` flags that
# `npm stage publish` accepts (params parity); hono's release.yml is the same
# invocation. The stage-id lands in the run summary via `tee`.
- name: Stage the release on npm
run: |
set -o pipefail
npm stage publish --provenance --access public | tee -a "$GITHUB_STEP_SUMMARY"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,6 @@ yarn-error.log*
next-env.d.ts
.factory
e2e_*.mjs

.playwright-mcp/
.pi/
4 changes: 4 additions & 0 deletions .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
".": "0.1.0",
"demo": "0.1.0"
}
25 changes: 25 additions & 0 deletions .renovaterc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:best-practices",
":semanticPrefixChore",
":automergePr",
":automergeRequireAllStatusChecks",
":preserveSemverRanges",
":disableRateLimiting"
],
"ignorePresets": [":semanticPrefixFixDepsChoreOthers"],
"automergeStrategy": "squash",
"packageRules": [
{
"description": "Pi Coding Agent group",
"groupName": "Pi Coding Agent",
"matchDatasources": ["npm"],
"matchPackageNames": ["/@earendil-works\/pi/"],
"group": {
"commitMessageTopic": "{{{groupName}}} group"
},
"minimumGroupSize": 4
}
]
}
14 changes: 10 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,12 @@ app/api/
skills/route.ts GET/PATCH loaded skills, disable-model-invocation
skills/install/route.ts POST install skills via npx skills add
skills/search/route.ts POST skills.sh search
subagents/settings/route.ts GET/PUT built-in subagent switch and maxConcurrent
subagents/[id]/route.ts GET legacy built-in-engine run status
subagents/profiles/route.ts GET/PUT/DELETE agent profile files (global/project)
subagents/catalog/route.ts GET pi-subagents agent catalog for a cwd
subagents/tools/route.ts GET selectable child tools (builtin + extension)
subagents/overrides/route.ts PUT user-scope agentOverrides disable switch
subagents/eject/route.ts POST copy a catalog agent into a writable agent dir
web-auth/route.ts GET status | POST login | DELETE logout (browser password)
provider-usage/query/route.ts POST provider usage quotas
push/config/route.ts GET VAPID public key
Expand All @@ -103,7 +108,8 @@ lib/
default-preferences.ts write defaultModel/defaultThinkingLevel; detect project shadowing
enabled-models.ts pure minimal-edit engine for the enabledModels pattern list
enabled-models-runtime.ts SDK adapter for enabledModels: pattern resolution, provider kinds, settings IO
subagent-settings.ts read/write ~/.pi/agent/agents/settings.json
subagents.ts legacy subagent session readers + shared agent-profile editor
subagent-overrides.ts setSubagentOverrideDisabled — user settings agentOverrides writer; plus lib/subagent-profile-precedence.ts and lib/pi-subagents-*.ts
file-access.ts allowed file roots for /api/files and worktrees
linked-directory.ts directory links leading outside the allowed roots + the allow-link check
file-paths.ts client/server path encoding helpers
Expand Down Expand Up @@ -158,7 +164,7 @@ components/
EnabledModelsSection.tsx model switches inside ModelsConfig (enabledModels)
OAuthPastePanel.tsx paste box for a sign-in's redirected address or code (Models, MCP)
ProjectTrustDialog.tsx trust confirmation listing the project's MCP servers
AgentsConfig.tsx built-in subagent toggle + agent profile editor
AgentsConfig.tsx agent profile editor for ~/.pi/agent/agents/*.md
PluginsConfig.tsx Settings › Plugins: installed package plugins
SkillsConfig.tsx Settings › Skills: loaded, search, install
McpConfig.tsx Settings › MCP: servers, switches, exposure, remove/undo, Test, sign-in, Code mode, trust
Expand Down Expand Up @@ -196,7 +202,7 @@ Design decisions and traps live in `docs/agents/`, one note per area. Read every
- [models.md](docs/agents/models.md): default model and reasoning level, mid-run reasoning changes, remote provider catalogs, `enabledModels` scoping and minimal edits, provider auth listing and credentials. Files: `app/api/models/**`, `app/api/models-config/**`, `app/api/auth/**`, `lib/default-preferences.ts`, `lib/model-scope.ts`, `lib/enabled-models*.ts`, `lib/model-catalog-refresh.ts`, `lib/provider-listing*.ts`, `components/ModelsConfig.tsx`, `components/EnabledModelsSection.tsx`, `components/ModelSelector.tsx`, `components/SelectorRow.tsx`.
- [files-and-access.md](docs/agents/files-and-access.md): worktrees and project grouping, the file access allow-list (the `/api/files` security boundary), file tree visibility, web password throttling. Files: `app/api/files/**`, `app/api/cwd/**`, `app/api/worktrees/**`, `app/api/file-index/**`, `app/api/web-auth/**`, `proxy.ts`, `lib/path-security.ts`, `lib/file-access.ts`, `lib/linked-directory.ts`, `lib/session-file-references*.ts`, `lib/file-tree-visibility.ts`, `lib/worktree.ts`, `lib/paths.ts`, `lib/auth-throttle.ts`, `components/FileExplorer.tsx`.
- [settings-ui.md](docs/agents/settings-ui.md): Plugins and Skills routes, sidebar group switches, the shared `SettingsUi` blocks every settings panel and add pane uses. Files: `app/api/plugins/**`, `app/api/skills/**`, `components/SettingsUi.tsx`, `components/settings-ui-helpers.ts`, `components/SkillsConfig.tsx`, `components/PluginsConfig.tsx`; also before adding a settings section or add pane.
- [subagents.md](docs/agents/subagents.md): the built-in subagent setting, profiles and their files, run status, completion notifications. Files: `lib/subagent*.ts`, `app/api/subagents/**`, `components/AgentsConfig.tsx`.
- [subagents.md](docs/agents/subagents.md): delegation owned by the `pi-subagents` package, the legacy built-in-engine sessions that still render, and the shared agent-profile editor. Files: `lib/subagents.ts`, `lib/subagent-overrides.ts`, `lib/subagent-profile-precedence.ts`, `lib/pi-subagents-*.ts`, `app/api/subagents/**`, `components/AgentsConfig.tsx`, `components/AgentSessionPanel.tsx`, `hooks/useAgentsRefresh.ts`.
- [client-platform.md](docs/agents/client-platform.md): mobile software keyboard and viewport height, completion sound. Files: `hooks/useViewportHeight.ts`, `hooks/useAudio.ts`, the keyboard-open CSS.

---
Expand Down
Loading