office: open a lazygit session on the machine that owns the folder, and stop overwriting a working wrapper
This commit is contained in:
@@ -1663,3 +1663,105 @@ And for the record: the `office` commands no longer need any of this. They read
|
|||||||
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-home-2026-11-12-22-47-55|Rich discovery: home 2026-11-12 22:47:55]]
|
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-home-2026-11-12-22-47-55|Rich discovery: home 2026-11-12 22:47:55]]
|
||||||
- context: [[packs/paperclip-harness/20-context/home|home]]
|
- context: [[packs/paperclip-harness/20-context/home|home]]
|
||||||
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|home repository structure and configuration patterns]]
|
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|home repository structure and configuration patterns]]
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Update (2026-11-12 23:34:09)
|
||||||
|
|
||||||
|
## Rich discovery update (2026-11-12 23:34:09)
|
||||||
|
|
||||||
|
## The problem was `sudo`, not the command
|
||||||
|
|
||||||
|
```
|
||||||
|
/home/sam/.local/bin/office: line 3: /root/.local/share/paperclip-harness/bin/office: No such file or directory
|
||||||
|
```
|
||||||
|
|
||||||
|
`sudo` sets `HOME=/root`, so the wrapper's `$HOME/.local/share/...` pointed at a directory that does not exist. The command underneath was fine.
|
||||||
|
|
||||||
|
**`office` never needed `sudo`, and must not have it.** It is a user command in three ways:
|
||||||
|
|
||||||
|
| it needs | why root cannot have it |
|
||||||
|
|---|---|
|
||||||
|
| your Paperclip key | it is in **your** `~/.config/environment.d`, not root's |
|
||||||
|
| **your** TUIOS daemon | the daemon socket lives in your runtime directory; root talks to a different one |
|
||||||
|
| files you will edit | anything written as root would be owned by root in your home |
|
||||||
|
|
||||||
|
So: no `sudo`.
|
||||||
|
|
||||||
|
## Two things I changed so this cannot bite again
|
||||||
|
|
||||||
|
**1. The wrapper now refuses root, clearly.**
|
||||||
|
|
||||||
|
```sh
|
||||||
|
if [ "$(id -u)" = "0" ]; then
|
||||||
|
echo "office: run this as your own user, not with sudo." >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. The wrapper no longer uses `$HOME`.** The installation writes the real path out in full, so `sudo` cannot make it look for a copy that is not there:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
exec "/home/sam/.local/share/paperclip-harness/bin/office" "$@"
|
||||||
|
```
|
||||||
|
|
||||||
|
The same guard is inside `office` itself, so a copy invoked directly as root refuses the same way rather than half-working. Both are on `.13`, `.27` and `.51`.
|
||||||
|
|
||||||
|
## Your command, corrected
|
||||||
|
|
||||||
|
```sh
|
||||||
|
office ~/TEST-BETA --new "TEST-BETA" --host nixos-desktop --session TEST-BETA
|
||||||
|
```
|
||||||
|
|
||||||
|
I dry-ran exactly that from `.27` and it resolves:
|
||||||
|
|
||||||
|
```
|
||||||
|
worktrees: no — this is not a repository
|
||||||
|
would write /home/sam/TEST-BETA/.harness/harness.toml
|
||||||
|
would create or reuse session 'TEST-BETA' and build eight panes there
|
||||||
|
|
||||||
|
switch to it: tuios attach --host nixos-desktop TEST-BETA
|
||||||
|
```
|
||||||
|
|
||||||
|
`--session TEST-BETA` is fine — no clash with `security`.
|
||||||
|
|
||||||
|
Two things will happen when you run it for real:
|
||||||
|
|
||||||
|
1. It will find that `/home/sam/TEST-BETA` is **not a git repository** and ask **Y or N**, because that decides whether each task gets its own branch and worktree. Y makes the repository, writes `.gitignore` with `.paperclip/`, stages everything, and stops so you can commit in lazygit. N creates the project in place with no diff and no merge.
|
||||||
|
2. If you would rather not be asked, `--git-init` means Y, and `--commit-all` means Y and commit in one step.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
office ~/TEST-BETA --new "TEST-BETA" --host nixos-desktop --session TEST-BETA --git-init
|
||||||
|
```
|
||||||
|
|
||||||
|
## After it is created
|
||||||
|
|
||||||
|
```sh
|
||||||
|
tuios attach --host nixos-desktop TEST-BETA
|
||||||
|
```
|
||||||
|
|
||||||
|
Then `Project>project` → `(` for the **git** tab to see the state, `g` for lazygit in the folder, `t` for the other tools. If you answered Y, the top of every pane will carry the warning line until you commit — that line is what tells you the worktrees are not real yet.
|
||||||
|
|
||||||
|
Committed: `paperclip-harness` `fd71837`, pushed, and copied to `.27` and `.51`.
|
||||||
|
|
||||||
|
## Source paths observed
|
||||||
|
|
||||||
|
- `home/sam/.local/bin/office`
|
||||||
|
- `root/.local/share/paperclip-harness/bin/office`
|
||||||
|
- `home/sam/paseo/projects/paperclip-harness/bin/office`
|
||||||
|
- `home/sam/.local/share/paperclip-harness/bin/office`
|
||||||
|
- `home/sam/TEST-BETA/.harness/harness.toml`
|
||||||
|
- `HOME/.local/share/`
|
||||||
|
- `home/sam/TEST-BETA`
|
||||||
|
|
||||||
|
## Evidence
|
||||||
|
|
||||||
|
- Confidence: 84%
|
||||||
|
- Reason: Update component/repository context with detailed discovered structure and configuration
|
||||||
|
|
||||||
|
## Related learned memories <!-- same-turn-2026-11-12 23:34:09 -->
|
||||||
|
|
||||||
|
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-would-2026-11-12-23-34-09|Rich discovery: would 2026-11-12 23:34:09]]
|
||||||
|
- context: [[packs/paperclip-harness/20-context/home|would]]
|
||||||
|
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|would repository structure and configuration patterns]]
|
||||||
|
|||||||
@@ -7012,3 +7012,105 @@ All committed and pushed: `paperclip-harness` `32fb356`, `nixos-4screen` `587db3
|
|||||||
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-local-2026-11-12-23-03-35|Rich discovery: .local 2026-11-12 23:03:35]]
|
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-local-2026-11-12-23-03-35|Rich discovery: .local 2026-11-12 23:03:35]]
|
||||||
- context: [[packs/paperclip-harness/20-context/paperclip-harness|.local]]
|
- context: [[packs/paperclip-harness/20-context/paperclip-harness|.local]]
|
||||||
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|.local repository structure and configuration patterns]]
|
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|.local repository structure and configuration patterns]]
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Update (2026-11-12 23:34:09)
|
||||||
|
|
||||||
|
## Structural/configuration observations (2026-11-12 23:34:09)
|
||||||
|
|
||||||
|
## The problem was `sudo`, not the command
|
||||||
|
|
||||||
|
```
|
||||||
|
/home/sam/.local/bin/office: line 3: /root/.local/share/paperclip-harness/bin/office: No such file or directory
|
||||||
|
```
|
||||||
|
|
||||||
|
`sudo` sets `HOME=/root`, so the wrapper's `$HOME/.local/share/...` pointed at a directory that does not exist. The command underneath was fine.
|
||||||
|
|
||||||
|
**`office` never needed `sudo`, and must not have it.** It is a user command in three ways:
|
||||||
|
|
||||||
|
| it needs | why root cannot have it |
|
||||||
|
|---|---|
|
||||||
|
| your Paperclip key | it is in **your** `~/.config/environment.d`, not root's |
|
||||||
|
| **your** TUIOS daemon | the daemon socket lives in your runtime directory; root talks to a different one |
|
||||||
|
| files you will edit | anything written as root would be owned by root in your home |
|
||||||
|
|
||||||
|
So: no `sudo`.
|
||||||
|
|
||||||
|
## Two things I changed so this cannot bite again
|
||||||
|
|
||||||
|
**1. The wrapper now refuses root, clearly.**
|
||||||
|
|
||||||
|
```sh
|
||||||
|
if [ "$(id -u)" = "0" ]; then
|
||||||
|
echo "office: run this as your own user, not with sudo." >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. The wrapper no longer uses `$HOME`.** The installation writes the real path out in full, so `sudo` cannot make it look for a copy that is not there:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
exec "/home/sam/.local/share/paperclip-harness/bin/office" "$@"
|
||||||
|
```
|
||||||
|
|
||||||
|
The same guard is inside `office` itself, so a copy invoked directly as root refuses the same way rather than half-working. Both are on `.13`, `.27` and `.51`.
|
||||||
|
|
||||||
|
## Your command, corrected
|
||||||
|
|
||||||
|
```sh
|
||||||
|
office ~/TEST-BETA --new "TEST-BETA" --host nixos-desktop --session TEST-BETA
|
||||||
|
```
|
||||||
|
|
||||||
|
I dry-ran exactly that from `.27` and it resolves:
|
||||||
|
|
||||||
|
```
|
||||||
|
worktrees: no — this is not a repository
|
||||||
|
would write /home/sam/TEST-BETA/.harness/harness.toml
|
||||||
|
would create or reuse session 'TEST-BETA' and build eight panes there
|
||||||
|
|
||||||
|
switch to it: tuios attach --host nixos-desktop TEST-BETA
|
||||||
|
```
|
||||||
|
|
||||||
|
`--session TEST-BETA` is fine — no clash with `security`.
|
||||||
|
|
||||||
|
Two things will happen when you run it for real:
|
||||||
|
|
||||||
|
1. It will find that `/home/sam/TEST-BETA` is **not a git repository** and ask **Y or N**, because that decides whether each task gets its own branch and worktree. Y makes the repository, writes `.gitignore` with `.paperclip/`, stages everything, and stops so you can commit in lazygit. N creates the project in place with no diff and no merge.
|
||||||
|
2. If you would rather not be asked, `--git-init` means Y, and `--commit-all` means Y and commit in one step.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
office ~/TEST-BETA --new "TEST-BETA" --host nixos-desktop --session TEST-BETA --git-init
|
||||||
|
```
|
||||||
|
|
||||||
|
## After it is created
|
||||||
|
|
||||||
|
```sh
|
||||||
|
tuios attach --host nixos-desktop TEST-BETA
|
||||||
|
```
|
||||||
|
|
||||||
|
Then `Project>project` → `(` for the **git** tab to see the state, `g` for lazygit in the folder, `t` for the other tools. If you answered Y, the top of every pane will carry the warning line until you commit — that line is what tells you the worktrees are not real yet.
|
||||||
|
|
||||||
|
Committed: `paperclip-harness` `fd71837`, pushed, and copied to `.27` and `.51`.
|
||||||
|
|
||||||
|
## Source paths observed
|
||||||
|
|
||||||
|
- `home/sam/.local/bin/office`
|
||||||
|
- `root/.local/share/paperclip-harness/bin/office`
|
||||||
|
- `home/sam/paseo/projects/paperclip-harness/bin/office`
|
||||||
|
- `home/sam/.local/share/paperclip-harness/bin/office`
|
||||||
|
- `home/sam/TEST-BETA/.harness/harness.toml`
|
||||||
|
- `HOME/.local/share/`
|
||||||
|
- `home/sam/TEST-BETA`
|
||||||
|
|
||||||
|
## Evidence
|
||||||
|
|
||||||
|
- Confidence: 82%
|
||||||
|
- Reason: Captured factual repo structure/configuration patterns from rich discovery
|
||||||
|
|
||||||
|
## Related learned memories <!-- same-turn-2026-11-12 23:34:09 -->
|
||||||
|
|
||||||
|
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-would-2026-11-12-23-34-09|Rich discovery: would 2026-11-12 23:34:09]]
|
||||||
|
- context: [[packs/paperclip-harness/20-context/home|would]]
|
||||||
|
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|would repository structure and configuration patterns]]
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
---
|
||||||
|
type: session
|
||||||
|
id: session.paperclip-harness.rich-discovery-would-2026-11-12-23-34-09
|
||||||
|
title: Rich discovery: would 2026-11-12 23:34:09
|
||||||
|
status: active
|
||||||
|
source_of_truth: false
|
||||||
|
freshness: current
|
||||||
|
last_reviewed: 2026-11-12
|
||||||
|
tags:
|
||||||
|
- pack/paperclip-harness
|
||||||
|
- agent-memory/session
|
||||||
|
- autolearn
|
||||||
|
- rich-discovery
|
||||||
|
- repo/would
|
||||||
|
---
|
||||||
|
|
||||||
|
# Rich discovery: would 2026-11-12 23:34:09
|
||||||
|
|
||||||
|
Sanitized rich discovery snapshot captured automatically from the completed turn.
|
||||||
|
|
||||||
|
|
||||||
|
## Source paths observed
|
||||||
|
|
||||||
|
- `home/sam/.local/bin/office`
|
||||||
|
- `root/.local/share/paperclip-harness/bin/office`
|
||||||
|
- `home/sam/paseo/projects/paperclip-harness/bin/office`
|
||||||
|
- `home/sam/.local/share/paperclip-harness/bin/office`
|
||||||
|
- `home/sam/TEST-BETA/.harness/harness.toml`
|
||||||
|
- `HOME/.local/share/`
|
||||||
|
- `home/sam/TEST-BETA`
|
||||||
|
|
||||||
|
## Final answer snapshot
|
||||||
|
|
||||||
|
## The problem was `sudo`, not the command
|
||||||
|
|
||||||
|
```
|
||||||
|
/home/sam/.local/bin/office: line 3: /root/.local/share/paperclip-harness/bin/office: No such file or directory
|
||||||
|
```
|
||||||
|
|
||||||
|
`sudo` sets `HOME=/root`, so the wrapper's `$HOME/.local/share/...` pointed at a directory that does not exist. The command underneath was fine.
|
||||||
|
|
||||||
|
**`office` never needed `sudo`, and must not have it.** It is a user command in three ways:
|
||||||
|
|
||||||
|
| it needs | why root cannot have it |
|
||||||
|
|---|---|
|
||||||
|
| your Paperclip key | it is in **your** `~/.config/environment.d`, not root's |
|
||||||
|
| **your** TUIOS daemon | the daemon socket lives in your runtime directory; root talks to a different one |
|
||||||
|
| files you will edit | anything written as root would be owned by root in your home |
|
||||||
|
|
||||||
|
So: no `sudo`.
|
||||||
|
|
||||||
|
## Two things I changed so this cannot bite again
|
||||||
|
|
||||||
|
**1. The wrapper now refuses root, clearly.**
|
||||||
|
|
||||||
|
```sh
|
||||||
|
if [ "$(id -u)" = "0" ]; then
|
||||||
|
echo "office: run this as your own user, not with sudo." >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. The wrapper no longer uses `$HOME`.** The installation writes the real path out in full, so `sudo` cannot make it look for a copy that is not there:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
exec "/home/sam/.local/share/paperclip-harness/bin/office" "$@"
|
||||||
|
```
|
||||||
|
|
||||||
|
The same guard is inside `office` itself, so a copy invoked directly as root refuses the same way rather than half-working. Both are on `.13`, `.27` and `.51`.
|
||||||
|
|
||||||
|
## Your command, corrected
|
||||||
|
|
||||||
|
```sh
|
||||||
|
office ~/TEST-BETA --new "TEST-BETA" --host nixos-desktop --session TEST-BETA
|
||||||
|
```
|
||||||
|
|
||||||
|
I dry-ran exactly that from `.27` and it resolves:
|
||||||
|
|
||||||
|
```
|
||||||
|
worktrees: no — this is not a repository
|
||||||
|
would write /home/sam/TEST-BETA/.harness/harness.toml
|
||||||
|
would create or reuse session 'TEST-BETA' and build eight panes there
|
||||||
|
|
||||||
|
switch to it: tuios attach --host nixos-desktop TEST-BETA
|
||||||
|
```
|
||||||
|
|
||||||
|
`--session TEST-BETA` is fine — no clash with `security`.
|
||||||
|
|
||||||
|
Two things will happen when you run it for real:
|
||||||
|
|
||||||
|
1. It will find that `/home/sam/TEST-BETA` is **not a git repository** and ask **Y or N**, because that decides whether each task gets its own branch and worktree. Y makes the repository, writes `.gitignore` with `.paperclip/`, stages everything, and stops so you can commit in lazygit. N creates the project in place with no diff and no merge.
|
||||||
|
2. If you would rather not be asked, `--git-init` means Y, and `--commit-all` means Y and commit in one step.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
office ~/TEST-BETA --new "TEST-BETA" --host nixos-desktop --session TEST-BETA --git-init
|
||||||
|
```
|
||||||
|
|
||||||
|
## After it is created
|
||||||
|
|
||||||
|
```sh
|
||||||
|
tuios attach --host nixos-desktop TEST-BETA
|
||||||
|
```
|
||||||
|
|
||||||
|
Then `Project>project` → `(` for the **git** tab to see the state, `g` for lazygit in the folder, `t` for the other tools. If you answered Y, the top of every pane will carry the warning line until you commit — that line is what tells you the worktrees are not real yet.
|
||||||
|
|
||||||
|
Committed: `paperclip-harness` `fd71837`, pushed, and copied to `.27` and `.51`.
|
||||||
|
|
||||||
|
## Evidence
|
||||||
|
|
||||||
|
- Confidence: 86%
|
||||||
|
- Reason: Preserve full sanitized discovery detail from a rich investigation turn
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [[packs/paperclip-harness/00-system/pi-agent/memory-manifest|Memory Manifest]]
|
||||||
|
|
||||||
|
## Related learned memories <!-- same-turn-2026-11-12 23:34:09 -->
|
||||||
|
|
||||||
|
- session: [[packs/paperclip-harness/80-sessions/rich-discovery-would-2026-11-12-23-34-09|Rich discovery: would 2026-11-12 23:34:09]]
|
||||||
|
- context: [[packs/paperclip-harness/20-context/home|would]]
|
||||||
|
- observation: [[packs/paperclip-harness/60-observations/tmp-repository-structure-and-configuration-patterns|would repository structure and configuration patterns]]
|
||||||
71
bin/office
71
bin/office
@@ -47,14 +47,16 @@ def parse(argv):
|
|||||||
opts = {"folder": ".", "folder_given": False, "project": "", "session": "",
|
opts = {"folder": ".", "folder_given": False, "project": "", "session": "",
|
||||||
"dry": False, "host": "", "no_switch": False, "new": "", "remote": "",
|
"dry": False, "host": "", "no_switch": False, "new": "", "remote": "",
|
||||||
"git_init": "--git-init" in argv, "anywhere": "--anywhere" in argv,
|
"git_init": "--git-init" in argv, "anywhere": "--anywhere" in argv,
|
||||||
"commit_all": "--commit-all" in argv, "git_init_commits": False}
|
"commit_all": "--commit-all" in argv, "git_init_commits": False,
|
||||||
|
"client_host": ""}
|
||||||
positional = []
|
positional = []
|
||||||
i = 0
|
i = 0
|
||||||
while i < len(argv):
|
while i < len(argv):
|
||||||
a = argv[i]
|
a = argv[i]
|
||||||
if a in ("--project", "--session", "--host", "--new", "--remote"):
|
if a in ("--project", "--session", "--host", "--new", "--remote", "--client-host"):
|
||||||
if i + 1 < len(argv):
|
if i + 1 < len(argv):
|
||||||
opts[a[2:]] = argv[i + 1]
|
# Keys are Python names, so a flag with a hyphen becomes an underscore.
|
||||||
|
opts[a[2:].replace("-", "_")] = argv[i + 1]
|
||||||
i += 2
|
i += 2
|
||||||
continue
|
continue
|
||||||
i += 1
|
i += 1
|
||||||
@@ -146,6 +148,45 @@ def ensure_session(session, folder):
|
|||||||
h.say("session: %s (created; switch to it with TUIOS's session switcher)" % session)
|
h.say("session: %s (created; switch to it with TUIOS's session switcher)" % session)
|
||||||
|
|
||||||
|
|
||||||
|
def open_git_session(folder, session, opts):
|
||||||
|
"""A session with lazygit already open in the folder, on the machine that has it.
|
||||||
|
|
||||||
|
The commit has to happen where the files are, and that machine is often not
|
||||||
|
the one being typed at. A session on that machine is how the person gets
|
||||||
|
there from TUIOS, which is the whole point of this program: one attach, no
|
||||||
|
ssh, no cd.
|
||||||
|
"""
|
||||||
|
helper = session + "-git"
|
||||||
|
created = ensure_session_quiet(helper, folder)
|
||||||
|
# The pane a tool needs a PATH of its own: a pane started this way does not
|
||||||
|
# inherit an interactive shell's.
|
||||||
|
prelude = ('export PATH="$HOME/.local/bin:$HOME/.nix-profile/bin:'
|
||||||
|
'/run/current-system/sw/bin:/etc/profiles/per-user/$USER/bin:$PATH"; ')
|
||||||
|
tuios.open_pane("git", "Git", folder, prelude + "exec lazygit", helper)
|
||||||
|
h.say("")
|
||||||
|
h.say(" A session called %r now holds lazygit in that folder%s." % (helper, "" if created else " (it was already there)"))
|
||||||
|
h.say(" Attach to it, stage and commit, then come back and repeat the command:")
|
||||||
|
h.say("")
|
||||||
|
client = opts.get("client_host") or ""
|
||||||
|
h.say(" tuios attach%s %s" % (" --host " + client if client else "", helper))
|
||||||
|
h.say("")
|
||||||
|
h.say(" When you are done with it: tuios kill-session %s" % helper)
|
||||||
|
return helper
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_session_quiet(session, folder):
|
||||||
|
"""ensure_session, without the line about switching: the caller explains."""
|
||||||
|
if session in tuios.sessions():
|
||||||
|
return False
|
||||||
|
params = {"name": session, "cwd": folder, "window": False}
|
||||||
|
out = subprocess.run(["tuios", "call", "new-session", json.dumps(params)],
|
||||||
|
capture_output=True, text=True, timeout=60)
|
||||||
|
if out.returncode != 0 and "session_exists" not in (out.stderr or out.stdout):
|
||||||
|
raise h.Refused(3, "could not create session %r: %s"
|
||||||
|
% (session, (out.stderr or out.stdout).strip()[:300]))
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def scaffold(folder, name):
|
def scaffold(folder, name):
|
||||||
"""Write the files this project keeps, and only the ones that are missing.
|
"""Write the files this project keeps, and only the ones that are missing.
|
||||||
|
|
||||||
@@ -237,6 +278,15 @@ def install_wrapper(addr, remote_bin):
|
|||||||
capture_output=True, text=True, timeout=60).stdout.strip()
|
capture_output=True, text=True, timeout=60).stdout.strip()
|
||||||
if not home:
|
if not home:
|
||||||
return
|
return
|
||||||
|
# Never replace a wrapper that already works. Pushing from another machine
|
||||||
|
# would otherwise rewrite the owner's own `office` command to point at the
|
||||||
|
# copy that machine sent, which is how the canonical machine ended up
|
||||||
|
# running someone else's older copy.
|
||||||
|
existing = subprocess.run(
|
||||||
|
["ssh", "-o", "BatchMode=yes", addr, 'cat "$HOME/.local/bin/office" 2>/dev/null'],
|
||||||
|
capture_output=True, text=True, timeout=60).stdout
|
||||||
|
if "paperclip-harness/bin/office" in existing:
|
||||||
|
return
|
||||||
script = ("#!/bin/sh\n"
|
script = ("#!/bin/sh\n"
|
||||||
"# Written by office on another machine. Runs the copy it keeps here.\n"
|
"# Written by office on another machine. Runs the copy it keeps here.\n"
|
||||||
"#\n"
|
"#\n"
|
||||||
@@ -291,6 +341,9 @@ def run_on_remote(host, folder, opts):
|
|||||||
for flag in ("--git-init", "--commit-all", "--anywhere"):
|
for flag in ("--git-init", "--commit-all", "--anywhere"):
|
||||||
if opts.get(flag[2:].replace("-", "_")):
|
if opts.get(flag[2:].replace("-", "_")):
|
||||||
inner.append(flag)
|
inner.append(flag)
|
||||||
|
# So the instructions printed on the other machine say how to reach it from
|
||||||
|
# where the person is sitting.
|
||||||
|
inner += ["--client-host", host]
|
||||||
if opts["dry"]:
|
if opts["dry"]:
|
||||||
inner.append("--dry")
|
inner.append("--dry")
|
||||||
# "$HOME" must stay unquoted so the other machine's shell expands it; every
|
# "$HOME" must stay unquoted so the other machine's shell expands it; every
|
||||||
@@ -410,6 +463,12 @@ ON ANOTHER MACHINE
|
|||||||
is not on PATH yet, so there you call it by its full path:
|
is not on PATH yet, so there you call it by its full path:
|
||||||
~/.local/share/paperclip-harness/bin/office <folder>
|
~/.local/share/paperclip-harness/bin/office <folder>
|
||||||
|
|
||||||
|
WHEN THE FILES ARE ON ANOTHER MACHINE
|
||||||
|
The git work has to happen where the files are, because that is where the
|
||||||
|
commit, the worktree and the agent are. So when a folder cannot hold a
|
||||||
|
worktree yet, office makes a session on THAT machine with lazygit already
|
||||||
|
open in the folder, and tells you how to attach to it. No ssh, no cd.
|
||||||
|
|
||||||
AFTER A REBOOT
|
AFTER A REBOOT
|
||||||
TUIOS restores a session with a fresh shell in every pane and keeps the pane
|
TUIOS restores a session with a fresh shell in every pane and keeps the pane
|
||||||
names. Run board once for that project: it checks what each pane is actually
|
names. Run board once for that project: it checks what each pane is actually
|
||||||
@@ -482,7 +541,7 @@ def repeat_command(folder, opts):
|
|||||||
return " ".join(parts)
|
return " ".join(parts)
|
||||||
|
|
||||||
|
|
||||||
def prepare_git(folder, opts):
|
def prepare_git(folder, opts, session):
|
||||||
"""Get the folder as far as it can go toward a worktree per task.
|
"""Get the folder as far as it can go toward a worktree per task.
|
||||||
|
|
||||||
A worktree needs a repository and at least one commit. Neither is made
|
A worktree needs a repository and at least one commit. Neither is made
|
||||||
@@ -568,6 +627,8 @@ def prepare_git(folder, opts):
|
|||||||
h.say(" space stage or unstage e edit a file, .gitignore included")
|
h.say(" space stage or unstage e edit a file, .gitignore included")
|
||||||
h.say(" c commit ? every key")
|
h.say(" c commit ? every key")
|
||||||
h.say("")
|
h.say("")
|
||||||
|
open_git_session(folder, session, opts)
|
||||||
|
h.say("")
|
||||||
h.say(" Then repeat this command to create the project with worktrees:")
|
h.say(" Then repeat this command to create the project with worktrees:")
|
||||||
h.say("")
|
h.say("")
|
||||||
h.say(" %s" % repeat_command(folder, opts))
|
h.say(" %s" % repeat_command(folder, opts))
|
||||||
@@ -643,7 +704,7 @@ def main():
|
|||||||
# Only now: a folder on another machine has already been handed over, and
|
# Only now: a folder on another machine has already been handed over, and
|
||||||
# the machine that owns it does these two checks itself.
|
# the machine that owns it does these two checks itself.
|
||||||
guard_machine(folder, opts)
|
guard_machine(folder, opts)
|
||||||
ready = prepare_git(folder, opts)
|
ready = prepare_git(folder, opts, session)
|
||||||
|
|
||||||
if opts["dry"]:
|
if opts["dry"]:
|
||||||
if opts["new"]:
|
if opts["new"]:
|
||||||
|
|||||||
Reference in New Issue
Block a user