From a137de77dbb57282a7bd226e8915dccffa52f2f2 Mon Sep 17 00:00:00 2001 From: Lee Overy Date: Mon, 24 Aug 2026 08:54:48 +0100 Subject: [PATCH 1/6] Never re-ask what the join prompt already answered MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The instance README's run-it-on-another-machine paste names an existing dex and its repo, but Step 1 unconditionally opened with the new-or- existing question — a session following the join prompt would ask the owner what the owner's own paste had just stated. The interview now takes {mode} and {repo} from the request that brought it here when they are already in it. Co-Authored-By: Claude Fable 5 --- docs/start.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/start.md b/docs/start.md index ae18089..20f64b5 100644 --- a/docs/start.md +++ b/docs/start.md @@ -9,7 +9,9 @@ every blocker loudly and never work around a failure silently. ## Step 1: New or Existing? Ask the owner: "Are we creating a new dex, or setting up an existing one on -this machine?" +this machine?" — unless the request that brought you here already says. An +instance README's join prompt names an existing dex and its repo; never +re-ask what the owner already stated. Set `{mode}` = `new` or `existing`. From 053e8b0f3a56073c5e20a3e3f049d81cbb9604d4 Mon Sep 17 00:00:00 2001 From: Lee Overy Date: Mon, 24 Aug 2026 08:54:58 +0100 Subject: [PATCH 2/6] Pull LFS media on join and anchor commands at the instance root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Driven on a simulated fresh machine: a clone on a box that never ran `git lfs install` globally checks LFS media out as pointer files, and `git lfs install --local` alone does not materialize them — any joined instance with media would read pointers where binaries belong. The join path now runs `git lfs pull` after the local install, with the reason stated. Same step, two smaller defects: the inbox parenthetical claimed it "reconciles waiting captures" (it materializes staged binaries and checks the standing release; text captures wait untouched) and dropped the command's own commit-and-push-now instruction; and the new path's "Commit" bullet never said where, leaving `gh repo create --source .` runnable from {home}. Both paths also set {name}, which Step 5 needs. Co-Authored-By: Claude Fable 5 --- docs/start.md | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/docs/start.md b/docs/start.md index 20f64b5..21184ed 100644 --- a/docs/start.md +++ b/docs/start.md @@ -49,14 +49,19 @@ choosing somewhere else silently. #### If `{mode}` is `existing` -From `{home}`: `gh repo clone {repo}`, then `git lfs install --local` -inside the clone. If the clone is denied, the owner's GitHub account lacks -access to `{repo}` — resolve that with them before anything else. - -Set `{instance}` = the clone's absolute path. Bring its machinery current: -`bin/dex sync` (commit and push if it changed anything), then `bin/dex -inbox` (reconciles waiting captures and verifies the capture staging -release). +From `{home}`: `gh repo clone {repo}`, then inside the clone +`git lfs install --local` and `git lfs pull` — on a machine that never ran +`git lfs install` globally, the clone checks LFS media out as pointer +files, and the pull materializes them. If the clone is denied, the owner's +GitHub account lacks access to `{repo}` — resolve that with them before +anything else. + +Set `{instance}` = the clone's absolute path and `{name}` = its directory +name. Bring its machinery current — from `{instance}`: `bin/dex sync` +(commit and push if it changed anything), then `bin/dex inbox` +(materializes any staged binary captures and checks the standing inbox +release). Follow the inbox output: anything it materialized is committed +and pushed immediately, for the reason it states. → Proceed to **Step 5**. @@ -92,11 +97,11 @@ seed CLAUDE.md and README.md, machinery, git init, local LFS. Then: `/` placeholder in its "Run it on another machine" prompt — that prompt is what a second machine or a second person pastes, so it has to name the real repo. If GitHub was declined, delete the section. -- Commit. If GitHub was wanted: `gh repo create {name} --private --source . - --push`, then `bin/dex inbox ensure` — creates the standing "inbox" - release that binary captures stage into. -- Sanity check: `bin/dex lint` from `{instance}` (prints a fresh-instance - notice). +- Commit — from `{instance}`, like every command from here on. If GitHub + was wanted: `gh repo create {name} --private --source . --push`, then + `bin/dex inbox ensure` — creates the standing "inbox" release that + binary captures stage into. +- Sanity check: `bin/dex lint` (prints a fresh-instance notice). → Proceed to **Step 5**. From 04bc02693dd68a00a85157be455e8daabbcfdbcb Mon Sep 17 00:00:00 2001 From: Lee Overy Date: Mon, 24 Aug 2026 08:55:06 +0100 Subject: [PATCH 3/6] Fit the relocated schedule step to start.md's own frame MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The content moved from first-run.md verbatim, still speaking the skill's dialect: `-run` and "" against this file's {name}/{instance} variables (and {instance} already IS the absolute path), and a task prompt telling the runner to perform an "Every-run procedure" when the skill's heading reads "Every run". The move also dropped the section's closing "do a run now, whatever the host" — the desktop path kept its Run now, the no-desktop path ended setup without ever running the instance. Restored on that bullet. Co-Authored-By: Claude Fable 5 --- docs/start.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/start.md b/docs/start.md index 21184ed..fe6c129 100644 --- a/docs/start.md +++ b/docs/start.md @@ -116,10 +116,10 @@ desktop app (Code tab → Routines → New routine → Local), which runs the instance's dex-run skill on the owner's machine with their full environment. The task: -- Name `-run`; the chosen frequency; instructions exactly: - "Work in the folder . +- Name `{name}-run`; the chosen frequency; instructions exactly: + "Work in the folder {instance}. This is a scheduled, unattended run. Read .claude/skills/dex-run/SKILL.md - and perform its Every-run procedure exactly. Never ask the owner + and perform its Every run section exactly. Never ask the owner questions; report what was done." The first line is load-bearing: task creation from a session cannot set the task's folder (no folder parameter), so the prompt must carry it. @@ -144,7 +144,10 @@ environment. The task: trigger is theirs then — a cron or launchd entry that starts a session in the instance, or nothing at all, since asking for a run does the same work. Record what they chose and move on: an unscheduled instance - is a supported state, not a failed setup. + is a supported state, not a failed setup. Then do the first run + yourself, in this session — read + `{instance}/.claude/skills/dex-run/SKILL.md` and perform its Every run + section — so setup still ends with the instance current. --- From 3da682826bd086fe97f06236895eba3cc94bccf6 Mon Sep 17 00:00:00 2001 From: Lee Overy Date: Mon, 24 Aug 2026 08:55:15 +0100 Subject: [PATCH 4/6] Fetch the shortcut guide raw and gate the capture step MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Step 6 pointed at `docs/shortcut.md`, a path in the engine repo — which the install never clones (the instance runs the engine via uvx), so a session following start.md had nothing at that path. The step now names the raw URL to fetch. It also ran unconditionally, though the interview asks whether the owner wants the shortcut at all and a local-only instance has no repo to capture into — skip conditions stated. The token walkthrough now points at the guide's Before-you-begin section instead of restating its click-path, keeping the expiration and org-repo detail single-homed where the shortcut is built. Co-Authored-By: Claude Fable 5 --- docs/start.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/start.md b/docs/start.md index fe6c129..035a5d9 100644 --- a/docs/start.md +++ b/docs/start.md @@ -153,12 +153,17 @@ environment. The task: ## Step 6: Phone Capture +Skip this step if the owner declined the shortcut, or the instance has no +GitHub repo. Otherwise fetch the shortcut guide — it lives in the engine +repo, which is never cloned, so fetch it raw: +https://raw.githubusercontent.com/leeovery/dex/main/docs/shortcut.md + Each person captures with their own token. Walk them through, concretely: -1. GitHub → Settings → Developer settings → Fine-grained tokens → new token +1. The token, per the guide's **Before you begin** section: fine-grained, scoped to ONLY this instance repo, permissions: Contents R/W. -2. Install the shortcut from the link pinned at the top of - `docs/shortcut.md` — on import it asks for their instances and token. +2. Install the shortcut from the iCloud link at the top of the guide — on + import it asks for their instances and token. 3. Using it: share anything from any app and pick **Send To Dex**. If it isn't in the share sheet, scroll to the very bottom, tap **Edit Actions**, add Send To Dex, and drag it to the top so it's always in From 5cb27d443779aec8bc816613a83ac7277fcf991c Mon Sep 17 00:00:00 2001 From: Lee Overy Date: Mon, 24 Aug 2026 08:55:23 +0100 Subject: [PATCH 5/6] State the materialization order inbox enforces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The protocol doc said inbox rewrites the capture's frontmatter and then deletes the asset — the code's order is LFS-verify, delete, rewrite, and inbox.py calls it load-bearing: the verify precedes the delete so a binary that failed to stage never loses its only remote copy, and the pointer rewrite lands last so an interrupted run re-enters cleanly. A client author reasoning about the orphaned-asset failure mode needs the real sequence. Co-Authored-By: Claude Fable 5 --- docs/capture.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/capture.md b/docs/capture.md index d70b2c5..8ebb207 100644 --- a/docs/capture.md +++ b/docs/capture.md @@ -79,10 +79,11 @@ creates it), and the capture file points at it: the note ``` -At the next run, `bin/dex inbox` downloads the asset into `media//` -(where LFS applies), rewrites the capture's frontmatter to `media:`, and -deletes the asset. End state: media in LFS, git history text-only, release -empty. +At the next run, `bin/dex inbox` downloads the asset into `media//`, +verifies it staged under LFS, deletes the asset, and rewrites the capture's +frontmatter to `media:` — in that order, so a binary that failed to stage +never loses its only remote copy. End state: media in LFS, git history +text-only, release empty. ## curl reference implementation From af5b8dc2f50e936201f39f61bcd31ce6c445183c Mon Sep 17 00:00:00 2001 From: Lee Overy Date: Mon, 24 Aug 2026 08:55:23 +0100 Subject: [PATCH 6/6] List the synced machinery in the instance layout The under-the-hood section opens on the bin/dex shim and the synced skills, then gave an instance layout with neither .claude/ nor bin/ in it. Both listed now, and CLAUDE.md's gloss matches what the seed holds: identity and scope, importing the synced contract. Co-Authored-By: Claude Fable 5 --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f98a159..a67dbda 100644 --- a/README.md +++ b/README.md @@ -308,11 +308,13 @@ sessions: the PUT is the commit, and the next run moves staged binaries into `media/` where LFS applies. Suggestion is untrusted by design, so scope filtering happens at processing time, inside the instance. Full protocol: `docs/capture.md`. -Instance layout: `CLAUDE.md` (scope and operations contract) · `inbox/` (pending -captures) · `raw/` (verbatim exports) · `corpus/` (append-only items) · -`enrichment/` · `media/` (captured binaries, LFS) · `wiki/` -(topics/entities/syntheses plus index, log, pins) · `state/` (digests, taxonomy, -the ledger and other append-only JSONL, config.json) · `cache/` (gitignored -ephemera) · `.dex-engine-pin` (the engine release this instance runs). +Instance layout: `CLAUDE.md` (identity and scope; imports the synced contract) · +`.claude/` (synced skills + `dex-contract.md`) · `bin/dex` (the shim) · +`inbox/` (pending captures) · `raw/` (verbatim exports) · `corpus/` +(append-only items) · `enrichment/` · `media/` (captured binaries, LFS) · +`wiki/` (topics/entities/syntheses plus index, log, pins) · `state/` (digests, +taxonomy, the ledger and other append-only JSONL, config.json) · `cache/` +(gitignored ephemera) · `.dex-engine-pin` (the engine release this instance +runs).