llar 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- llar-0.1.1/LICENSE +21 -0
- llar-0.1.1/PKG-INFO +311 -0
- llar-0.1.1/README.md +284 -0
- llar-0.1.1/pyproject.toml +69 -0
- llar-0.1.1/pyproject.toml.orig +55 -0
- llar-0.1.1/src/llar/__init__.py +2 -0
- llar-0.1.1/src/llar/__main__.py +7 -0
- llar-0.1.1/src/llar/cli.py +646 -0
- llar-0.1.1/src/llar/core/__init__.py +2 -0
- llar-0.1.1/src/llar/core/activity.py +32 -0
- llar-0.1.1/src/llar/core/associations.py +271 -0
- llar-0.1.1/src/llar/core/atomic.py +38 -0
- llar-0.1.1/src/llar/core/context.py +36 -0
- llar-0.1.1/src/llar/core/conversations.py +93 -0
- llar-0.1.1/src/llar/core/coverage.py +293 -0
- llar-0.1.1/src/llar/core/doctor.py +72 -0
- llar-0.1.1/src/llar/core/file_copy.py +431 -0
- llar-0.1.1/src/llar/core/inspection.py +40 -0
- llar-0.1.1/src/llar/core/inventory.py +41 -0
- llar-0.1.1/src/llar/core/scope.py +29 -0
- llar-0.1.1/src/llar/core/snapshot.py +94 -0
- llar-0.1.1/src/llar/core/ssh.py +335 -0
- llar-0.1.1/src/llar/core/ssh_receiver.py +161 -0
- llar-0.1.1/src/llar/core/ssh_transfer.py +306 -0
- llar-0.1.1/src/llar/core/state.py +185 -0
- llar-0.1.1/src/llar/core/transfer_plan.py +725 -0
- llar-0.1.1/src/llar/core/transfers.py +206 -0
- llar-0.1.1/src/llar/harnesses/__init__.py +8 -0
- llar-0.1.1/src/llar/harnesses/base.py +19 -0
- llar-0.1.1/src/llar/harnesses/claude/__init__.py +121 -0
- llar-0.1.1/src/llar/harnesses/claude/activity.py +80 -0
- llar-0.1.1/src/llar/harnesses/claude/copy.py +577 -0
- llar-0.1.1/src/llar/harnesses/claude/locking.py +136 -0
- llar-0.1.1/src/llar/harnesses/claude/paths.py +18 -0
- llar-0.1.1/src/llar/harnesses/claude/records.py +220 -0
- llar-0.1.1/src/llar/harnesses/claude/state.py +385 -0
- llar-0.1.1/src/llar/harnesses/claude/transfer.py +131 -0
- llar-0.1.1/src/llar/harnesses/codex/Apache-2.0.txt +201 -0
- llar-0.1.1/src/llar/harnesses/codex/NOTICE +6 -0
- llar-0.1.1/src/llar/harnesses/codex/__init__.py +96 -0
- llar-0.1.1/src/llar/harnesses/codex/activity.py +75 -0
- llar-0.1.1/src/llar/harnesses/codex/copy.py +355 -0
- llar-0.1.1/src/llar/harnesses/codex/database.py +155 -0
- llar-0.1.1/src/llar/harnesses/codex/import_state.py +481 -0
- llar-0.1.1/src/llar/harnesses/codex/native-schema.json +621 -0
- llar-0.1.1/src/llar/harnesses/codex/publication.py +108 -0
- llar-0.1.1/src/llar/harnesses/codex/schemas.json +501 -0
- llar-0.1.1/src/llar/harnesses/codex/schemas.py +38 -0
- llar-0.1.1/src/llar/harnesses/codex/state.py +519 -0
- llar-0.1.1/src/llar/harnesses/codex/transfer.py +100 -0
- llar-0.1.1/src/llar/harnesses/transfers.py +91 -0
llar-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 All Tuner
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
llar-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: llar
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Look after the local state coding agents keep about your projects.
|
|
5
|
+
Keywords: claude,codex,sessions,developer-tools,cli
|
|
6
|
+
Author: All Tuner
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: MacOS
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
17
|
+
Classifier: Topic :: Software Development
|
|
18
|
+
Classifier: Topic :: Utilities
|
|
19
|
+
Requires-Dist: psutil>=7.2.2
|
|
20
|
+
Requires-Dist: typer>=0.27.3
|
|
21
|
+
Requires-Python: >=3.12
|
|
22
|
+
Project-URL: Homepage, https://github.com/alltuner/llar
|
|
23
|
+
Project-URL: Repository, https://github.com/alltuner/llar
|
|
24
|
+
Project-URL: Issues, https://github.com/alltuner/llar/issues
|
|
25
|
+
Project-URL: Documentation, https://github.com/alltuner/llar#readme
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# llar
|
|
29
|
+
|
|
30
|
+
Inspect and copy the project state that Claude Code and Codex keep outside your
|
|
31
|
+
checkout.
|
|
32
|
+
|
|
33
|
+
Moving a repository does not move its conversations, memories, or path-based
|
|
34
|
+
settings. llar discovers that state, explains its ownership, and plans transfers.
|
|
35
|
+
Supported copies can then be applied explicitly.
|
|
36
|
+
|
|
37
|
+
*Llar* is Catalan for home or hearth. The project is under active development;
|
|
38
|
+
the table below describes implemented support, not the eventual command surface.
|
|
39
|
+
|
|
40
|
+
## What works today
|
|
41
|
+
|
|
42
|
+
| Operation | Support |
|
|
43
|
+
|---|---|
|
|
44
|
+
| Inspect projects, explicit trust, sessions, activity, and storage locations | Claude Code and Codex |
|
|
45
|
+
| Diagnose missing directories and unresolved state | Read-only |
|
|
46
|
+
| Copy project files locally | Explicit file selection |
|
|
47
|
+
| Copy project files over SSH | Push or pull, one remote endpoint |
|
|
48
|
+
| Copy Claude project state locally | Recognized settings, history, sessions, memory, and artifacts; select Claude explicitly |
|
|
49
|
+
| Copy Codex project state locally | Selected sessions, supported SQLite memory rows, and artifacts; exclude settings |
|
|
50
|
+
| Apply one copy across both harnesses | Pending |
|
|
51
|
+
| Transfer native state over SSH | Pending |
|
|
52
|
+
| Apply a move | Pending; move plans are available |
|
|
53
|
+
|
|
54
|
+
Every copy is a **dry run by default**. Writes require `--apply`. Destination
|
|
55
|
+
conflicts are refused, including existing native IDs or project-setting keys.
|
|
56
|
+
Unsupported or unattributed selected state blocks the transfer; llar does not
|
|
57
|
+
quietly drop it.
|
|
58
|
+
|
|
59
|
+
[What remains](https://github.com/alltuner/llar/blob/main/docs/roadmap.md) lists the implementation gaps and deferred work.
|
|
60
|
+
|
|
61
|
+
## Install
|
|
62
|
+
|
|
63
|
+
llar supports Linux and macOS and requires Python 3.12 or later. Install the
|
|
64
|
+
[PyPI package](https://pypi.org/project/llar/) with
|
|
65
|
+
[uv](https://docs.astral.sh/uv/):
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
uv tool install llar
|
|
69
|
+
llar --help
|
|
70
|
+
llar status
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
For a one-off run without a persistent tool installation:
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
uvx llar --help
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Upgrade an installed copy with:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
uv tool upgrade llar
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The examples below use the installed llar command and work outside a source
|
|
86
|
+
checkout. Replace /path/to/... placeholders with your own paths.
|
|
87
|
+
|
|
88
|
+
Copies also require Linux or macOS, git, and rsync 3.2.6 or later with ACL and
|
|
89
|
+
extended-attribute support. Apple's bundled openrsync is insufficient. On macOS,
|
|
90
|
+
the development workflow installs modern rsync through Homebrew:
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
brew install rsync
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
llar selects the first compatible rsync in absolute PATH entries. SSH copies
|
|
97
|
+
require compatible llar helpers and modern rsync on both machines.
|
|
98
|
+
|
|
99
|
+
## Inspect a project
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
llar status /path/to/project
|
|
103
|
+
llar projects list
|
|
104
|
+
llar projects list --missing
|
|
105
|
+
llar projects trust show /path/to/project
|
|
106
|
+
llar doctor --dir /path/to/project
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
A project is one absolute directory. Inspection filters are exact unless you
|
|
110
|
+
request descendants explicitly. A directory is never expanded to its Git root.
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
llar projects list --dir /path/to/project --recursive
|
|
114
|
+
llar sessions list --dir /path/to/project --harness claude
|
|
115
|
+
llar sessions list --dir /path/to/project --recursive
|
|
116
|
+
llar activity list --dir /path/to/project --state live
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Options follow the leaf command. `--harness` is repeatable; inspection otherwise
|
|
120
|
+
selects both harnesses.
|
|
121
|
+
|
|
122
|
+
### Sessions and activity answer different questions
|
|
123
|
+
|
|
124
|
+
A session is a logical conversation, identified by its harness and native ID.
|
|
125
|
+
It can have several transcript files and runtime observations, counted separately.
|
|
126
|
+
|
|
127
|
+
- Session directory filters use **started_in**, the recorded launch directory.
|
|
128
|
+
- Activity directory filters use **observed_in**, the runtime directory when known.
|
|
129
|
+
- Transfer adapters track **current ownership** separately from launch history.
|
|
130
|
+
|
|
131
|
+
A copied session retains its original launch directory. Copying does not make
|
|
132
|
+
it a conversation that started in the destination. Codex writer locks identify
|
|
133
|
+
thread ownership but do not supply an observed runtime directory.
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
llar sessions list
|
|
137
|
+
llar sessions list --live
|
|
138
|
+
llar activity list --state unknown
|
|
139
|
+
llar activity list --unassigned
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
To inspect a single session, take its reference from the list. In this example,
|
|
143
|
+
replace `codex:UUID` with that reference:
|
|
144
|
+
|
|
145
|
+
```sh
|
|
146
|
+
llar sessions show codex:UUID
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
No activity observed is not proof of idleness. Transfer application performs its
|
|
150
|
+
own checks and acquires the required native locks.
|
|
151
|
+
|
|
152
|
+
### Trust and memory counts
|
|
153
|
+
|
|
154
|
+
Trust output describes a supported **explicit setting**, not the harness's full
|
|
155
|
+
effective policy. `unset` means the setting was inspected and no supported
|
|
156
|
+
explicit decision was found; `unknown` means it could not be established.
|
|
157
|
+
|
|
158
|
+
Status currently reports `memory_inventory=not_inspected` and a null
|
|
159
|
+
`memory_count`. That does not mean there are no memories. Transfer adapters have
|
|
160
|
+
a separate, broader inventory for supported memory storage.
|
|
161
|
+
|
|
162
|
+
## Copy project files
|
|
163
|
+
|
|
164
|
+
Preview first, then apply the same selection:
|
|
165
|
+
|
|
166
|
+
```sh
|
|
167
|
+
llar cp /path/to/source /path/to/target --only files
|
|
168
|
+
llar cp /path/to/source /path/to/target --only files --apply
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The destination names the **exact resulting project root** and must not exist
|
|
172
|
+
when files are selected. A trailing slash does not change nesting semantics.
|
|
173
|
+
Hidden files and symlinks are included; symlinks are preserved rather than followed.
|
|
174
|
+
|
|
175
|
+
llar stages privately, verifies content and metadata, and publishes without
|
|
176
|
+
replacing the destination. Copies retain the source. Linked Git worktrees,
|
|
177
|
+
submodules, and unverified external Git bindings are refused.
|
|
178
|
+
|
|
179
|
+
## Copy native project state
|
|
180
|
+
|
|
181
|
+
Omitting `--only` selects files and all attributable native components. Omitting
|
|
182
|
+
`--harness` selects both harnesses. Because combined application is pending,
|
|
183
|
+
native copies currently require an explicit single-harness selection.
|
|
184
|
+
|
|
185
|
+
A new project directory does not create a new native conversation identity.
|
|
186
|
+
Copying sessions into the same native store conflicts with their existing IDs.
|
|
187
|
+
The examples use a separate destination home for native state:
|
|
188
|
+
|
|
189
|
+
```sh
|
|
190
|
+
llar cp /path/to/source /path/to/target --harness claude --target-home /path/to/destination-home
|
|
191
|
+
llar cp /path/to/source /path/to/target --harness claude --target-home /path/to/destination-home --apply
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Claude shared settings/history updates add only disjoint records and preserve
|
|
195
|
+
unrelated destination data under native locks. Unsupported formats and artifact
|
|
196
|
+
stores remain blockers.
|
|
197
|
+
|
|
198
|
+
For a supported Codex session/artifact selection:
|
|
199
|
+
|
|
200
|
+
```sh
|
|
201
|
+
llar cp /path/to/source /path/to/target --harness codex --only sessions --only artifacts --target-home /path/to/destination-home
|
|
202
|
+
llar cp /path/to/source /path/to/target --harness codex --only sessions --only artifacts --target-home /path/to/destination-home --apply
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
That Codex example is state-only: it does not copy project files. Add another
|
|
206
|
+
`--only files` to include them. SQLite memory rows can be selected with
|
|
207
|
+
`--only memory`; Git-backed memory stores and Codex shared settings remain
|
|
208
|
+
unsupported. Dependencies must be selected explicitly.
|
|
209
|
+
|
|
210
|
+
The [transfer guide](https://github.com/alltuner/llar/blob/main/docs/usage-transfers.md) explains component selection,
|
|
211
|
+
destination profiles, conflicts, native format limits, and partial failures.
|
|
212
|
+
|
|
213
|
+
## Copy files across machines
|
|
214
|
+
|
|
215
|
+
SSH currently supports explicit **files-only** copies in either direction:
|
|
216
|
+
|
|
217
|
+
```sh
|
|
218
|
+
llar cp /path/to/source machine:~/repos/target --only files
|
|
219
|
+
llar cp /path/to/source machine:~/repos/target --only files --apply
|
|
220
|
+
llar cp machine:~/repos/source /path/to/target --only files --apply
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Use existing OpenSSH aliases, authentication, and trusted host keys. Remote paths
|
|
224
|
+
must be absolute or start with `~/`, expanded remotely. An optional
|
|
225
|
+
`--ssh-config` selects a local OpenSSH configuration file.
|
|
226
|
+
|
|
227
|
+
Initial SSH support requires matching OS platforms, equal user IDs, and
|
|
228
|
+
preservable numeric group ownership. Cross-platform metadata translation is
|
|
229
|
+
pending. Native state over SSH and all move application remain blocked.
|
|
230
|
+
|
|
231
|
+
## Read results reliably
|
|
232
|
+
|
|
233
|
+
```sh
|
|
234
|
+
llar status /path/to/project --json
|
|
235
|
+
llar sessions list --json
|
|
236
|
+
llar cp /path/to/source /path/to/target --only files --json
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
JSON includes `items`, `diagnostics`, and `coverage`. Complete coverage means the
|
|
240
|
+
declared inspection finished; it does not mean every native feature is supported.
|
|
241
|
+
Partial results retain useful records, but their counts are not guaranteed totals.
|
|
242
|
+
|
|
243
|
+
| Exit code | Meaning |
|
|
244
|
+
|---|---|
|
|
245
|
+
| 0 | Inspection or supported preview completed, or apply succeeded. Doctor findings alone do not make inspection fail. |
|
|
246
|
+
| 1 | Inspection is incomplete, a plan is blocked, or apply failed or partially completed. |
|
|
247
|
+
| 2 | Invalid usage, or a missing/ambiguous session reference after a complete scan. |
|
|
248
|
+
|
|
249
|
+
Applied copies record progress under the destination home's private
|
|
250
|
+
`.local/state/llar/operations` directory. Publication can be partial across files
|
|
251
|
+
or databases. SSH disconnection during final publication can leave its outcome
|
|
252
|
+
unknown. Keep the reported receipt and staging; automatic recovery is pending.
|
|
253
|
+
|
|
254
|
+
[Output and troubleshooting](https://github.com/alltuner/llar/blob/main/docs/output.md) explains coverage, trust, blockers,
|
|
255
|
+
receipts, and the JSON fields needed by scripts.
|
|
256
|
+
|
|
257
|
+
## State locations
|
|
258
|
+
|
|
259
|
+
Without `--home`, llar uses the current user's home and honors `CLAUDE_CONFIG_DIR`,
|
|
260
|
+
`CODEX_HOME`, and the supported `CODEX_SQLITE_HOME` override. An explicit
|
|
261
|
+
`--home` selects an isolated effective home and ignores those native overrides.
|
|
262
|
+
|
|
263
|
+
```sh
|
|
264
|
+
llar harnesses
|
|
265
|
+
llar harnesses --home /path/to/home --json
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
`--home` selects state stores; it does not rewrite project paths recorded inside
|
|
269
|
+
them. Alternate homes are storage contexts, not filesystem sandboxes: recorded
|
|
270
|
+
absolute paths and supported native configuration references retain their meaning.
|
|
271
|
+
For transfers, `--home` is the source home and `--target-home` is the
|
|
272
|
+
destination home. Local transfers default the latter to the former; SSH
|
|
273
|
+
transfers do not.
|
|
274
|
+
|
|
275
|
+
## Documentation and development
|
|
276
|
+
|
|
277
|
+
| Document | Purpose |
|
|
278
|
+
|---|---|
|
|
279
|
+
| [Transfer guide](https://github.com/alltuner/llar/blob/main/docs/usage-transfers.md) | Supported workflows, selection, SSH, and failure handling |
|
|
280
|
+
| [Output and troubleshooting](https://github.com/alltuner/llar/blob/main/docs/output.md) | Evidence fields, JSON, exit codes, and common blockers |
|
|
281
|
+
| [Roadmap](https://github.com/alltuner/llar/blob/main/docs/roadmap.md) | Pending, deferred, and unspecified work |
|
|
282
|
+
| [Releasing](https://github.com/alltuner/llar/blob/main/docs/releasing.md) | Maintainer workflow and PyPI trusted publishing |
|
|
283
|
+
| [CLI contract](https://github.com/alltuner/llar/blob/main/docs/cli-contract.md) | Accepted target surface; includes commands not implemented yet |
|
|
284
|
+
| [Transfer design](https://github.com/alltuner/llar/blob/main/docs/transfers.md) | Safety protocol, adapter decisions, and implementation constraints |
|
|
285
|
+
| [Architecture](https://github.com/alltuner/llar/blob/main/docs/architecture.md) | Models, boundaries, and coordination |
|
|
286
|
+
| [Native attribution](https://github.com/alltuner/llar/blob/main/docs/state-attribution.md) | Recognized storage layouts and ownership evidence |
|
|
287
|
+
|
|
288
|
+
For development, clone the repository and use uv's project environment.
|
|
289
|
+
[just](https://just.systems/) and the copy/test dependencies must be installed:
|
|
290
|
+
|
|
291
|
+
```sh
|
|
292
|
+
git clone https://github.com/alltuner/llar.git
|
|
293
|
+
cd llar
|
|
294
|
+
uv sync --locked
|
|
295
|
+
uv run llar --help
|
|
296
|
+
just check
|
|
297
|
+
just smoke
|
|
298
|
+
just build
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Pytest uses isolated homes, real files, SQLite databases, processes, native locks,
|
|
302
|
+
and an ephemeral OpenSSH server. Development also requires ssh, ssh-keygen, and
|
|
303
|
+
sshd; Linux CI installs openssh-server and prepares its privilege-separation
|
|
304
|
+
directory. Tests use generated keys and a private server configuration.
|
|
305
|
+
Ruff handles lint/format checks and ty checks types. CI targets Linux and macOS
|
|
306
|
+
with Python 3.12 and 3.15.
|
|
307
|
+
|
|
308
|
+
## License
|
|
309
|
+
|
|
310
|
+
[MIT](https://github.com/alltuner/llar/blob/main/LICENSE), copyright All Tuner. Packaged Codex schema material retains its
|
|
311
|
+
[upstream license and notices](https://github.com/alltuner/llar/blob/main/src/llar/harnesses/codex/NOTICE).
|
llar-0.1.1/README.md
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# llar
|
|
2
|
+
|
|
3
|
+
Inspect and copy the project state that Claude Code and Codex keep outside your
|
|
4
|
+
checkout.
|
|
5
|
+
|
|
6
|
+
Moving a repository does not move its conversations, memories, or path-based
|
|
7
|
+
settings. llar discovers that state, explains its ownership, and plans transfers.
|
|
8
|
+
Supported copies can then be applied explicitly.
|
|
9
|
+
|
|
10
|
+
*Llar* is Catalan for home or hearth. The project is under active development;
|
|
11
|
+
the table below describes implemented support, not the eventual command surface.
|
|
12
|
+
|
|
13
|
+
## What works today
|
|
14
|
+
|
|
15
|
+
| Operation | Support |
|
|
16
|
+
|---|---|
|
|
17
|
+
| Inspect projects, explicit trust, sessions, activity, and storage locations | Claude Code and Codex |
|
|
18
|
+
| Diagnose missing directories and unresolved state | Read-only |
|
|
19
|
+
| Copy project files locally | Explicit file selection |
|
|
20
|
+
| Copy project files over SSH | Push or pull, one remote endpoint |
|
|
21
|
+
| Copy Claude project state locally | Recognized settings, history, sessions, memory, and artifacts; select Claude explicitly |
|
|
22
|
+
| Copy Codex project state locally | Selected sessions, supported SQLite memory rows, and artifacts; exclude settings |
|
|
23
|
+
| Apply one copy across both harnesses | Pending |
|
|
24
|
+
| Transfer native state over SSH | Pending |
|
|
25
|
+
| Apply a move | Pending; move plans are available |
|
|
26
|
+
|
|
27
|
+
Every copy is a **dry run by default**. Writes require `--apply`. Destination
|
|
28
|
+
conflicts are refused, including existing native IDs or project-setting keys.
|
|
29
|
+
Unsupported or unattributed selected state blocks the transfer; llar does not
|
|
30
|
+
quietly drop it.
|
|
31
|
+
|
|
32
|
+
[What remains](https://github.com/alltuner/llar/blob/main/docs/roadmap.md) lists the implementation gaps and deferred work.
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
llar supports Linux and macOS and requires Python 3.12 or later. Install the
|
|
37
|
+
[PyPI package](https://pypi.org/project/llar/) with
|
|
38
|
+
[uv](https://docs.astral.sh/uv/):
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
uv tool install llar
|
|
42
|
+
llar --help
|
|
43
|
+
llar status
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
For a one-off run without a persistent tool installation:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
uvx llar --help
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Upgrade an installed copy with:
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
uv tool upgrade llar
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The examples below use the installed llar command and work outside a source
|
|
59
|
+
checkout. Replace /path/to/... placeholders with your own paths.
|
|
60
|
+
|
|
61
|
+
Copies also require Linux or macOS, git, and rsync 3.2.6 or later with ACL and
|
|
62
|
+
extended-attribute support. Apple's bundled openrsync is insufficient. On macOS,
|
|
63
|
+
the development workflow installs modern rsync through Homebrew:
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
brew install rsync
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
llar selects the first compatible rsync in absolute PATH entries. SSH copies
|
|
70
|
+
require compatible llar helpers and modern rsync on both machines.
|
|
71
|
+
|
|
72
|
+
## Inspect a project
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
llar status /path/to/project
|
|
76
|
+
llar projects list
|
|
77
|
+
llar projects list --missing
|
|
78
|
+
llar projects trust show /path/to/project
|
|
79
|
+
llar doctor --dir /path/to/project
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
A project is one absolute directory. Inspection filters are exact unless you
|
|
83
|
+
request descendants explicitly. A directory is never expanded to its Git root.
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
llar projects list --dir /path/to/project --recursive
|
|
87
|
+
llar sessions list --dir /path/to/project --harness claude
|
|
88
|
+
llar sessions list --dir /path/to/project --recursive
|
|
89
|
+
llar activity list --dir /path/to/project --state live
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Options follow the leaf command. `--harness` is repeatable; inspection otherwise
|
|
93
|
+
selects both harnesses.
|
|
94
|
+
|
|
95
|
+
### Sessions and activity answer different questions
|
|
96
|
+
|
|
97
|
+
A session is a logical conversation, identified by its harness and native ID.
|
|
98
|
+
It can have several transcript files and runtime observations, counted separately.
|
|
99
|
+
|
|
100
|
+
- Session directory filters use **started_in**, the recorded launch directory.
|
|
101
|
+
- Activity directory filters use **observed_in**, the runtime directory when known.
|
|
102
|
+
- Transfer adapters track **current ownership** separately from launch history.
|
|
103
|
+
|
|
104
|
+
A copied session retains its original launch directory. Copying does not make
|
|
105
|
+
it a conversation that started in the destination. Codex writer locks identify
|
|
106
|
+
thread ownership but do not supply an observed runtime directory.
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
llar sessions list
|
|
110
|
+
llar sessions list --live
|
|
111
|
+
llar activity list --state unknown
|
|
112
|
+
llar activity list --unassigned
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
To inspect a single session, take its reference from the list. In this example,
|
|
116
|
+
replace `codex:UUID` with that reference:
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
llar sessions show codex:UUID
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
No activity observed is not proof of idleness. Transfer application performs its
|
|
123
|
+
own checks and acquires the required native locks.
|
|
124
|
+
|
|
125
|
+
### Trust and memory counts
|
|
126
|
+
|
|
127
|
+
Trust output describes a supported **explicit setting**, not the harness's full
|
|
128
|
+
effective policy. `unset` means the setting was inspected and no supported
|
|
129
|
+
explicit decision was found; `unknown` means it could not be established.
|
|
130
|
+
|
|
131
|
+
Status currently reports `memory_inventory=not_inspected` and a null
|
|
132
|
+
`memory_count`. That does not mean there are no memories. Transfer adapters have
|
|
133
|
+
a separate, broader inventory for supported memory storage.
|
|
134
|
+
|
|
135
|
+
## Copy project files
|
|
136
|
+
|
|
137
|
+
Preview first, then apply the same selection:
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
llar cp /path/to/source /path/to/target --only files
|
|
141
|
+
llar cp /path/to/source /path/to/target --only files --apply
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The destination names the **exact resulting project root** and must not exist
|
|
145
|
+
when files are selected. A trailing slash does not change nesting semantics.
|
|
146
|
+
Hidden files and symlinks are included; symlinks are preserved rather than followed.
|
|
147
|
+
|
|
148
|
+
llar stages privately, verifies content and metadata, and publishes without
|
|
149
|
+
replacing the destination. Copies retain the source. Linked Git worktrees,
|
|
150
|
+
submodules, and unverified external Git bindings are refused.
|
|
151
|
+
|
|
152
|
+
## Copy native project state
|
|
153
|
+
|
|
154
|
+
Omitting `--only` selects files and all attributable native components. Omitting
|
|
155
|
+
`--harness` selects both harnesses. Because combined application is pending,
|
|
156
|
+
native copies currently require an explicit single-harness selection.
|
|
157
|
+
|
|
158
|
+
A new project directory does not create a new native conversation identity.
|
|
159
|
+
Copying sessions into the same native store conflicts with their existing IDs.
|
|
160
|
+
The examples use a separate destination home for native state:
|
|
161
|
+
|
|
162
|
+
```sh
|
|
163
|
+
llar cp /path/to/source /path/to/target --harness claude --target-home /path/to/destination-home
|
|
164
|
+
llar cp /path/to/source /path/to/target --harness claude --target-home /path/to/destination-home --apply
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Claude shared settings/history updates add only disjoint records and preserve
|
|
168
|
+
unrelated destination data under native locks. Unsupported formats and artifact
|
|
169
|
+
stores remain blockers.
|
|
170
|
+
|
|
171
|
+
For a supported Codex session/artifact selection:
|
|
172
|
+
|
|
173
|
+
```sh
|
|
174
|
+
llar cp /path/to/source /path/to/target --harness codex --only sessions --only artifacts --target-home /path/to/destination-home
|
|
175
|
+
llar cp /path/to/source /path/to/target --harness codex --only sessions --only artifacts --target-home /path/to/destination-home --apply
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
That Codex example is state-only: it does not copy project files. Add another
|
|
179
|
+
`--only files` to include them. SQLite memory rows can be selected with
|
|
180
|
+
`--only memory`; Git-backed memory stores and Codex shared settings remain
|
|
181
|
+
unsupported. Dependencies must be selected explicitly.
|
|
182
|
+
|
|
183
|
+
The [transfer guide](https://github.com/alltuner/llar/blob/main/docs/usage-transfers.md) explains component selection,
|
|
184
|
+
destination profiles, conflicts, native format limits, and partial failures.
|
|
185
|
+
|
|
186
|
+
## Copy files across machines
|
|
187
|
+
|
|
188
|
+
SSH currently supports explicit **files-only** copies in either direction:
|
|
189
|
+
|
|
190
|
+
```sh
|
|
191
|
+
llar cp /path/to/source machine:~/repos/target --only files
|
|
192
|
+
llar cp /path/to/source machine:~/repos/target --only files --apply
|
|
193
|
+
llar cp machine:~/repos/source /path/to/target --only files --apply
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Use existing OpenSSH aliases, authentication, and trusted host keys. Remote paths
|
|
197
|
+
must be absolute or start with `~/`, expanded remotely. An optional
|
|
198
|
+
`--ssh-config` selects a local OpenSSH configuration file.
|
|
199
|
+
|
|
200
|
+
Initial SSH support requires matching OS platforms, equal user IDs, and
|
|
201
|
+
preservable numeric group ownership. Cross-platform metadata translation is
|
|
202
|
+
pending. Native state over SSH and all move application remain blocked.
|
|
203
|
+
|
|
204
|
+
## Read results reliably
|
|
205
|
+
|
|
206
|
+
```sh
|
|
207
|
+
llar status /path/to/project --json
|
|
208
|
+
llar sessions list --json
|
|
209
|
+
llar cp /path/to/source /path/to/target --only files --json
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
JSON includes `items`, `diagnostics`, and `coverage`. Complete coverage means the
|
|
213
|
+
declared inspection finished; it does not mean every native feature is supported.
|
|
214
|
+
Partial results retain useful records, but their counts are not guaranteed totals.
|
|
215
|
+
|
|
216
|
+
| Exit code | Meaning |
|
|
217
|
+
|---|---|
|
|
218
|
+
| 0 | Inspection or supported preview completed, or apply succeeded. Doctor findings alone do not make inspection fail. |
|
|
219
|
+
| 1 | Inspection is incomplete, a plan is blocked, or apply failed or partially completed. |
|
|
220
|
+
| 2 | Invalid usage, or a missing/ambiguous session reference after a complete scan. |
|
|
221
|
+
|
|
222
|
+
Applied copies record progress under the destination home's private
|
|
223
|
+
`.local/state/llar/operations` directory. Publication can be partial across files
|
|
224
|
+
or databases. SSH disconnection during final publication can leave its outcome
|
|
225
|
+
unknown. Keep the reported receipt and staging; automatic recovery is pending.
|
|
226
|
+
|
|
227
|
+
[Output and troubleshooting](https://github.com/alltuner/llar/blob/main/docs/output.md) explains coverage, trust, blockers,
|
|
228
|
+
receipts, and the JSON fields needed by scripts.
|
|
229
|
+
|
|
230
|
+
## State locations
|
|
231
|
+
|
|
232
|
+
Without `--home`, llar uses the current user's home and honors `CLAUDE_CONFIG_DIR`,
|
|
233
|
+
`CODEX_HOME`, and the supported `CODEX_SQLITE_HOME` override. An explicit
|
|
234
|
+
`--home` selects an isolated effective home and ignores those native overrides.
|
|
235
|
+
|
|
236
|
+
```sh
|
|
237
|
+
llar harnesses
|
|
238
|
+
llar harnesses --home /path/to/home --json
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
`--home` selects state stores; it does not rewrite project paths recorded inside
|
|
242
|
+
them. Alternate homes are storage contexts, not filesystem sandboxes: recorded
|
|
243
|
+
absolute paths and supported native configuration references retain their meaning.
|
|
244
|
+
For transfers, `--home` is the source home and `--target-home` is the
|
|
245
|
+
destination home. Local transfers default the latter to the former; SSH
|
|
246
|
+
transfers do not.
|
|
247
|
+
|
|
248
|
+
## Documentation and development
|
|
249
|
+
|
|
250
|
+
| Document | Purpose |
|
|
251
|
+
|---|---|
|
|
252
|
+
| [Transfer guide](https://github.com/alltuner/llar/blob/main/docs/usage-transfers.md) | Supported workflows, selection, SSH, and failure handling |
|
|
253
|
+
| [Output and troubleshooting](https://github.com/alltuner/llar/blob/main/docs/output.md) | Evidence fields, JSON, exit codes, and common blockers |
|
|
254
|
+
| [Roadmap](https://github.com/alltuner/llar/blob/main/docs/roadmap.md) | Pending, deferred, and unspecified work |
|
|
255
|
+
| [Releasing](https://github.com/alltuner/llar/blob/main/docs/releasing.md) | Maintainer workflow and PyPI trusted publishing |
|
|
256
|
+
| [CLI contract](https://github.com/alltuner/llar/blob/main/docs/cli-contract.md) | Accepted target surface; includes commands not implemented yet |
|
|
257
|
+
| [Transfer design](https://github.com/alltuner/llar/blob/main/docs/transfers.md) | Safety protocol, adapter decisions, and implementation constraints |
|
|
258
|
+
| [Architecture](https://github.com/alltuner/llar/blob/main/docs/architecture.md) | Models, boundaries, and coordination |
|
|
259
|
+
| [Native attribution](https://github.com/alltuner/llar/blob/main/docs/state-attribution.md) | Recognized storage layouts and ownership evidence |
|
|
260
|
+
|
|
261
|
+
For development, clone the repository and use uv's project environment.
|
|
262
|
+
[just](https://just.systems/) and the copy/test dependencies must be installed:
|
|
263
|
+
|
|
264
|
+
```sh
|
|
265
|
+
git clone https://github.com/alltuner/llar.git
|
|
266
|
+
cd llar
|
|
267
|
+
uv sync --locked
|
|
268
|
+
uv run llar --help
|
|
269
|
+
just check
|
|
270
|
+
just smoke
|
|
271
|
+
just build
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Pytest uses isolated homes, real files, SQLite databases, processes, native locks,
|
|
275
|
+
and an ephemeral OpenSSH server. Development also requires ssh, ssh-keygen, and
|
|
276
|
+
sshd; Linux CI installs openssh-server and prepares its privilege-separation
|
|
277
|
+
directory. Tests use generated keys and a private server configuration.
|
|
278
|
+
Ruff handles lint/format checks and ty checks types. CI targets Linux and macOS
|
|
279
|
+
with Python 3.12 and 3.15.
|
|
280
|
+
|
|
281
|
+
## License
|
|
282
|
+
|
|
283
|
+
[MIT](https://github.com/alltuner/llar/blob/main/LICENSE), copyright All Tuner. Packaged Codex schema material retains its
|
|
284
|
+
[upstream license and notices](https://github.com/alltuner/llar/blob/main/src/llar/harnesses/codex/NOTICE).
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "llar"
|
|
3
|
+
version = "0.1.1"
|
|
4
|
+
description = "Look after the local state coding agents keep about your projects."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
requires-python = ">=3.12"
|
|
9
|
+
keywords = [
|
|
10
|
+
"claude",
|
|
11
|
+
"codex",
|
|
12
|
+
"sessions",
|
|
13
|
+
"developer-tools",
|
|
14
|
+
"cli",
|
|
15
|
+
]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"Operating System :: MacOS",
|
|
21
|
+
"Operating System :: POSIX :: Linux",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.15",
|
|
25
|
+
"Topic :: Software Development",
|
|
26
|
+
"Topic :: Utilities",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"psutil>=7.2.2",
|
|
30
|
+
"typer>=0.27.3",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[[project.authors]]
|
|
34
|
+
name = "All Tuner"
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://github.com/alltuner/llar"
|
|
38
|
+
Repository = "https://github.com/alltuner/llar"
|
|
39
|
+
Issues = "https://github.com/alltuner/llar/issues"
|
|
40
|
+
Documentation = "https://github.com/alltuner/llar#readme"
|
|
41
|
+
|
|
42
|
+
[project.scripts]
|
|
43
|
+
llar = "llar.cli:app"
|
|
44
|
+
|
|
45
|
+
[build-system]
|
|
46
|
+
requires = ["uv_build>=0.13.6,<0.14"]
|
|
47
|
+
build-backend = "uv_build"
|
|
48
|
+
|
|
49
|
+
[tool.ruff]
|
|
50
|
+
target-version = "py312"
|
|
51
|
+
|
|
52
|
+
[tool.ruff.lint]
|
|
53
|
+
select = [
|
|
54
|
+
"E",
|
|
55
|
+
"F",
|
|
56
|
+
"I",
|
|
57
|
+
"UP",
|
|
58
|
+
"B",
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
[tool.ty.rules]
|
|
62
|
+
all = "error"
|
|
63
|
+
|
|
64
|
+
[dependency-groups]
|
|
65
|
+
dev = [
|
|
66
|
+
"pytest>=9.2.0",
|
|
67
|
+
"ruff>=0.17.3",
|
|
68
|
+
"ty>=0.0.95",
|
|
69
|
+
]
|