@hurshb50/setup-ubuntu 0.0.3 → 1.0.1
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/README.md +15 -4
- package/distribution/assets/.gitconfig +31 -0
- package/distribution/assets/AGENTS.md +10 -53
- package/distribution/assets/skills/design/SKILL.md +21 -38
- package/distribution/assets/skills/teach/SKILL.md +4 -22
- package/distribution/setup-ubuntu.mjs +38 -11
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# setup-ubuntu
|
|
2
2
|
|
|
3
|
-
Sets up a fresh Ubuntu machine with
|
|
3
|
+
Sets up a fresh Ubuntu machine with tools, configuration, and dotfiles.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -10,8 +10,19 @@ curl -fsSL https://vite.plus | bash
|
|
|
10
10
|
vpx @hurshb50/setup-ubuntu
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## After Installation
|
|
14
|
+
|
|
15
|
+
Open a new terminal, then:
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
- Log out and back in to use Docker without `sudo`.
|
|
18
|
+
- Sign in to Zed, 1Password, and Chrome.
|
|
19
|
+
- Run `gh auth login` to authenticate the GitHub CLI.
|
|
20
|
+
- Pick a wallpaper in HydraPaper.
|
|
21
|
+
- Put personal shell config in `~/custom.bashrc`, not `~/.bashrc`.
|
|
22
|
+
- Update `/.gitconfig` if you are on work machine
|
|
23
|
+
|
|
24
|
+
## Publishing
|
|
16
25
|
|
|
17
|
-
|
|
26
|
+
1. Run `publish.yaml` from the Actions tab with a `patch`, `minor`, or `major` bump. CI checks, tests, builds, tags, and stages the package, using OIDC instead of a token.
|
|
27
|
+
2. Approve the staged package on npmjs.com to publish it.
|
|
28
|
+
3. `release.yaml` creates the GitHub release once the version is live.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
[user]
|
|
2
|
+
name = Hursh Patel
|
|
3
|
+
email = hurshb50@gmail.com
|
|
4
|
+
|
|
5
|
+
[core]
|
|
6
|
+
editor = zed --wait
|
|
7
|
+
|
|
8
|
+
[init]
|
|
9
|
+
defaultBranch = main
|
|
10
|
+
|
|
11
|
+
[push]
|
|
12
|
+
autoSetupRemote = true
|
|
13
|
+
|
|
14
|
+
[merge]
|
|
15
|
+
conflictStyle = zdiff3
|
|
16
|
+
|
|
17
|
+
[diff]
|
|
18
|
+
algorithm = histogram
|
|
19
|
+
|
|
20
|
+
[fetch]
|
|
21
|
+
prune = true
|
|
22
|
+
|
|
23
|
+
[rerere]
|
|
24
|
+
enabled = true
|
|
25
|
+
|
|
26
|
+
[branch]
|
|
27
|
+
sort = -committerdate
|
|
28
|
+
|
|
29
|
+
[credential "https://github.com"]
|
|
30
|
+
helper =
|
|
31
|
+
helper = !/usr/bin/gh auth git-credential
|
|
@@ -1,58 +1,15 @@
|
|
|
1
|
-
# Voice
|
|
2
|
-
|
|
3
|
-
Default to one to three sentences. Answer, then stop. No opening praise and no
|
|
4
|
-
closing summary of what you just wrote.
|
|
5
|
-
|
|
6
|
-
Lead with the answer. The first sentence answers the question or states what
|
|
7
|
-
changed. Detail I cannot infer comes after it, and only if it earns its place.
|
|
8
|
-
|
|
9
|
-
Scale length to the task, not to your effort. One file changed gets two
|
|
10
|
-
sentences. A tradeoff I must weigh can run a few short paragraphs. If a reply
|
|
11
|
-
needs more than a screenful, say why in line one. Otherwise revise it shorter.
|
|
12
|
-
|
|
13
|
-
Prose first. Bullets are for genuinely parallel items, not for chopping sentences
|
|
14
|
-
into pieces.
|
|
15
|
-
|
|
16
|
-
Plain words. Cut hedging, preamble, adverbs, and openers like "it is important to
|
|
17
|
-
note". Delve, resolve, crucial, robust, seamless, leverage, showcase, testament,
|
|
18
|
-
landscape, and underscore are banned. So is any non-technical word you would not
|
|
19
|
-
say out loud. No em dashes, and no parentheses for asides. Sentence case headings.
|
|
20
|
-
Bold at most one phrase per reply.
|
|
21
|
-
|
|
22
|
-
Write the point once. No "not just X, but Y", no padding a list to three, and no
|
|
23
|
-
bullet whose lead-in restates its own line.
|
|
24
|
-
|
|
25
|
-
Terse means fewer sentences, not denser ones. Keep the articles and the verbs.
|
|
26
|
-
|
|
27
|
-
Keep one idea per sentence, most of them under 15 words. Split anything past 20.
|
|
28
|
-
|
|
29
1
|
# Formatting
|
|
30
2
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
3
|
+
- Sentences: 8 words or fewer
|
|
4
|
+
- Paragraphs: 2 sentences or fewer
|
|
5
|
+
- Sections: 3 paragraphs or fewer
|
|
6
|
+
- Lists: 4 words per item
|
|
7
|
+
- Tables: 3 columns or fewer, 3 words or fewer per cell
|
|
8
|
+
- Diagrams: 6 nodes, one per level
|
|
36
9
|
|
|
37
10
|
# Explanation
|
|
38
11
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
Draw a diagram when the answer is a flow, a sequence, or a state machine. Keep it
|
|
44
|
-
under ten nodes and taller than it is wide.
|
|
45
|
-
|
|
46
|
-
Snippets, diagrams, and before-and-after pairs do not count against the length
|
|
47
|
-
budget.
|
|
48
|
-
|
|
49
|
-
# Delegation
|
|
50
|
-
|
|
51
|
-
Do the work in this thread by default. Spawn a subagent for reads that cost more
|
|
52
|
-
than they return: codebase search, online research, docs and changelog lookups,
|
|
53
|
-
log and CI triage, enumerating call sites, mapping an unfamiliar repo, and
|
|
54
|
-
summarizing a large diff.
|
|
55
|
-
|
|
56
|
-
Brief it like it has no history, because it does not. "Look into the auth flow"
|
|
57
|
-
fails; "Find where a session token is validated in src/ and return the file, the
|
|
58
|
-
function, and whether expiry is checked" works.
|
|
12
|
+
- Simple
|
|
13
|
+
- Straightforward
|
|
14
|
+
- Minimal
|
|
15
|
+
- Avoid verbosity
|
|
@@ -6,56 +6,39 @@ disable-model-invocation: true
|
|
|
6
6
|
|
|
7
7
|
# Design
|
|
8
8
|
|
|
9
|
-
Turn a vague
|
|
9
|
+
Turn a vague idea into one API shape.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Output
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
Ask me about the decisions the design has to make.
|
|
18
|
-
|
|
19
|
-
Some decisions depend on others. Ask the unblocked ones now and leave the rest for a later round.
|
|
20
|
-
|
|
21
|
-
When a question lands better as an example than as prose, add one: a short snippet of a caller using each option, a sketch of the types, or a diagram of the flow. Keep it small and illustrative. This is not meant to represent the final design.
|
|
22
|
-
|
|
23
|
-
One option per line, each labeled, never run together in a paragraph. Assume I have not read the code you are asking about: name each option by what it does, and quote the signature, variable, or line it turns on, so I can judge it without opening the file.
|
|
24
|
-
|
|
25
|
-
Put every unblocked question in one round, numbered, each with your recommended answer and whatever example it needs. Then stop and wait for mine.
|
|
13
|
+
- Produce the API shape
|
|
14
|
+
- Types, signatures, classes with fields and methods
|
|
15
|
+
- No implementation, no function bodies, no pseudocode
|
|
26
16
|
|
|
27
|
-
|
|
17
|
+
## Phase 1. Interview
|
|
28
18
|
|
|
29
|
-
|
|
19
|
+
1. Ask only about decisions needing my judgement
|
|
20
|
+
2. Move on when only trying designs can answer
|
|
30
21
|
|
|
31
22
|
## Phase 2. Ideation
|
|
32
23
|
|
|
33
|
-
Spawn
|
|
34
|
-
|
|
35
|
-
Send them different starting material. At least one starts from the code as it is today, and at least one ignores the current code and designs as if the problem were new.
|
|
24
|
+
- Spawn 4 subagents at once
|
|
25
|
+
- Send each one different starting material
|
|
36
26
|
|
|
37
27
|
Each subagent returns:
|
|
38
28
|
|
|
39
|
-
- The API shape
|
|
40
|
-
- An example
|
|
41
|
-
- A short paragraph on what the API handles for the caller.
|
|
42
|
-
- The rules a caller must follow, and how it fails.
|
|
43
|
-
- What this approach makes worse.
|
|
44
|
-
|
|
45
|
-
Read what comes back before Phase 3. Throw away any design that does not address the problem, and spawn a replacement with a different approach until you have three or four that do. Merge any two that describe the same shape, or re-run one with different starting material. If all of them match, either the domain forces that shape or the starting material was too alike. Tell me which you think it is.
|
|
46
|
-
|
|
47
|
-
## Phase 3. Choose together
|
|
29
|
+
- The API shape
|
|
30
|
+
- An example caller
|
|
48
31
|
|
|
49
|
-
|
|
32
|
+
## Phase 3. Feedback
|
|
50
33
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
34
|
+
- Present all the designs
|
|
35
|
+
- Show how a caller would use each one
|
|
36
|
+
- Do not pick a winner
|
|
37
|
+
- Ask what I like and dislike
|
|
38
|
+
- Ask whether to run another round
|
|
54
39
|
|
|
55
40
|
## Phase 4. Converge
|
|
56
41
|
|
|
57
|
-
Build one API shape from
|
|
58
|
-
|
|
59
|
-
Show it
|
|
60
|
-
|
|
61
|
-
Then output the same things the subagents returned, and explain why you chose each part. Say how much of the code we already have has to change.
|
|
42
|
+
- Build one API shape from my choices
|
|
43
|
+
- It must read as one design
|
|
44
|
+
- Show it, then refine from my feedback
|
|
@@ -8,28 +8,10 @@ disable-model-invocation: true
|
|
|
8
8
|
|
|
9
9
|
Any concept, in one sitting, from the ground up.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Assume I know nothing about this and have no context. Do not ask what I already know.
|
|
14
|
-
|
|
15
|
-
Define every term the first time it appears, including ones that seem basic. Say what problem the concept solves and what it replaces.
|
|
16
|
-
|
|
17
|
-
Do not refer to anything I have not been shown. No other files, no earlier conversations, no shared setup.
|
|
18
|
-
|
|
19
|
-
Start at the beginning. Teach the first idea, then add one step at a time.
|
|
11
|
+
Assume no prior knowledge and no context.
|
|
20
12
|
|
|
21
13
|
## The lesson
|
|
22
14
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
One new idea at a time. If a sentence asks me to hold two at once, split it.
|
|
28
|
-
|
|
29
|
-
Grow one running example. Do not hop between unrelated ones.
|
|
30
|
-
|
|
31
|
-
## Ending
|
|
32
|
-
|
|
33
|
-
Close with what this now lets me do or understand, in two sentences.
|
|
34
|
-
|
|
35
|
-
Then the sources. Links to the pages you actually read, local paths for anything in this repo. Never invent a link, and if you did not read a source, say so.
|
|
15
|
+
- Define every term before use, even basic ones
|
|
16
|
+
- Each section depends on the ones before
|
|
17
|
+
- Open with an example, then a definition
|
|
@@ -10,7 +10,7 @@ import fs from "fs/promises";
|
|
|
10
10
|
import { execa } from "execa";
|
|
11
11
|
//#region package.json
|
|
12
12
|
var name = "@hurshb50/setup-ubuntu";
|
|
13
|
-
var version = "0.0
|
|
13
|
+
var version = "1.0.0";
|
|
14
14
|
//#endregion
|
|
15
15
|
//#region source/modules/logger/logger.ts
|
|
16
16
|
var Logger = class Logger {
|
|
@@ -184,6 +184,19 @@ var DependencyManager = class {
|
|
|
184
184
|
}
|
|
185
185
|
}))).every((installation) => installation === true);
|
|
186
186
|
}
|
|
187
|
+
async authenticate() {
|
|
188
|
+
if (await this.isAuthenticated()) return;
|
|
189
|
+
process.stdout.write("Administrator access is required to install packages. You may be prompted for your password.\n");
|
|
190
|
+
try {
|
|
191
|
+
await execa("sudo", ["--validate"], {
|
|
192
|
+
stdin: "inherit",
|
|
193
|
+
stdout: "inherit",
|
|
194
|
+
stderr: "inherit"
|
|
195
|
+
});
|
|
196
|
+
} catch (error) {
|
|
197
|
+
throw new Error("Administrator access was not granted. Run 'sudo --validate' and then run this tool again.", { cause: error });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
187
200
|
async install(dependencies, task) {
|
|
188
201
|
await this.enqueue([
|
|
189
202
|
"install",
|
|
@@ -195,8 +208,17 @@ var DependencyManager = class {
|
|
|
195
208
|
async update(task) {
|
|
196
209
|
await this.enqueue(["update"], task);
|
|
197
210
|
}
|
|
211
|
+
async isAuthenticated() {
|
|
212
|
+
try {
|
|
213
|
+
await execa("sudo", ["--non-interactive", "--validate"], { stdin: "ignore" });
|
|
214
|
+
return true;
|
|
215
|
+
} catch {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
198
219
|
enqueue(managerArguments, task) {
|
|
199
220
|
const operation = this.queue.then(async () => {
|
|
221
|
+
if (!await this.isAuthenticated()) throw new Error("Administrator access is no longer available for apt-get. Run 'sudo --validate' and then run this tool again.");
|
|
200
222
|
const subprocess = execa("sudo", [
|
|
201
223
|
"env",
|
|
202
224
|
...["DEBIAN_FRONTEND=noninteractive", "NEEDRESTART_SUSPEND=1"],
|
|
@@ -204,13 +226,15 @@ var DependencyManager = class {
|
|
|
204
226
|
...managerArguments
|
|
205
227
|
], { stdin: "ignore" });
|
|
206
228
|
let partial = "";
|
|
207
|
-
|
|
229
|
+
const track = (chunk) => {
|
|
208
230
|
partial += chunk.toString();
|
|
209
231
|
const lines = partial.split(/\r\n|\r|\n/);
|
|
210
232
|
partial = lines.pop() ?? "";
|
|
211
233
|
const line = lines.at(-1)?.trim();
|
|
212
234
|
if (line) task.continue(line);
|
|
213
|
-
}
|
|
235
|
+
};
|
|
236
|
+
subprocess.stdout?.on("data", track);
|
|
237
|
+
subprocess.stderr?.on("data", track);
|
|
214
238
|
await subprocess;
|
|
215
239
|
});
|
|
216
240
|
this.queue = operation.catch(() => {});
|
|
@@ -563,14 +587,16 @@ var VersionControlSystem = class {
|
|
|
563
587
|
context.logger.add(task);
|
|
564
588
|
task.start();
|
|
565
589
|
const dependencies = ["git", "build-essential"];
|
|
566
|
-
if (await context.dependencyManager.isInstalled(dependencies)) {
|
|
567
|
-
task.
|
|
568
|
-
|
|
590
|
+
if (!await context.dependencyManager.isInstalled(dependencies)) {
|
|
591
|
+
task.continue("Update package manager");
|
|
592
|
+
await context.dependencyManager.update(task);
|
|
593
|
+
task.continue(`Installing dependencies: ${dependencies.join(", ")}`);
|
|
594
|
+
await context.dependencyManager.install(dependencies, task);
|
|
569
595
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
task.continue(
|
|
573
|
-
await
|
|
596
|
+
const sourceFilePath = path.join(context.directories.assets, ".gitconfig");
|
|
597
|
+
const destinationFilePath = path.join(context.directories.home, ".gitconfig");
|
|
598
|
+
task.continue("Copy configuration");
|
|
599
|
+
await fs.copyFile(sourceFilePath, destinationFilePath);
|
|
574
600
|
task.finish();
|
|
575
601
|
}
|
|
576
602
|
};
|
|
@@ -599,9 +625,10 @@ var Wallpapers = class {
|
|
|
599
625
|
};
|
|
600
626
|
//#endregion
|
|
601
627
|
//#region source/setup-ubuntu.ts
|
|
602
|
-
program.name(name).version(version).description("
|
|
628
|
+
program.name(name).version(version).description("Sets up a fresh Ubuntu machine with a standard set of tools, configuration, and dotfiles.").action(async () => {
|
|
603
629
|
const logger = new Logger();
|
|
604
630
|
const dependencyManager = new DependencyManager();
|
|
631
|
+
await dependencyManager.authenticate();
|
|
605
632
|
logger.start();
|
|
606
633
|
const packages = [
|
|
607
634
|
new AgentRules(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hurshb50/setup-ubuntu",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"distribution"
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"onFail": "download"
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
|
-
"description": "
|
|
44
|
+
"description": "Sets up a fresh Ubuntu machine with a standard set of tools, configuration, and dotfiles.",
|
|
45
45
|
"homepage": "https://github.com/hurshb50/setup-ubuntu#readme",
|
|
46
46
|
"bugs": {
|
|
47
47
|
"url": "https://github.com/hurshb50/setup-ubuntu/issues"
|