@bastani/atomic 0.5.14-0 → 0.5.15-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/.claude/settings.json +24 -0
- package/.opencode/opencode.json +10 -0
- package/README.md +10 -58
- package/assets/settings.schema.json +29 -0
- package/dist/sdk/runtime/executor.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts +4 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts +4 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts +4 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts.map +1 -1
- package/dist/services/config/atomic-config.d.ts +44 -0
- package/dist/services/config/atomic-config.d.ts.map +1 -0
- package/dist/services/config/definitions.d.ts +18 -13
- package/dist/services/config/definitions.d.ts.map +1 -1
- package/dist/services/config/index.d.ts +7 -0
- package/dist/services/config/index.d.ts.map +1 -0
- package/dist/services/config/settings-schema.d.ts +2 -0
- package/dist/services/config/settings-schema.d.ts.map +1 -0
- package/dist/services/system/copy.d.ts +8 -1
- package/dist/services/system/copy.d.ts.map +1 -1
- package/package.json +3 -1
- package/src/cli.ts +1 -30
- package/src/commands/cli/chat/index.ts +21 -6
- package/src/commands/cli/init/index.ts +78 -323
- package/src/commands/cli/init/onboarding.ts +4 -10
- package/src/commands/cli/init/scm.ts +3 -34
- package/src/lib/common-ignore.ts +46 -0
- package/src/lib/merge.ts +28 -1
- package/src/sdk/runtime/executor.ts +85 -52
- package/src/sdk/workflows/builtin/deep-research-codebase/claude/index.ts +9 -4
- package/src/sdk/workflows/builtin/deep-research-codebase/copilot/index.ts +12 -7
- package/src/sdk/workflows/builtin/deep-research-codebase/opencode/index.ts +12 -7
- package/src/services/config/atomic-config.ts +95 -1
- package/src/services/config/atomic-global-config.ts +8 -21
- package/src/services/config/definitions.ts +41 -44
- package/src/services/config/settings.ts +2 -1
- package/src/services/system/agents.ts +2 -1
- package/src/services/system/copy.ts +18 -7
- package/src/services/system/skills.ts +3 -1
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
* Agent configuration definitions for atomic CLI
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { stat } from "node:fs/promises";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
|
|
5
8
|
export interface AgentConfig {
|
|
6
9
|
/** Display name for the agent */
|
|
7
10
|
name: string;
|
|
@@ -36,12 +39,10 @@ export const AGENT_CONFIG: Record<AgentKey, AgentConfig> = {
|
|
|
36
39
|
"--allow-dangerously-skip-permissions",
|
|
37
40
|
"--dangerously-skip-permissions",
|
|
38
41
|
],
|
|
39
|
-
env_vars: {
|
|
40
|
-
CLAUDE_CODE_NO_FLICKER: "1",
|
|
41
|
-
},
|
|
42
|
+
env_vars: {},
|
|
42
43
|
folder: ".claude",
|
|
43
44
|
install_url: "https://code.claude.com/docs/en/setup",
|
|
44
|
-
exclude: [
|
|
45
|
+
exclude: [],
|
|
45
46
|
onboarding_files: [
|
|
46
47
|
{
|
|
47
48
|
source: ".mcp.json",
|
|
@@ -62,14 +63,7 @@ export const AGENT_CONFIG: Record<AgentKey, AgentConfig> = {
|
|
|
62
63
|
env_vars: { OPENCODE_EXPERIMENTAL_LSP_TOOL: "true" },
|
|
63
64
|
folder: ".opencode",
|
|
64
65
|
install_url: "https://opencode.ai",
|
|
65
|
-
exclude: [
|
|
66
|
-
"node_modules",
|
|
67
|
-
".gitignore",
|
|
68
|
-
"bun.lock",
|
|
69
|
-
"package.json",
|
|
70
|
-
".DS_Store",
|
|
71
|
-
"opencode.json",
|
|
72
|
-
],
|
|
66
|
+
exclude: [".gitignore", "package.json"],
|
|
73
67
|
onboarding_files: [
|
|
74
68
|
{
|
|
75
69
|
source: ".opencode/opencode.json",
|
|
@@ -81,30 +75,37 @@ export const AGENT_CONFIG: Record<AgentKey, AgentConfig> = {
|
|
|
81
75
|
copilot: {
|
|
82
76
|
name: "GitHub Copilot CLI",
|
|
83
77
|
cmd: "copilot",
|
|
84
|
-
chat_flags: [
|
|
85
|
-
"--add-dir",
|
|
86
|
-
".",
|
|
87
|
-
"--yolo",
|
|
88
|
-
"--experimental",
|
|
89
|
-
"--no-auto-update",
|
|
90
|
-
],
|
|
78
|
+
chat_flags: ["--add-dir", ".", "--yolo", "--experimental"],
|
|
91
79
|
env_vars: {
|
|
92
80
|
COPILOT_ALLOW_ALL: "true",
|
|
93
81
|
},
|
|
94
82
|
folder: ".github",
|
|
95
83
|
install_url:
|
|
96
84
|
"https://github.com/github/copilot-cli?tab=readme-ov-file#installation",
|
|
97
|
-
exclude: ["workflows", "dependabot.yml"
|
|
85
|
+
exclude: ["workflows", "dependabot.yml"],
|
|
98
86
|
onboarding_files: [
|
|
99
87
|
{
|
|
100
|
-
source: ".
|
|
101
|
-
destination: ".
|
|
88
|
+
source: ".mcp.json",
|
|
89
|
+
destination: ".mcp.json",
|
|
102
90
|
merge: true,
|
|
103
91
|
},
|
|
104
92
|
],
|
|
105
93
|
},
|
|
106
94
|
};
|
|
107
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Per-provider overrides that users can set in `.atomic/settings.json`
|
|
98
|
+
* (local) or `~/.atomic/settings.json` (global).
|
|
99
|
+
*
|
|
100
|
+
* - `chatFlags`: when set, replaces the agent's default `chat_flags` entirely.
|
|
101
|
+
* - `envVars`: environment variables merged on top of the agent's default
|
|
102
|
+
* `env_vars` (user values win on conflict).
|
|
103
|
+
*/
|
|
104
|
+
export interface ProviderOverrides {
|
|
105
|
+
chatFlags?: string[];
|
|
106
|
+
envVars?: Record<string, string>;
|
|
107
|
+
}
|
|
108
|
+
|
|
108
109
|
export function isValidAgent(key: string): key is AgentKey {
|
|
109
110
|
return key in AGENT_CONFIG;
|
|
110
111
|
}
|
|
@@ -128,49 +129,31 @@ const SCM_KEYS = ["github", "sapling"] as const;
|
|
|
128
129
|
export type SourceControlType = (typeof SCM_KEYS)[number];
|
|
129
130
|
|
|
130
131
|
export interface ScmConfig {
|
|
131
|
-
/** Internal identifier */
|
|
132
|
-
name: string;
|
|
133
132
|
/** Display name for prompts */
|
|
134
133
|
displayName: string;
|
|
135
134
|
/** Primary CLI tool (git or sl) */
|
|
136
135
|
cliTool: string;
|
|
137
|
-
/** Code review tool (gh, jf submit, arc diff, etc.) */
|
|
138
|
-
reviewTool: string;
|
|
139
136
|
/** Code review system (github, phabricator) */
|
|
140
137
|
reviewSystem: string;
|
|
141
|
-
/** Directory marker
|
|
138
|
+
/** Directory marker used to detect this SCM in a repo (e.g. `.git`, `.sl`) */
|
|
142
139
|
detectDir: string;
|
|
143
|
-
/** Code review command file name */
|
|
144
|
-
reviewCommandFile: string;
|
|
145
|
-
/** Required configuration files */
|
|
146
|
-
requiredConfigFiles?: string[];
|
|
147
140
|
}
|
|
148
141
|
|
|
149
142
|
export const SCM_CONFIG: Record<SourceControlType, ScmConfig> = {
|
|
150
143
|
github: {
|
|
151
|
-
name: "github",
|
|
152
144
|
displayName: "GitHub / Git",
|
|
153
145
|
cliTool: "git",
|
|
154
|
-
reviewTool: "gh",
|
|
155
146
|
reviewSystem: "github",
|
|
156
147
|
detectDir: ".git",
|
|
157
|
-
reviewCommandFile: "create-gh-pr.md",
|
|
158
148
|
},
|
|
159
149
|
sapling: {
|
|
160
|
-
name: "sapling",
|
|
161
150
|
displayName: "Sapling + Phabricator",
|
|
162
151
|
cliTool: "sl",
|
|
163
|
-
reviewTool: "jf submit",
|
|
164
152
|
reviewSystem: "phabricator",
|
|
165
153
|
detectDir: ".sl",
|
|
166
|
-
reviewCommandFile: "submit-diff.md",
|
|
167
|
-
requiredConfigFiles: [".arcconfig", "~/.arcrc"],
|
|
168
154
|
},
|
|
169
155
|
};
|
|
170
156
|
|
|
171
|
-
/** Commands that have SCM-specific variants */
|
|
172
|
-
export const SCM_SPECIFIC_COMMANDS = ["commit"];
|
|
173
|
-
|
|
174
157
|
/**
|
|
175
158
|
* SCM-variant skill names, grouped by source control type.
|
|
176
159
|
*
|
|
@@ -207,8 +190,22 @@ export function isValidScm(key: string): key is SourceControlType {
|
|
|
207
190
|
}
|
|
208
191
|
|
|
209
192
|
/**
|
|
210
|
-
*
|
|
193
|
+
* Detect the SCM type by looking for marker directories in `projectRoot`.
|
|
194
|
+
*
|
|
195
|
+
* Checks each {@link ScmConfig.detectDir} (e.g. `.git`, `.sl`) and returns
|
|
196
|
+
* the first match. Returns `null` when no known marker is found.
|
|
211
197
|
*/
|
|
212
|
-
export function
|
|
213
|
-
|
|
198
|
+
export async function detectScmType(
|
|
199
|
+
projectRoot: string,
|
|
200
|
+
): Promise<SourceControlType | null> {
|
|
201
|
+
for (const key of getScmKeys()) {
|
|
202
|
+
const markerPath = join(projectRoot, SCM_CONFIG[key].detectDir);
|
|
203
|
+
try {
|
|
204
|
+
await stat(markerPath);
|
|
205
|
+
return key;
|
|
206
|
+
} catch {
|
|
207
|
+
// marker not found — try next
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return null;
|
|
214
211
|
}
|
|
@@ -14,7 +14,7 @@ import { homedir } from "node:os";
|
|
|
14
14
|
import { SETTINGS_SCHEMA_URL } from "./settings-schema.ts";
|
|
15
15
|
import { ensureDir } from "../system/copy.ts";
|
|
16
16
|
import { errorMessage } from "../../sdk/errors.ts";
|
|
17
|
-
import type { AgentKey, SourceControlType } from "./definitions.ts";
|
|
17
|
+
import type { AgentKey, ProviderOverrides, SourceControlType } from "./definitions.ts";
|
|
18
18
|
|
|
19
19
|
export interface TrustedPathEntry {
|
|
20
20
|
workspacePath: string;
|
|
@@ -28,6 +28,7 @@ interface AtomicSettings {
|
|
|
28
28
|
lastUpdated?: string;
|
|
29
29
|
trustedPaths?: TrustedPathEntry[];
|
|
30
30
|
telemetryEnabled?: boolean;
|
|
31
|
+
providers?: Partial<Record<AgentKey, ProviderOverrides>>;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
/** Runtime guard for parsed JSON to ensure it's a plain object. */
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
ensureDir,
|
|
26
26
|
pathExists,
|
|
27
27
|
} from "./copy.ts";
|
|
28
|
+
import { createCommonIgnoreFilter } from "../../lib/common-ignore.ts";
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* Locate the package root by walking up from this module. Both in installed
|
|
@@ -72,7 +73,7 @@ export async function installGlobalAgents(): Promise<void> {
|
|
|
72
73
|
continue;
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
await copyDir(src, dest);
|
|
76
|
+
await copyDir(src, dest, { ignoreFilter: createCommonIgnoreFilter() });
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
// Surface skipped sources via a non-fatal thrown error only if ALL sources
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { readdir, mkdir, stat, readFile } from "node:fs/promises";
|
|
6
6
|
import { mkdirSync } from "node:fs";
|
|
7
7
|
import { join, extname, relative, resolve } from "node:path";
|
|
8
|
+
import type { Ignore } from "ignore";
|
|
8
9
|
import { getOppositeScriptExtension } from "./detect.ts";
|
|
9
10
|
import {
|
|
10
11
|
assertPathWithinRoot,
|
|
@@ -77,6 +78,8 @@ export function isPathSafe(basePath: string, targetPath: string): boolean {
|
|
|
77
78
|
interface CopyOptions {
|
|
78
79
|
/** Paths to exclude (relative to source root or base names) */
|
|
79
80
|
exclude?: string[];
|
|
81
|
+
/** Gitignore-style filter for common junk patterns (via the `ignore` package) */
|
|
82
|
+
ignoreFilter?: Ignore;
|
|
80
83
|
/** Whether to skip scripts for the opposite platform */
|
|
81
84
|
skipOppositeScripts?: boolean;
|
|
82
85
|
}
|
|
@@ -158,21 +161,29 @@ async function copySymlinkAsFileWithOverwriteOption(
|
|
|
158
161
|
* Check if a path should be excluded based on exclusion rules.
|
|
159
162
|
* Uses normalized paths (forward slashes) to ensure consistent matching
|
|
160
163
|
* on both Windows and Unix systems.
|
|
164
|
+
*
|
|
165
|
+
* When an {@link Ignore} filter is provided, gitignore-style glob patterns
|
|
166
|
+
* are evaluated first so common junk files (.DS_Store, node_modules, etc.)
|
|
167
|
+
* are filtered automatically without polluting the explicit `exclude` list.
|
|
161
168
|
*/
|
|
162
169
|
export function shouldExclude(
|
|
163
170
|
relativePath: string,
|
|
164
171
|
name: string,
|
|
165
|
-
exclude: string[]
|
|
172
|
+
exclude: string[],
|
|
173
|
+
ignoreFilter?: Ignore,
|
|
166
174
|
): boolean {
|
|
175
|
+
const normalizedPath = normalizePath(relativePath);
|
|
176
|
+
|
|
177
|
+
// Gitignore-style patterns take precedence
|
|
178
|
+
if (ignoreFilter?.ignores(normalizedPath)) {
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
|
|
167
182
|
// Check if the name matches any exclusion
|
|
168
183
|
if (exclude.includes(name)) {
|
|
169
184
|
return true;
|
|
170
185
|
}
|
|
171
186
|
|
|
172
|
-
// Normalize the relative path for cross-platform comparison
|
|
173
|
-
// This ensures Windows backslash paths match forward-slash exclusion patterns
|
|
174
|
-
const normalizedPath = normalizePath(relativePath);
|
|
175
|
-
|
|
176
187
|
// Check if the relative path starts with any exclusion
|
|
177
188
|
for (const ex of exclude) {
|
|
178
189
|
const normalizedExclusion = normalizePath(ex);
|
|
@@ -205,7 +216,7 @@ async function copyDirInternal(
|
|
|
205
216
|
overwriteExisting: boolean = true,
|
|
206
217
|
): Promise<void> {
|
|
207
218
|
try {
|
|
208
|
-
const { exclude = [], skipOppositeScripts = true } = options;
|
|
219
|
+
const { exclude = [], ignoreFilter, skipOppositeScripts = true } = options;
|
|
209
220
|
const root = rootSrc ?? src;
|
|
210
221
|
const destinationRoot = rootDest ?? dest;
|
|
211
222
|
|
|
@@ -245,7 +256,7 @@ async function copyDirInternal(
|
|
|
245
256
|
}
|
|
246
257
|
|
|
247
258
|
// Check if this path should be excluded
|
|
248
|
-
if (shouldExclude(relativePath, entry.name, exclude)) {
|
|
259
|
+
if (shouldExclude(relativePath, entry.name, exclude, ignoreFilter)) {
|
|
249
260
|
continue;
|
|
250
261
|
}
|
|
251
262
|
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import { join } from "node:path";
|
|
19
19
|
import { homedir } from "node:os";
|
|
20
20
|
import { ALL_SCM_SKILLS } from "../config/index.ts";
|
|
21
|
+
import { createCommonIgnoreFilter } from "../../lib/common-ignore.ts";
|
|
21
22
|
import { copyDir, pathExists } from "./copy.ts";
|
|
22
23
|
|
|
23
24
|
/**
|
|
@@ -64,10 +65,11 @@ export async function installGlobalSkills(): Promise<void> {
|
|
|
64
65
|
|
|
65
66
|
// Build the exclusion list from SCM skill names
|
|
66
67
|
const exclude = [...SCM_SKILL_SET];
|
|
68
|
+
const ignoreFilter = createCommonIgnoreFilter();
|
|
67
69
|
|
|
68
70
|
await Promise.all(
|
|
69
71
|
SKILL_DEST_DIRS.map((rel) =>
|
|
70
|
-
copyDir(src, join(home, rel), { exclude }),
|
|
72
|
+
copyDir(src, join(home, rel), { exclude, ignoreFilter }),
|
|
71
73
|
),
|
|
72
74
|
);
|
|
73
75
|
}
|