ardfw 0.1.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/README.md ADDED
@@ -0,0 +1,161 @@
1
+ # Agentics Framework
2
+
3
+ An AI agentics framework for building multi-agent systems focused on software engineering, datascience research, and personal knowledge management. Built for Claude Code and Claude Agent SDK, with support for other agentics platforms like OpenCode and Cursor.
4
+
5
+ ## The Problem
6
+
7
+ Building robust multi-agent systems is challenging:
8
+ - **Inconsistent agent definitions** - Each agent defined differently across projects
9
+ - **Skill duplication** - Writing the same capabilities for different agents
10
+ - **Workflow complexity** - Orchestrating commands and agents is ad-hoc
11
+ - **Limited extensibility** - Hard to add custom skills and MCP servers
12
+
13
+ ## The Solution
14
+
15
+ This framework provides a standardized system for:
16
+ - **Standardized Agent Definitions** - Consistent structure for defining specialized agents
17
+ - **Reusable Skill Library** - Build skills once, use across multiple agents
18
+ - **Command Workflow Automation** - Chain commands and agents for complex workflows
19
+ - **Custom Skills & MCP Servers** - Extend agents with custom capabilities and MCP integrations
20
+
21
+ ## Architecture
22
+
23
+ The framework is built on the **ARD** design pattern:
24
+
25
+ - **Abstract** - Take existing methods and abstract them to understand underlying frameworks and context from user input
26
+ - **Refactor** - Modularize and reorganize ideas from abstraction
27
+ - **Derivative** - Derive new specialized variations from existing ideas
28
+
29
+ ### Core Components
30
+
31
+ The framework has three essential building blocks that work together:
32
+
33
+ #### 1. **Agents** (`/agents`)
34
+ Specialized AI agents with defined roles and capabilities. Each agent is a prompt template with specific expertise (e.g., architect, developer, analyst, tech-writer, etc.). These are the primary abstractions users work with.
35
+
36
+ **Examples:**
37
+ - `architect.md` - Architecture and design decisions
38
+ - `dev.md` - Software development and coding
39
+ - `analyst.md` - Data analysis and research
40
+ - `tech-writer.md` - Documentation and technical writing
41
+ - `pm.md` - Project management
42
+ - `ux-designer.md` - UI/UX design
43
+ - `sm.md` - Scrum/agile management
44
+ - `agent-dev.md` - Building custom agents
45
+
46
+ #### 2. **Commands** (`/commands`)
47
+ Reusable Claude Code commands that orchestrate agents and define workflows. Commands are executed via Claude Code and can chain multiple agents together.
48
+
49
+ **Core commands:**
50
+ - `prime.md` - Understand a codebase quickly
51
+ - `quick-plan.md` - Create rapid implementation plans
52
+ - `build.md` - Execute implementations
53
+ - `meta-prompt.md` - Generate new command prompts
54
+ - `load_ai_docs.md` - Load documentation context
55
+ - `parallel_subagents.md` - Orchestrate multiple agents in parallel
56
+
57
+ **Expert commands** (`/commands/experts`)
58
+ - `plan.md` - Create detailed implementation plans
59
+ - `build.md` - Execute plans with expert guidance
60
+ - `plan-build-improve.md` - Complete workflow with continuous improvement
61
+ - `self-improve.md` - Update expertise based on learnings
62
+
63
+ #### 3. **Skills** (`/skills`)
64
+ Reusable capabilities that agents can use. Skills are MCP servers, tools, and utility functions that extend agent capabilities.
65
+
66
+ **Examples:**
67
+ - Custom MCP servers for domain-specific tasks
68
+ - Tool definitions for agent use
69
+ - Integration skills for connecting to external systems
70
+
71
+ ### Project Structure
72
+
73
+ ```
74
+ agentics/
75
+ ├── agents/ # Agent definitions
76
+ │ ├── architect.md
77
+ │ ├── dev.md
78
+ │ ├── analyst.md
79
+ │ └── ... (other agents)
80
+ ├── commands/ # Command workflows
81
+ │ ├── prime.md
82
+ │ ├── quick-plan.md
83
+ │ ├── build.md
84
+ │ └── experts/ # Expert command variants
85
+ └── skills/ # Reusable skills & MCP servers
86
+ └── meta-skills/
87
+ ```
88
+
89
+ Project-specific workflows and templates are built **outside** these core folders in your project directory.
90
+
91
+ ## Getting Started
92
+
93
+ ### Installation & Setup
94
+
95
+ 1. **Clone this repository** to your `_ard` folder or relevant configuration directory:
96
+ ```bash
97
+ git clone <repo> ~/_ard/agentics
98
+ ```
99
+
100
+ 2. **Symlink to your projects** - Link the framework into your project directories:
101
+ ```bash
102
+ ln -s ~/_ard/agentics/agents ./project/_ard/agents
103
+ ln -s ~/_ard/agentics/commands ./project/_ard/commands
104
+ ln -s ~/_ard/agentics/skills ./project/_ard/skills
105
+ ```
106
+
107
+ 3. **Use in Claude Code** - Reference agents and commands in your Claude Code workflows
108
+
109
+ ### Your First Agent
110
+
111
+ 1. Start with the `prime` command to understand your codebase:
112
+ ```
113
+ /prime
114
+ ```
115
+
116
+ 2. Create a plan using `quick-plan`:
117
+ ```
118
+ /quick-plan
119
+ ```
120
+
121
+ 3. Execute with the appropriate agent (architect for design, dev for implementation, etc.)
122
+
123
+ ### Creating Custom Agents
124
+
125
+ Use the `agent-dev.md` agent or `meta-prompt` command to create new specialized agents:
126
+
127
+ ```
128
+ /meta-prompt "Create a [Role] agent that handles [Responsibility]"
129
+ ```
130
+
131
+ ### Creating Custom Skills
132
+
133
+ Define custom skills in the `/skills` directory following the established patterns. Skills can be:
134
+ - MCP servers
135
+ - Tool definitions
136
+ - Integration wrappers
137
+
138
+ ## Platform Compatibility
139
+
140
+ - **Primary**: Claude Code & Claude Agent SDK
141
+ - **Compatible**: OpenCode, Cursor, and other agentics platforms (with adaptations)
142
+
143
+ ## Current Status
144
+
145
+ **Internal/Experimental** - This framework is actively being developed. It's suitable for internal use and early adopter feedback, but not yet production-ready for external distribution.
146
+
147
+ ## Next Steps
148
+
149
+ - [ ] Define each agent's specific capabilities and use cases
150
+ - [ ] Build a comprehensive skill library with examples
151
+ - [ ] Create workflow templates for common scenarios
152
+ - [ ] Document best practices for extending the framework
153
+ - [ ] Add examples and sample projects
154
+
155
+ ## Contributing
156
+
157
+ For internal development:
158
+ 1. Create new agent definitions in `/agents`
159
+ 2. Add commands in `/commands`
160
+ 3. Extend skills in `/skills`
161
+ 4. Follow the ARD pattern for consistency
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "ardfw",
3
+ "version": "0.1.0",
4
+ "description": "Agentics Framework CLI - Multi-agent system for Claude Code and OpenCode",
5
+ "bin": {
6
+ "ardfw": "tools/ard-npx-wrapper.js",
7
+ "ard": "tools/ard-npx-wrapper.js"
8
+ },
9
+ "files": [
10
+ "tools/",
11
+ "src/project_config/"
12
+ ],
13
+ "scripts": {
14
+ "test": "echo \"No tests yet\"",
15
+ "ard:install": "node tools/ard-npx-wrapper.js install"
16
+ },
17
+ "dependencies": {
18
+ "chalk": "^5.3.0",
19
+ "commander": "^12.0.0",
20
+ "fs-extra": "^11.2.0",
21
+ "inquirer": "^9.2.0",
22
+ "yaml": "^2.3.0"
23
+ },
24
+ "engines": {
25
+ "node": ">=18.0.0"
26
+ },
27
+ "type": "module",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/uechanx/agentics.git"
31
+ },
32
+ "keywords": [
33
+ "agentics",
34
+ "claude-code",
35
+ "opencode",
36
+ "ai-agents",
37
+ "cli"
38
+ ],
39
+ "author": "uechanx",
40
+ "license": "MIT"
41
+ }
@@ -0,0 +1,19 @@
1
+ # Project: {{PROJECT_NAME}}
2
+
3
+ ## Overview
4
+ <!-- Describe your project here -->
5
+
6
+ ## Tech Stack
7
+ <!-- List key technologies, frameworks, and tools -->
8
+
9
+ ## Project Structure
10
+ <!-- Describe directory layout and organization -->
11
+
12
+ ## Conventions
13
+ <!-- Document coding conventions, naming patterns, etc. -->
14
+
15
+ ## Development Commands
16
+ <!-- Common dev commands for building, testing, running -->
17
+
18
+ ## Notes for AI Agents
19
+ <!-- Special instructions, constraints, or context for AI assistance -->
File without changes
File without changes
@@ -0,0 +1,3 @@
1
+ {
2
+ "spinnerTipsEnabled": true
3
+ }
File without changes
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ard CLI wrapper
4
+ * Handles npx execution context and delegates to main CLI
5
+ */
6
+
7
+ import { execSync } from 'node:child_process';
8
+ import path from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = path.dirname(__filename);
13
+
14
+ // Detect if running through npx (npm cache directory)
15
+ const isNpxExecution = __dirname.includes('_npx') || __dirname.includes('.npm');
16
+
17
+ if (isNpxExecution) {
18
+ // Running via npx - spawn child process to preserve CWD
19
+ const ardCliPath = path.join(__dirname, 'cli', 'ard-cli.js');
20
+ const args = process.argv.slice(2);
21
+
22
+ try {
23
+ execSync(`node "${ardCliPath}" ${args.join(' ')}`, {
24
+ stdio: 'inherit',
25
+ cwd: process.cwd(), // Preserve user's working directory
26
+ });
27
+ } catch (error) {
28
+ process.exit(error.status || 1);
29
+ }
30
+ } else {
31
+ // Running locally - dynamic import
32
+ await import('./cli/ard-cli.js');
33
+ }
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ard CLI - Agentics Framework installer
4
+ */
5
+
6
+ import { Command } from 'commander';
7
+ import fs from 'node:fs';
8
+ import path from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = path.dirname(__filename);
13
+
14
+ // Load package.json for version
15
+ const packageJsonPath = path.resolve(__dirname, '../../package.json');
16
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
17
+
18
+ const program = new Command();
19
+
20
+ program
21
+ .name('ard')
22
+ .description('Agentics Framework CLI - Multi-agent system for Claude Code and OpenCode')
23
+ .version(packageJson.version);
24
+
25
+ // Dynamically load commands from commands/ directory
26
+ const commandsDir = path.join(__dirname, 'commands');
27
+
28
+ if (fs.existsSync(commandsDir)) {
29
+ const commandFiles = fs.readdirSync(commandsDir).filter((f) => f.endsWith('.js'));
30
+
31
+ for (const file of commandFiles) {
32
+ const commandModule = await import(path.join(commandsDir, file));
33
+ const command = commandModule.default;
34
+
35
+ const cmd = program.command(command.command).description(command.description);
36
+
37
+ // Add options if defined
38
+ if (command.options) {
39
+ for (const opt of command.options) {
40
+ cmd.option(...opt);
41
+ }
42
+ }
43
+
44
+ cmd.action(command.action);
45
+ }
46
+ }
47
+
48
+ // Show help if no command provided
49
+ if (process.argv.length <= 2) {
50
+ program.help();
51
+ }
52
+
53
+ program.parse(process.argv);
@@ -0,0 +1,81 @@
1
+ /**
2
+ * install command - Sets up Agentics in a project
3
+ */
4
+
5
+ import Installer from '../lib/installer.js';
6
+ import UI from '../lib/ui.js';
7
+ import chalk from 'chalk';
8
+
9
+ export default {
10
+ command: 'install',
11
+ description: 'Install Agentics Framework in current project',
12
+ options: [
13
+ ['--force', 'Overwrite existing installation'],
14
+ ['--claude', 'Enable Claude Code integration'],
15
+ ['--opencode', 'Enable OpenCode integration'],
16
+ ['-y, --yes', 'Skip prompts, use defaults'],
17
+ ],
18
+
19
+ async action(options) {
20
+ const ui = new UI();
21
+ const installer = new Installer();
22
+
23
+ console.log(chalk.blue('\n🤖 Agentics Framework Installer\n'));
24
+
25
+ try {
26
+ // Check for existing installation
27
+ const existing = installer.checkExisting();
28
+
29
+ if (existing && !options.force) {
30
+ if (options.yes) {
31
+ // In non-interactive mode with existing install, just update
32
+ await installer.update();
33
+ console.log(chalk.green('\n✅ Agentics updated successfully!'));
34
+ return;
35
+ }
36
+
37
+ const { action } = await ui.promptExistingInstall(existing);
38
+
39
+ if (action === 'cancel') {
40
+ console.log(chalk.yellow('Installation cancelled.'));
41
+ return;
42
+ }
43
+
44
+ if (action === 'update') {
45
+ await installer.update();
46
+ console.log(chalk.green('\n✅ Agentics updated successfully!'));
47
+ return;
48
+ }
49
+ }
50
+
51
+ // Gather installation options
52
+ let config;
53
+ if (options.yes) {
54
+ config = {
55
+ enableClaude: options.claude !== false,
56
+ enableOpenCode: options.opencode || false,
57
+ projectName: 'my-project',
58
+ };
59
+ } else {
60
+ config = await ui.promptInstall(existing);
61
+ }
62
+
63
+ if (config.cancelled) {
64
+ console.log(chalk.yellow('Installation cancelled.'));
65
+ return;
66
+ }
67
+
68
+ // Run installation
69
+ await installer.install(config);
70
+
71
+ // Show success message
72
+ ui.showSuccess(config);
73
+ } catch (error) {
74
+ console.error(chalk.red('\n❌ Installation failed:'), error.message);
75
+ if (process.env.DEBUG) {
76
+ console.error(error.stack);
77
+ }
78
+ process.exit(1);
79
+ }
80
+ },
81
+ };
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Configuration constants for ARD CLI
3
+ */
4
+
5
+ export const PATHS = {
6
+ ARD_DIR: '_ard',
7
+ PROJECT_CONFIG: '_ard/project_config',
8
+ CONFIG_YAML: '_ard/config.yaml',
9
+ MANIFEST: '_ard/.manifest.json',
10
+ ARTIFACTS: '_ard/artifacts',
11
+ };
12
+
13
+ export const DEFAULT_CONFIG = {
14
+ project_name: 'my-project',
15
+ user_name: 'User',
16
+ output_folder: '_ard/artifacts',
17
+ planning_artifacts: '_ard/artifacts/planning',
18
+ implementation_artifacts: '_ard/artifacts/implementation',
19
+ product_knowledge: 'docs',
20
+ communication_language: 'en',
21
+ document_output_language: 'en',
22
+ user_skill_level: 'intermediate',
23
+ };
24
+
25
+ export const IDE_CONFIGS = {
26
+ claude: {
27
+ id: 'claude',
28
+ name: 'Claude Code',
29
+ linkName: '.claude',
30
+ contextFile: 'CLAUDE.md',
31
+ sourceContextFile: 'AGENTICS.md',
32
+ },
33
+ opencode: {
34
+ id: 'opencode',
35
+ name: 'OpenCode',
36
+ linkName: '.opencode',
37
+ contextFile: 'OPENCODE.md',
38
+ sourceContextFile: 'AGENTICS.md',
39
+ },
40
+ };
41
+
42
+ export const SYMLINK_MAPPINGS = [
43
+ { source: 'AGENTICS.md', targets: { claude: 'CLAUDE.md', opencode: 'OPENCODE.md' } },
44
+ { source: 'settings.json', targets: { claude: 'settings.json', opencode: 'settings.json' } },
45
+ { source: 'agents', targets: { claude: 'agents', opencode: 'agents' }, isDir: true },
46
+ { source: 'commands', targets: { claude: 'commands', opencode: 'commands' }, isDir: true },
47
+ { source: 'skills', targets: { claude: 'skills', opencode: 'skills' }, isDir: true },
48
+ ];
@@ -0,0 +1,76 @@
1
+ /**
2
+ * File operations utilities
3
+ */
4
+
5
+ import fs from 'fs-extra';
6
+ import path from 'node:path';
7
+
8
+ export default class FileOps {
9
+ constructor(projectRoot) {
10
+ this.projectRoot = projectRoot;
11
+ }
12
+
13
+ resolve(...paths) {
14
+ return path.join(this.projectRoot, ...paths);
15
+ }
16
+
17
+ async exists(filePath) {
18
+ return fs.pathExists(this.resolve(filePath));
19
+ }
20
+
21
+ async isSymlink(filePath) {
22
+ try {
23
+ const stat = await fs.lstat(this.resolve(filePath));
24
+ return stat.isSymbolicLink();
25
+ } catch {
26
+ return false;
27
+ }
28
+ }
29
+
30
+ async readSymlink(linkPath) {
31
+ return fs.readlink(this.resolve(linkPath));
32
+ }
33
+
34
+ async ensureDir(dirPath) {
35
+ return fs.ensureDir(this.resolve(dirPath));
36
+ }
37
+
38
+ async copy(src, dest, options = {}) {
39
+ return fs.copy(this.resolve(src), this.resolve(dest), options);
40
+ }
41
+
42
+ async writeFile(filePath, content) {
43
+ await fs.ensureDir(path.dirname(this.resolve(filePath)));
44
+ return fs.writeFile(this.resolve(filePath), content);
45
+ }
46
+
47
+ async readFile(filePath) {
48
+ return fs.readFile(this.resolve(filePath), 'utf8');
49
+ }
50
+
51
+ async remove(filePath) {
52
+ return fs.remove(this.resolve(filePath));
53
+ }
54
+
55
+ async symlink(target, linkPath, type = 'file') {
56
+ const fullLinkPath = this.resolve(linkPath);
57
+ await fs.ensureDir(path.dirname(fullLinkPath));
58
+
59
+ // Remove existing symlink if present
60
+ if (await this.isSymlink(linkPath)) {
61
+ await this.remove(linkPath);
62
+ }
63
+
64
+ // Create relative symlink
65
+ return fs.symlink(target, fullLinkPath, type);
66
+ }
67
+
68
+ async writeJson(filePath, data, options = { spaces: 2 }) {
69
+ await fs.ensureDir(path.dirname(this.resolve(filePath)));
70
+ return fs.writeJson(this.resolve(filePath), data, options);
71
+ }
72
+
73
+ async readJson(filePath) {
74
+ return fs.readJson(this.resolve(filePath));
75
+ }
76
+ }
@@ -0,0 +1,261 @@
1
+ /**
2
+ * Installer - Core installation logic
3
+ */
4
+
5
+ import fs from 'fs-extra';
6
+ import path from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+ import * as yaml from 'yaml';
9
+ import FileOps from './file-ops.js';
10
+ import { PATHS, DEFAULT_CONFIG, IDE_CONFIGS, SYMLINK_MAPPINGS } from './config.js';
11
+
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
14
+
15
+ export default class Installer {
16
+ constructor() {
17
+ this.projectRoot = process.cwd();
18
+ this.packageRoot = path.resolve(__dirname, '../../..');
19
+ this.fileOps = new FileOps(this.projectRoot);
20
+ }
21
+
22
+ /**
23
+ * Check for existing Agentics installation
24
+ */
25
+ checkExisting() {
26
+ const ardPath = path.join(this.projectRoot, PATHS.ARD_DIR);
27
+ const configPath = path.join(this.projectRoot, PATHS.CONFIG_YAML);
28
+
29
+ if (!fs.existsSync(ardPath)) {
30
+ return null;
31
+ }
32
+
33
+ try {
34
+ if (fs.existsSync(configPath)) {
35
+ const content = fs.readFileSync(configPath, 'utf8');
36
+ const config = yaml.parse(content);
37
+ return {
38
+ path: ardPath,
39
+ version: config.ard_version || 'unknown',
40
+ config,
41
+ };
42
+ }
43
+ } catch {
44
+ // Corrupted config
45
+ }
46
+
47
+ return { path: ardPath, version: 'unknown', config: null };
48
+ }
49
+
50
+ /**
51
+ * Get package version
52
+ */
53
+ getVersion() {
54
+ const packageJsonPath = path.join(this.packageRoot, 'package.json');
55
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
56
+ return packageJson.version;
57
+ }
58
+
59
+ /**
60
+ * Main installation
61
+ */
62
+ async install(options) {
63
+ const { enableClaude = true, enableOpenCode = false, projectName = 'my-project' } = options;
64
+
65
+ // 1. Create _ard directory structure
66
+ await this._createArdDirectory();
67
+
68
+ // 2. Copy project_config template
69
+ await this._copyProjectConfig();
70
+
71
+ // 3. Create config.yaml
72
+ await this._createConfigYaml(projectName, enableClaude, enableOpenCode);
73
+
74
+ // 4. Create artifacts directory
75
+ await this._createArtifactsDirectory();
76
+
77
+ // 5. Create IDE symlinks
78
+ if (enableClaude) {
79
+ await this._createIdeSymlinks('claude');
80
+ }
81
+ if (enableOpenCode) {
82
+ await this._createIdeSymlinks('opencode');
83
+ }
84
+
85
+ // 6. Create manifest for tracking
86
+ await this._createManifest(options);
87
+ }
88
+
89
+ /**
90
+ * Update existing installation
91
+ */
92
+ async update() {
93
+ // Read existing config
94
+ const existing = this.checkExisting();
95
+ if (!existing) {
96
+ throw new Error('No existing installation found');
97
+ }
98
+
99
+ // Backup existing project_config
100
+ const projectConfigPath = path.join(this.projectRoot, PATHS.PROJECT_CONFIG);
101
+ const backupPath = path.join(this.projectRoot, '_ard/project_config.backup');
102
+
103
+ if (fs.existsSync(projectConfigPath)) {
104
+ await fs.copy(projectConfigPath, backupPath);
105
+ }
106
+
107
+ // Copy new template, preserving user files
108
+ await this._copyProjectConfig({ merge: true });
109
+
110
+ // Update config.yaml version
111
+ await this._updateConfigVersion();
112
+ }
113
+
114
+ // === Private Methods ===
115
+
116
+ async _createArdDirectory() {
117
+ await this.fileOps.ensureDir(PATHS.ARD_DIR);
118
+ }
119
+
120
+ async _copyProjectConfig(options = {}) {
121
+ const srcPath = path.join(this.packageRoot, 'src/project_config');
122
+ const destPath = path.join(this.projectRoot, PATHS.PROJECT_CONFIG);
123
+
124
+ // Ensure source exists
125
+ if (!fs.existsSync(srcPath)) {
126
+ // Create minimal template if source doesn't exist yet
127
+ await this._createMinimalTemplate(destPath);
128
+ return;
129
+ }
130
+
131
+ await fs.copy(srcPath, destPath, {
132
+ overwrite: !options.merge, // Don't overwrite in merge mode
133
+ errorOnExist: false,
134
+ });
135
+ }
136
+
137
+ async _createMinimalTemplate(destPath) {
138
+ await fs.ensureDir(destPath);
139
+ await fs.ensureDir(path.join(destPath, 'agents'));
140
+ await fs.ensureDir(path.join(destPath, 'commands'));
141
+ await fs.ensureDir(path.join(destPath, 'skills'));
142
+
143
+ // Create AGENTICS.md
144
+ const agenticsContent = `# Project: ${path.basename(this.projectRoot)}
145
+
146
+ ## Overview
147
+ <!-- Describe your project here -->
148
+
149
+ ## Tech Stack
150
+ <!-- List key technologies -->
151
+
152
+ ## Project Structure
153
+ <!-- Describe directory layout -->
154
+
155
+ ## Conventions
156
+ <!-- Document coding conventions -->
157
+
158
+ ## Development Commands
159
+ <!-- Common dev commands -->
160
+
161
+ ## Notes for AI Agents
162
+ <!-- Special instructions -->
163
+ `;
164
+ await fs.writeFile(path.join(destPath, 'AGENTICS.md'), agenticsContent);
165
+
166
+ // Create settings.json
167
+ await fs.writeJson(path.join(destPath, 'settings.json'), { spinnerTipsEnabled: true }, { spaces: 2 });
168
+
169
+ // Create .gitkeep files
170
+ await fs.writeFile(path.join(destPath, 'agents/.gitkeep'), '');
171
+ await fs.writeFile(path.join(destPath, 'commands/.gitkeep'), '');
172
+ await fs.writeFile(path.join(destPath, 'skills/.gitkeep'), '');
173
+ }
174
+
175
+ async _createConfigYaml(projectName, enableClaude, enableOpenCode) {
176
+ const configPath = path.join(this.projectRoot, PATHS.CONFIG_YAML);
177
+
178
+ // Don't overwrite existing config
179
+ if (fs.existsSync(configPath)) {
180
+ return;
181
+ }
182
+
183
+ const config = {
184
+ ...DEFAULT_CONFIG,
185
+ project_name: projectName,
186
+ ard_version: this.getVersion(),
187
+ ides: {
188
+ claude: enableClaude,
189
+ opencode: enableOpenCode,
190
+ },
191
+ };
192
+
193
+ const yamlContent = yaml.stringify(config);
194
+ await fs.writeFile(configPath, `# Agentics Framework Configuration\n${yamlContent}`);
195
+ }
196
+
197
+ async _createArtifactsDirectory() {
198
+ const dirs = [PATHS.ARTIFACTS, `${PATHS.ARTIFACTS}/planning`, `${PATHS.ARTIFACTS}/implementation`];
199
+
200
+ for (const dir of dirs) {
201
+ await this.fileOps.ensureDir(dir);
202
+ }
203
+ }
204
+
205
+ async _createIdeSymlinks(ideId) {
206
+ const ideConfig = IDE_CONFIGS[ideId];
207
+ const idePath = path.join(this.projectRoot, ideConfig.linkName);
208
+
209
+ // Check if IDE directory exists and is not a symlink
210
+ if (fs.existsSync(idePath)) {
211
+ const stat = fs.lstatSync(idePath);
212
+ if (!stat.isSymbolicLink()) {
213
+ throw new Error(
214
+ `${ideConfig.linkName} exists and is not a symlink. ` +
215
+ `Please remove or rename it before installing.`
216
+ );
217
+ }
218
+ // Remove existing symlink
219
+ await fs.remove(idePath);
220
+ }
221
+
222
+ // Create IDE directory
223
+ await fs.ensureDir(idePath);
224
+
225
+ // Create individual symlinks for each file/directory
226
+ for (const mapping of SYMLINK_MAPPINGS) {
227
+ const sourcePath = path.join('..', PATHS.PROJECT_CONFIG, mapping.source);
228
+ const targetName = mapping.targets[ideId];
229
+ const targetPath = path.join(idePath, targetName);
230
+
231
+ // Create symlink
232
+ const symlinkType = mapping.isDir ? 'dir' : 'file';
233
+ await fs.symlink(sourcePath, targetPath, symlinkType);
234
+ }
235
+ }
236
+
237
+ async _createManifest(options) {
238
+ const manifestPath = path.join(this.projectRoot, PATHS.MANIFEST);
239
+
240
+ const manifest = {
241
+ installed_at: new Date().toISOString(),
242
+ version: this.getVersion(),
243
+ options: {
244
+ enableClaude: options.enableClaude,
245
+ enableOpenCode: options.enableOpenCode,
246
+ },
247
+ };
248
+
249
+ await fs.writeJson(manifestPath, manifest, { spaces: 2 });
250
+ }
251
+
252
+ async _updateConfigVersion() {
253
+ const configPath = path.join(this.projectRoot, PATHS.CONFIG_YAML);
254
+ const content = await fs.readFile(configPath, 'utf8');
255
+ const config = yaml.parse(content);
256
+
257
+ config.ard_version = this.getVersion();
258
+
259
+ await fs.writeFile(configPath, yaml.stringify(config));
260
+ }
261
+ }
@@ -0,0 +1,134 @@
1
+ /**
2
+ * UI - Interactive prompts for installation
3
+ */
4
+
5
+ import inquirer from 'inquirer';
6
+ import chalk from 'chalk';
7
+ import path from 'node:path';
8
+ import { IDE_CONFIGS } from './config.js';
9
+
10
+ export default class UI {
11
+ async promptExistingInstall(existing) {
12
+ const { action } = await inquirer.prompt([
13
+ {
14
+ type: 'list',
15
+ name: 'action',
16
+ message: `Agentics already installed (v${existing.version}). What would you like to do?`,
17
+ choices: [
18
+ { name: 'Update to latest version', value: 'update' },
19
+ { name: 'Reinstall (overwrites config)', value: 'reinstall' },
20
+ { name: 'Cancel', value: 'cancel' },
21
+ ],
22
+ },
23
+ ]);
24
+
25
+ return { action };
26
+ }
27
+
28
+ async promptInstall(existing) {
29
+ const answers = {};
30
+
31
+ // IDE Selection
32
+ const { ides } = await inquirer.prompt([
33
+ {
34
+ type: 'checkbox',
35
+ name: 'ides',
36
+ message: 'Select IDE integrations:',
37
+ choices: [
38
+ {
39
+ name: `${IDE_CONFIGS.claude.name} (${IDE_CONFIGS.claude.linkName}/)`,
40
+ value: 'claude',
41
+ checked: true,
42
+ },
43
+ {
44
+ name: `${IDE_CONFIGS.opencode.name} (${IDE_CONFIGS.opencode.linkName}/)`,
45
+ value: 'opencode',
46
+ checked: false,
47
+ },
48
+ ],
49
+ validate: (input) => {
50
+ if (input.length === 0) {
51
+ return 'Please select at least one IDE integration.';
52
+ }
53
+ return true;
54
+ },
55
+ },
56
+ ]);
57
+
58
+ answers.enableClaude = ides.includes('claude');
59
+ answers.enableOpenCode = ides.includes('opencode');
60
+
61
+ // Project name (optional)
62
+ const { projectName } = await inquirer.prompt([
63
+ {
64
+ type: 'input',
65
+ name: 'projectName',
66
+ message: 'Project name (for config):',
67
+ default: this._inferProjectName(),
68
+ },
69
+ ]);
70
+
71
+ answers.projectName = projectName;
72
+
73
+ // Confirmation
74
+ console.log(chalk.dim('\nInstallation summary:'));
75
+ console.log(chalk.dim(' - Create _ard/ directory'));
76
+ console.log(chalk.dim(' - Copy project_config template'));
77
+ if (answers.enableClaude) {
78
+ console.log(chalk.dim(` - Symlink ${IDE_CONFIGS.claude.linkName}/ -> _ard/project_config/`));
79
+ }
80
+ if (answers.enableOpenCode) {
81
+ console.log(chalk.dim(` - Symlink ${IDE_CONFIGS.opencode.linkName}/ -> _ard/project_config/`));
82
+ }
83
+
84
+ const { confirm } = await inquirer.prompt([
85
+ {
86
+ type: 'confirm',
87
+ name: 'confirm',
88
+ message: 'Proceed with installation?',
89
+ default: true,
90
+ },
91
+ ]);
92
+
93
+ if (!confirm) {
94
+ answers.cancelled = true;
95
+ }
96
+
97
+ return answers;
98
+ }
99
+
100
+ showSuccess(config) {
101
+ console.log(chalk.green('\n✅ Agentics Framework installed successfully!\n'));
102
+
103
+ console.log(chalk.bold('Created:'));
104
+ console.log(` ${chalk.cyan('_ard/')}`);
105
+ console.log(' ├── config.yaml');
106
+ console.log(' ├── project_config/');
107
+ console.log(' │ ├── AGENTICS.md');
108
+ console.log(' │ ├── settings.json');
109
+ console.log(' │ ├── agents/');
110
+ console.log(' │ ├── commands/');
111
+ console.log(' │ └── skills/');
112
+ console.log(' └── artifacts/');
113
+
114
+ if (config.enableClaude) {
115
+ console.log(` ${chalk.cyan('.claude/')} (symlinked to _ard/project_config/)`);
116
+ console.log(' └── CLAUDE.md -> AGENTICS.md');
117
+ }
118
+ if (config.enableOpenCode) {
119
+ console.log(` ${chalk.cyan('.opencode/')} (symlinked to _ard/project_config/)`);
120
+ console.log(' └── OPENCODE.md -> AGENTICS.md');
121
+ }
122
+
123
+ console.log(chalk.bold('\nNext steps:'));
124
+ console.log(' 1. Edit _ard/project_config/AGENTICS.md with your project context');
125
+ console.log(' 2. Add project-specific commands to _ard/project_config/commands/');
126
+ console.log(' 3. Start Claude Code and use /prime to explore your codebase');
127
+ console.log('');
128
+ }
129
+
130
+ _inferProjectName() {
131
+ const cwd = process.cwd();
132
+ return path.basename(cwd) || 'my-project';
133
+ }
134
+ }