An Amp-native port of Lauren Tan's pstack, synchronized with upstream pstack 0.15.26. It keeps pstack's 55 skills, 23 engineering playbooks, principles, and PR tooling while replacing editor-specific orchestration with Amp agents, threads, orbs, schedules, and webhooks.
The workflow source is Cursor pstack 0.15.26 at the pinned revision. Preserve its decision rules, mandatory steps, and exceptions. Translate platform mechanics without weakening the workflow. Amp retains its deliberately tuned model defaults and three-family panels rather than adopting upstream's Opus/Grok-only defaults; this departure is recorded in upstream-port.json.
The Amp adapter owns execution details such as role-based child threads, executor selection, file transfer, ownership, and authorized schedules. Playbooks retain the instructions for what work to delegate and what evidence to require. Implementation and follow-up fixes belong to the implementation owner; comment review does not replace an independent whole-PR shipping verdict.
The thread that receives pstack:poteto-mode runs the playbook and owns its checklist and child spawns. Delegates handle scoped work, not the whole coordinator playbook.
Amp permissions and higher-priority instructions still apply. The mode supplies instructions, not a sandbox that prevents every workflow violation. The regression tests check the port's instruction contracts and runtime wiring; they do not prove that every future agent run complies. Inspect actual delegate calls and verification evidence when evaluating behavior. Loading the skill does not establish which mode was selected in the Dial.
pstack is a directory plugin. Amp's URL installer (amp plugins add) only accepts a single .ts file, so do not use it here.
Personal plugins (recommended). This loads on every machine and in orbs. Clone your Amp user-plugins repo, copy this tree in as pstack/, and build the selector for the root of that repo (next to pstack/, not inside it). The single-file selector must bundle the skill text: Amp isolates root plugins from sibling files at runtime.
amp clone user-plugins
rsync -a --delete --exclude .git ./ /path/to/user-plugins/pstack/
bun run build:selector
cp .amp/tmp/poteto-mode.ts /path/to/user-plugins/poteto-mode.tsThen reload plugins. Open Settings → Mode Dial → Build Dial and drag poteto into a bay. A system clone at ~/.config/amp/plugins/pstack beats a personal copy, so do not keep both.
This machine only:
git clone https://github.com/ThewindMom/amp-pstack.git ~/.config/amp/plugins/pstackOne project only:
mkdir -p .amp/plugins
git clone https://github.com/ThewindMom/amp-pstack.git .amp/plugins/pstackConfirm with amp plugins list. A personal copy shows as amp-global-plugin:pstack with scope: user.
Select poteto from the mode picker after it is on your Dial. If the picker still only shows builtins and official-modes, start in medium and load the skill:
Load pstack:poteto-mode. Then <task>.
Then state the goal and the evidence that proves it:
Use pstack:poteto-mode. The export writes duplicate rows after a retry. Reproduce it, fix the root cause, and verify the real export.
Configure model roles with the pstack:setup-pstack skill, the pstack_configure_models tool, or the setup-models command.
- Selectable mode.
poteto-mode.tsregisters the Mode Dial entry with Claude Opus 5.5 at medium reasoning, built-in medium tools, and the full Poteto instructions. Thepstack/directory plugin owns skills and tools. Do not also registerpotetofromindex.ts, or the key collides. - 55 registered skills. Invoke them with qualified names such as
pstack:how,pstack:arena,pstack:recall, andpstack:reflect. Explicitly invokepstack:in-your-own-wordsto check the agent's understanding of your goal before work begins, orpstack:sharpento improve the task's approach without adding scope. Usepstack:ketchupfor a read-only catch-up built on real visuals, with every pending decision explained in the reply even when that makes it long. For help choosing a workflow or wording a prompt, explicitly invokepstack:poteto-help; help questions do not start the work. - Role-based agents. Cursor backgrounds every Task; this port uses native Amp child threads. Default long work (
feature,how-explorer,bug-fix, and the rest of the playbooks) usespstack_start_agent. Writable starts need a human-readablescopeand concretescopePaths. Local and runner parents stay on their current executor by default; Amp-managed orb parents use a fresh child orb. The tool returns athreadID, and the child exclusively owns its paths. Children report with nativesend_thread_message; the plugin can recover unreported final text. The parent keeps doing independent work and ends the turn when blocked. Never usewait_for_threadsto judge startup. Only when the parent truly needs the result, wait with nativewait_for_threads, then inspect it with nativeread_thread. Do not combine a wait with a requested reply. Never redo or replace a live child. - Hybrid worker contracts. The
potetoparent retains the full coordinator skill. Worker modes do not load it automatically: callers inline completed task templates, and role instructions name only qualified execution skills to load when applicable. Strict read-only explorers, explainers, comment reviewers, interrogate reviewers, and arena cross-judges cannot load skills; their complete contracts are inline. Models and tool restrictions remain role-specific. - Multi-model panels.
pstack_run_panelwaits for arena, architect, and interrogate seats. Keep it for ranking that this turn needs now. Its optionalcountaccepts 1 through 20 candidates and cycles the configured seats in order. - Durable child threads.
pstack_start_agentlaunches on the current executor, a fresh orb, or a named runner. Use nativesend_thread_messagefor reports and steering; the parent relays between siblings. If an active child becomes terminal without reporting, pstack inspects the full child transcript and steers the parent with the terminal state and newest assistant text. Failed fallback appends remain pending for reload recovery. This is not a global exactly-once guarantee: the host has no transaction or idempotency key spanning append acknowledgement and local state, so a lost acknowledgement can still produce a duplicate fallback. Only work kept on the current executor can depend on its live checkout. Transfer files explicitly whenever either side is an orb. Two orbs do not share a disk. - Durable ownership. A transactional SQLite journal outside the plugin checkout permits disjoint paths to overlap, prevents duplicate or prefix-overlapping writers, and restores live claims after plugin reload on the same persistent executor.
- Thread-native memory. Reflection reads the current transcript directly.
pstack_read_current_threadreturnsoffset,total, andtruncated; callers page forward untiloffset + messages.lengthreachestotal. Recall and personal-mode mining use Amp's thread search and full thread reader. - Long-running work. Playbooks use Amp child threads, schedules, and native capability webhooks instead of editor polling commands.
- External wakeups. Task-specific plugins use Amp's native
amp.createWebhookAPI. They register stable keys from the plugin entry point, keep capability URLs secret, and make at-least-once effects durably idempotent. - Existing tools. The legacy orchestration ledger and GitHub PR watcher remain Bun tools. The playbooks invoke the watcher through Bun because synced plugin caches do not preserve executable bits. Current PR playbooks use forge-neutral base-branch stacks and do not require Graphite.
poteto extends built-in medium for tools, pins Claude Opus 5.5 at medium reasoning, embeds the complete skills/poteto-mode/SKILL.md as persistent mode instructions, and resolves resource paths through the skill loader. Rebuild and republish the selector after skill edits, then reload the plugin. Shipped delegate seats use explicit per-role models and efforts.
index.ts owns the role map and fallback efforts for bare shipped-model seats. There is no bundled pstack.models.json. A missing plugin file leaves those defaults. Orbs get them with the plugin code. They do not get ~/.config/amp/pstack.models.json unless that file also exists there.
| Seat | Shipped map |
|---|---|
Parent poteto |
Claude Opus 5.5 at medium reasoning; inherits built-in medium tools |
| Hardest | openai/gpt-6.1-sol at xhigh |
| Performance | openai/gpt-6.1-sol at high |
| Feature, bug-fix, why-investigator, swarm-worker | xai/grok-4.7 at high |
| Hillclimb | xai/grok-4.7 at xhigh |
| Refactoring and reflect-tooling | openai/gpt-6.1-sol at high |
| How-explorer | openai/gpt-5.6-luna at low with the premium fast serving feature |
| Judgment, reflect-judgment, reflect-synthesizer | anthropic/claude-opus-5-5 at high |
| How-explainer, why-synthesizer, reflect-divergent, comment-reviewer | anthropic/claude-opus-5-5 at medium |
| Panels and arena cross-judge pool | Opus 5.5 high, GPT-6.1 Sol high, Grok 4.7 xhigh; arena runners use Opus 5.5 medium; one cross-judge runs, preferring a known family different from the parent |
The hardest role is the strongest code-writing seat. It is separate from judgment, which reviews without owning an implementation diff.
Any role can use a concrete provider/model or builtin:low, builtin:medium, builtin:high, or builtin:ultra. A seat may remain a model string or use { "model": "provider/model", "effort": "..." }; panel arrays preserve each seat's model, effort, and order. Configuration layers replace a whole role value rather than merging effort into an earlier string. A model ID picks the weights only. A builtin mode picks Amp's prompt, tools, default model, and thinking. Amp owns all inference routing. Model access and billing follow the user's Amp connections; pstack does not bridge subscriptions or change provider settings. See Modes & Models for current models and reasoning efforts. Cursor thinking slugs such as grok-4.7-fast-xhigh and gpt-6.1-sol-max do not exist in Amp. Bare shipped-model seats use the fallback efforts in MODEL_REASONING_EFFORT; the balanced profile uses explicit effort per role. The standalone grok47-xhigh mode remains xhigh. Cursor inherit-parent and auto are not Amp aliases.
Run amp plugins show-agent-options --json before setup. Its model IDs and capabilities.efforts are the runtime capability table. An explicit unsupported effort for a known shipped model is an error; pstack does not silently downgrade it. Builtin aliases cannot carry a separate effort.
Later wins:
- Balanced defaults in
index.ts. - Optional plugin file
pstack.models.jsonnext toindex.ts, if someone adds one. The repo does not ship it. - User file
~/.config/amp/pstack.models.jsonon that machine. - Amp user config from
pstack_configure_modelssetorprofile. - Workspace file
.amp/pstack.models.jsonin the current repo.
A workspace file is project policy and beats leftover palette config. Reset clears only Amp user config. A missing plugin file adds nothing. User JSON and workspace JSON stay when present. Orb children inherit the plugin code, not a machine-local user JSON.
Every delegate resolves this stack on every spawn. Amp requires custom remote modes to be active before a tool runs, so pstack registers the current role, model, and effort map when the plugin loads and keeps those exact Agents active for the process lifetime. Local launches create an unregistered Agent from the latest configuration, so model and effort changes apply to the next local launch. Reload plugins before the next parent-project-orb or repo-independent-orb launch, including after an effort-only change, so Amp can publish the new modes. native-orb and named-runner redirects name a stable per-role mode instead, such as pstack-feature, and the child orb or runner resolves that mode's model from its own pstack configuration.
To change the map that orbs see, change DEFAULT_MODELS in index.ts, push GitHub, then copy the tree into your Amp user-plugins repo and push that too. GitHub push alone does not update personal plugins.
.amp/pstack.models.example.json is a smaller cheap-plus-high sketch for a machine-local overlay. .amp/pstack.models.json is gitignored. { "profile": "cheap" } alone is valid and cheaper, but parks prose on Grok.
A panel value is a JSON array. Without count, the list length is how many agents pstack_run_panel runs. The defaults use three seats. With count, the tool runs that many candidates and repeats configured seats in order while preserving each seat's effort.
All workers are native Amp threads. These launch targets select where those threads run; explicit placement requests are rejected rather than silently redirected.
pstack_start_agent takes a discriminated launchTarget. current-checkout stays on the current local Amp client or runner. named-runner requires runnerId and returns a guarded native create_thread redirect with executor: "runner", runner_id, the role's stable pstack mode, and optional absolute workingDirectory mapped to working_directory. parent-project-orb and repo-independent-orb create fresh isolated orbs. native-orb remains the adapter for project, size, or custom-mode fields absent from the plugin SDK. Read-only roles (how-explorer, how-explainer, comment-reviewer, and arena-cross-judge) and research roles (why-* and reflect-*) reject a native-orb agentMode override. The override would replace the role's tool allowlist or write exclusion, and the parent's write hook cannot guard a separate orb. arena-cross-judge has stable modes for pool seats 1 to 3 only, so a native redirect that selects a later seat fails. Move that model into the first three seats, or use parent-project-orb. Amp has no cloudBaseBranch. Arbitrary native threads that did not originate from a pstack redirect bypass the live implementation-owner guard.
Amp reports plugin placement as local, remote, or unknown; remote does not mean orb. Pstack probes the Amp-managed-orb lease capability before choosing a default. A remote non-orb process stays on its current runner. Unknown placement fails closed and requires an explicit target.
Implementation roles require scopePaths. Paths identify concrete writable resources; scope remains the human-readable brief. Disjoint paths may run concurrently under one parent. The same logical path set cannot gain a second owner, and prefix-overlapping paths in one workspace serialize.
The current parent can call pstack_stop_agent for any of its durably tracked children, including a nonimplementation background child whose prompt append acknowledgement was uncertain; another parent cannot cancel it. Implementation children additionally hold scope ownership, which is released only after Amp observes terminal idle or error. Background tracking is likewise retained until a terminal state is observed. A named-runner or native-orb redirect must first be paired with the exact child returned by its native create_thread result; an unpaired reservation is not stoppable by child ID.
Every child orb starts from the project remote. It does not receive the parent orb's live filesystem. Keep dependent work in the parent thread, or transfer the required files before the child starts. From a local parent, use current-checkout for uncommitted files, local services, simulators, devices, or machine-only credentials. Use an orb for clean, independent work. Do not push only to make a file visible to an orb unless the user authorized that push.
Panel wait timeout is not candidate completion. Timed-out candidate threads remain pending until they become terminal or are explicitly reconciled. The cross-judge cannot start early. While a judge is live, the parent becomes idle; the judge's report wakes it. A failed judge restores one replacement gate instead of satisfying the design run.
The runtime journal defaults to ~/.config/amp/pstack/runtime-<account>.sqlite; PSTACK_STATE_FILE overrides it for tests. It survives plugin reloads and process restarts on the same persistent executor. It does not migrate state after that executor's disk is lost.
Amp native webhooks are orb-only and at least once. A task-specific plugin must register its stable key from the entry point so reload reinstalls the handler, validate untrusted payloads, and persist event.id atomically with the business effect. Treat the returned URL as a bearer credential and keep it out of chat, commits, and logs.
Named runners must already be live. Amp selects a runner ID but the plugin API does not select among multiple directories served by that runner, so machine-bound workflows must verify the checkout before writing.
The primary skill is poteto-mode. It routes investigation, bug fixes, performance work, features, refactoring, prototypes, visual parity, skill authoring and evaluation, PR babysitting and shipping, autonomous runs, project orchestration, two autopilot variants, session pickup, safe pause, planning, and worktree cleanup.
Direct skills include:
- Understanding:
how,why,teach,recall. - Design and review:
architect,arena,swarm,interrogate,blast-radius. - Execution quality:
tdd,no-comments,unslop,technical-writing,benchmark-checklist. - Memory and customization:
reflect,automate-me,show-me-your-work,correct. - Verification:
create-verification-skill,maintain-verification-skill,create-formal-verification-skillfor a bounded proof of a race or invariant that tests rarely reach.
See the Amp guide for the ten-chapter tutorial: setup, poteto-mode, understanding, design, build, verify, overnight work, principles, making it yours, and recipes.
bun install
bun test
bun run test:tools
bun run typecheck:tools
amp plugins exec . session.start --data '{"thread":{"id":"T-00000000-0000-0000-0000-000000000000"}}'bun install also installs the legacy orchestration and PR-watcher tools under skills/poteto-mode/scripts. Bare bun test, bun run test:tools, and bun run typecheck:tools install that package if it is missing, so a fresh clone does not depend on a hidden node_modules. Tool typecheck uses that package's typescript and bun-types, not a global tsc.
amp plugins list shows the setup-models command, the five pstack tools (start_agent, run_panel, stop_agent, read_current_thread, and configure_models), the generated pstack-* orb adapter modes, and the poteto mode. It does not print export const description. That string is in index.ts and in package.json. Thread setup uses pstack_configure_models with action: "profile" or pstack:setup-pstack. The palette command is optional.
This repository preserves the upstream pstack subtree's Git history. The original work is Copyright Lauren Tan and contributors and is licensed under MIT. The Amp port is also MIT licensed. See LICENSE.