@ajaykumarnpm/talea 0.2.2 → 0.3.0

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,14 @@ All notable changes to this project are recorded here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the versions follow
5
5
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.3.0] - 2026-09-21
8
+
9
+ ### Added
10
+ - talea select reopens the checklist
11
+
12
+ ### Chores
13
+ - ignore .idea/
14
+
7
15
  ## [0.2.2] - 2026-09-21
8
16
 
9
17
  ### Documentation
package/README.md CHANGED
@@ -60,6 +60,7 @@ this machine needs, untick what it does not, press enter.
60
60
  talea sync # clone the new, fast-forward the rest
61
61
  talea status # branch, clean/dirty, ahead/behind, in one table
62
62
  talea add some-repo # keep one more on this machine, and clone it now
63
+ talea select # reopen the checklist and change the whole list
63
64
  cd $(talea where eklavya)
64
65
  ```
65
66
 
@@ -146,7 +147,8 @@ Treat the id like a bookmark you would not paste into a public channel.
146
147
  | `talea clone` | clone only — never fetches or merges |
147
148
  | `talea adopt` | move checkouts you already have into place |
148
149
  | `talea status` | branch, clean/dirty, ahead/behind |
149
- | `talea add` / `talea rm` | change what this machine keeps |
150
+ | `talea select` | reopen the checklist what this machine keeps |
151
+ | `talea add` / `talea rm` | change that one repo at a time |
150
152
  | `talea where <repo>` | print a repo's path, for `cd $( )` |
151
153
  | `talea list` | the catalogue |
152
154
  | `talea tree` | the folder tree on disk |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ajaykumarnpm/talea",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "One folder structure for every machine. Clone, adopt and sync your GitHub repos from a manifest you own.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -8,6 +8,7 @@ import { c, fail, plain } from './log.js';
8
8
  import * as init from './commands/init.js';
9
9
  import * as discover from './commands/discover.js';
10
10
  import * as clone from './commands/clone.js';
11
+ import * as select from './commands/select.js';
11
12
  import * as adopt from './commands/adopt.js';
12
13
  import * as sync from './commands/sync.js';
13
14
  import * as status from './commands/status.js';
@@ -28,6 +29,7 @@ const COMMANDS = {
28
29
  init,
29
30
  discover,
30
31
  clone,
32
+ select,
31
33
  adopt,
32
34
  sync,
33
35
  status,
@@ -50,6 +52,8 @@ const ALIASES = {
50
52
  pull: 'sync',
51
53
  update: 'sync',
52
54
  refresh: 'discover',
55
+ pick: 'select',
56
+ choose: 'select',
53
57
  ls: 'list',
54
58
  st: 'status',
55
59
  cd: 'where',
@@ -103,6 +107,7 @@ ${c.bold('Commands')}
103
107
  ${c.cyan('clone')} clone only — never fetches or merges
104
108
  ${c.cyan('adopt')} move repos you already have into the right place
105
109
  ${c.cyan('status')} one table: branch, clean/dirty, ahead/behind
110
+ ${c.cyan('select')} reopen the checklist — what this machine keeps
106
111
  ${c.cyan('add')} keep another repo on this machine (${c.dim('rm')} to drop one)
107
112
  ${c.cyan('where')} print a repo's path — ${c.dim('cd $(talea where eklavya)')}
108
113
  ${c.cyan('list')} show the catalogue
@@ -0,0 +1,79 @@
1
+ // `talea select` — reopen the checklist and change what this machine keeps.
2
+ //
3
+ // `add` and `rm` are the one-repo door. This is the door for "let me look at
4
+ // the whole list again", which until now was reachable only as `--pick` on a
5
+ // command you had to already know to run. The picker was the first thing `init`
6
+ // showed and then had no name of its own.
7
+ //
8
+ // It is deliberately thin: the picking and the saving live in `src/select.js`
9
+ // because `clone` and `sync` ask the same question, and the cloning is
10
+ // `clone.run`, re-entered after the new selection is on disk.
11
+
12
+ import { c, fail, heading, ok, plain, skip } from '../log.js';
13
+ import { chooseRepos } from '../select.js';
14
+ import { machineRepos, requireCatalogue, requireWorkspace } from '../workspace.js';
15
+ import * as clone from './clone.js';
16
+
17
+ export const help = `
18
+ ${c.bold('talea select')} — change what this machine keeps
19
+
20
+ ${c.dim('talea select')} reopen the checklist, then clone what is newly ticked
21
+ ${c.dim('talea select --no-clone')} change the list only, fill it in later
22
+
23
+ The checklist opens with the current selection ticked. Space toggles, Enter
24
+ saves, Esc cancels and changes nothing. Everything in the catalogue is listed,
25
+ including the archived and the forks — this machine is allowed to keep
26
+ something the default set does not have.
27
+
28
+ It writes ${c.dim('.talea.json')}, which never leaves this machine, so no other machine's
29
+ selection changes. Unticking a repo takes it off the list and leaves the
30
+ checkout exactly where it is; deleting it is your call.
31
+
32
+ For one repo, ${c.dim('talea add <repo>')} and ${c.dim('talea rm <repo>')} skip the checklist.
33
+
34
+ Options
35
+ --no-clone save the selection, clone nothing
36
+ --protocol <p> ssh (default) or https
37
+ -j, --jobs <n> parallel clones
38
+ `;
39
+
40
+ /** What changed, as two lists of names. Pure, so it can be tested. */
41
+ export function changes(before, after) {
42
+ const had = new Set(before);
43
+ const has = new Set(after);
44
+ return {
45
+ added: after.filter((n) => !had.has(n)),
46
+ dropped: before.filter((n) => !has.has(n)),
47
+ };
48
+ }
49
+
50
+ export async function run(opts) {
51
+ const { root, manifest, state } = requireWorkspace();
52
+ requireCatalogue(manifest);
53
+
54
+ // -g/-r narrow a run; they cannot narrow a decision about the whole machine.
55
+ // Accepting them silently would return the old selection unchanged and look
56
+ // like the picker had simply declined to open.
57
+ if (opts.group || opts.repo) {
58
+ fail('`select` is about the whole list — -g/-r do not narrow it.');
59
+ console.error('\n Use `talea add <repo>` or `talea rm <repo>` for one repo at a time.');
60
+ process.exit(1);
61
+ }
62
+
63
+ const before = machineRepos(manifest, state).map((r) => r.name);
64
+ const { repos } = await chooseRepos({ manifest, root, state, opts: { ...opts, pick: true } });
65
+ const after = repos.map((r) => r.name);
66
+ const { added, dropped } = changes(before, after);
67
+
68
+ heading('This machine keeps');
69
+ for (const name of added) ok(`${c.bold(name)} ${c.dim('added')}`);
70
+ for (const name of dropped) {
71
+ skip(`${c.bold(name)} ${c.dim('off the list — the checkout stays where it is')}`);
72
+ }
73
+ plain(c.dim(` ${after.length} repos`));
74
+
75
+ if (!added.length || opts.clone === false) return;
76
+
77
+ // The selection is on disk now, so clone reads it back and never re-asks.
78
+ await clone.run({ ...opts, pick: false });
79
+ }