cc-channel 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.
Files changed (62) hide show
  1. package/README.md +213 -0
  2. package/dist/claude/executor.d.ts +24 -0
  3. package/dist/claude/executor.d.ts.map +1 -0
  4. package/dist/claude/executor.js +109 -0
  5. package/dist/claude/executor.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +63 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/commands/config-cmd.d.ts +2 -0
  11. package/dist/commands/config-cmd.d.ts.map +1 -0
  12. package/dist/commands/config-cmd.js +105 -0
  13. package/dist/commands/config-cmd.js.map +1 -0
  14. package/dist/commands/init.d.ts +2 -0
  15. package/dist/commands/init.d.ts.map +1 -0
  16. package/dist/commands/init.js +167 -0
  17. package/dist/commands/init.js.map +1 -0
  18. package/dist/commands/logs.d.ts +4 -0
  19. package/dist/commands/logs.d.ts.map +1 -0
  20. package/dist/commands/logs.js +29 -0
  21. package/dist/commands/logs.js.map +1 -0
  22. package/dist/commands/start.d.ts +2 -0
  23. package/dist/commands/start.d.ts.map +1 -0
  24. package/dist/commands/start.js +70 -0
  25. package/dist/commands/start.js.map +1 -0
  26. package/dist/commands/status.d.ts +2 -0
  27. package/dist/commands/status.d.ts.map +1 -0
  28. package/dist/commands/status.js +69 -0
  29. package/dist/commands/status.js.map +1 -0
  30. package/dist/commands/stop.d.ts +2 -0
  31. package/dist/commands/stop.d.ts.map +1 -0
  32. package/dist/commands/stop.js +12 -0
  33. package/dist/commands/stop.js.map +1 -0
  34. package/dist/config.d.ts +23 -0
  35. package/dist/config.d.ts.map +1 -0
  36. package/dist/config.js +32 -0
  37. package/dist/config.js.map +1 -0
  38. package/dist/daemon/service.d.ts +42 -0
  39. package/dist/daemon/service.d.ts.map +1 -0
  40. package/dist/daemon/service.js +300 -0
  41. package/dist/daemon/service.js.map +1 -0
  42. package/dist/daemon.d.ts +7 -0
  43. package/dist/daemon.d.ts.map +1 -0
  44. package/dist/daemon.js +56 -0
  45. package/dist/daemon.js.map +1 -0
  46. package/dist/feishu/client.d.ts +38 -0
  47. package/dist/feishu/client.d.ts.map +1 -0
  48. package/dist/feishu/client.js +188 -0
  49. package/dist/feishu/client.js.map +1 -0
  50. package/dist/feishu/handler.d.ts +23 -0
  51. package/dist/feishu/handler.d.ts.map +1 -0
  52. package/dist/feishu/handler.js +225 -0
  53. package/dist/feishu/handler.js.map +1 -0
  54. package/dist/index.d.ts +5 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +6 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/session/store.d.ts +24 -0
  59. package/dist/session/store.d.ts.map +1 -0
  60. package/dist/session/store.js +135 -0
  61. package/dist/session/store.js.map +1 -0
  62. package/package.json +54 -0
package/README.md ADDED
@@ -0,0 +1,213 @@
1
+ # cc-channel
2
+
3
+ > Feishu/Lark channel for Claude Code - trigger Claude Code from Feishu messages
4
+
5
+ A lightweight service that lets you use Claude Code from Feishu/Lark. Send messages to your Feishu bot and get responses from Claude Code running on your local machine.
6
+
7
+ ## Features
8
+
9
+ - 🚀 **Easy setup** - One command initialization
10
+ - 💬 **Multi-turn conversations** - Maintains context across messages
11
+ - 🔄 **Background service** - Runs as a daemon, no terminal needed
12
+ - 📁 **Per-chat working directory** - Each chat can have its own working directory
13
+ - 🌐 **WebSocket connection** - No public IP or port forwarding required
14
+
15
+ ## Prerequisites
16
+
17
+ - Node.js 18+
18
+ - [Claude Code CLI](https://claude.ai/code) installed and configured
19
+ - A Feishu/Lark self-built application (see setup guide below)
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install -g cc-channel
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ### 1. Create a Feishu Application
30
+
31
+ 1. Go to [Feishu Open Platform](https://open.feishu.cn/app) (or [Lark Developer](https://open.larksuite.com/app) for international)
32
+ 2. Create a new "Self-built Application" (自建应用)
33
+ 3. Note down your **App ID** and **App Secret**
34
+ 4. In the app settings:
35
+ - Enable "Bot" capability (机器人能力)
36
+ - Add message event subscription: `im.message.receive_v1`
37
+ - Configure event subscription method as **WebSocket** (事件订阅方式: 使用长连接接收事件)
38
+
39
+ ### 2. Initialize cc-channel
40
+
41
+ ```bash
42
+ cc-channel init
43
+ ```
44
+
45
+ This will guide you through:
46
+ - Entering your Feishu App ID and Secret
47
+ - Setting the default working directory
48
+ - Testing the connection
49
+ - Starting the background service
50
+
51
+ ### 3. Use in Feishu
52
+
53
+ 1. Add your bot to a group chat, or
54
+ 2. Start a direct message with the bot
55
+
56
+ Send any message to trigger Claude Code!
57
+
58
+ ## Usage
59
+
60
+ ### Commands
61
+
62
+ ```bash
63
+ # Initialize configuration
64
+ cc-channel init
65
+
66
+ # Start background service
67
+ cc-channel start
68
+
69
+ # Start in foreground (for debugging)
70
+ cc-channel start --foreground
71
+
72
+ # Stop background service
73
+ cc-channel stop
74
+
75
+ # Show status
76
+ cc-channel status
77
+
78
+ # View logs
79
+ cc-channel logs
80
+ cc-channel logs --follow
81
+
82
+ # Configuration
83
+ cc-channel config list
84
+ cc-channel config set claude.defaultWorkDir ~/projects
85
+ ```
86
+
87
+ ### In-Chat Commands
88
+
89
+ When messaging the bot in Feishu:
90
+
91
+ | Command | Description |
92
+ |---------|-------------|
93
+ | (any message) | Execute with Claude Code |
94
+ | `/cc help` | Show available commands |
95
+ | `/cc cd <path>` | Change working directory |
96
+ | `/cc pwd` | Show current directory |
97
+ | `/cc clear` | Clear conversation history |
98
+ | `/cc status` | Show session status |
99
+
100
+ ## Configuration
101
+
102
+ Configuration is stored in `~/.cc-channel/config.json`.
103
+
104
+ ### Example Configuration
105
+
106
+ ```json
107
+ {
108
+ "feishu": {
109
+ "appId": "cli_xxxx",
110
+ "appSecret": "xxxx",
111
+ "verificationToken": "",
112
+ "encryptKey": "",
113
+ "domain": "feishu"
114
+ },
115
+ "claude": {
116
+ "defaultWorkDir": "~",
117
+ "timeout": 300000
118
+ }
119
+ }
120
+ ```
121
+
122
+ ### Environment Variables
123
+
124
+ You can also configure via environment variables:
125
+
126
+ - `CC_CHANNEL_FEISHU_APP_ID`
127
+ - `CC_CHANNEL_FEISHU_APP_SECRET`
128
+ - `CC_CHANNEL_FEISHU_DOMAIN`
129
+ - `CC_CHANNEL_WORK_DIR`
130
+
131
+ ## How It Works
132
+
133
+ ```
134
+ ┌─────────────────┐ WebSocket ┌─────────────────┐
135
+ │ Feishu Bot │ ◄───────────────► │ cc-channel │
136
+ │ (Cloud) │ │ (Local) │
137
+ └─────────────────┘ └────────┬────────┘
138
+
139
+ │ spawn
140
+
141
+ ┌─────────────────┐
142
+ │ Claude Code │
143
+ │ CLI │
144
+ └─────────────────┘
145
+ ```
146
+
147
+ 1. You send a message to your Feishu bot
148
+ 2. Feishu pushes the event via WebSocket to cc-channel
149
+ 3. cc-channel spawns Claude Code CLI with your message
150
+ 4. The response is sent back to Feishu
151
+
152
+ ## Multi-turn Conversations
153
+
154
+ cc-channel maintains conversation history per chat:
155
+
156
+ - Each chat (direct message or group) has its own session
157
+ - Context is passed to Claude Code for follow-up questions
158
+ - Use `/cc clear` to start a fresh conversation
159
+
160
+ ## Security Considerations
161
+
162
+ - Only users who can message your Feishu bot can trigger Claude Code
163
+ - All execution happens locally on your machine
164
+ - Session data is stored in `~/.cc-channel/sessions/`
165
+
166
+ ## Troubleshooting
167
+
168
+ ### Claude CLI not found
169
+
170
+ ```bash
171
+ # Check if claude is in PATH
172
+ which claude
173
+
174
+ # If installed but not found, add to PATH
175
+ export PATH="$PATH:$(dirname $(which claude))"
176
+ ```
177
+
178
+ ### Connection issues
179
+
180
+ 1. Verify your App ID and Secret are correct
181
+ 2. Make sure WebSocket mode is enabled in Feishu app settings
182
+ 3. Check logs: `cc-channel logs`
183
+
184
+ ### Service not starting
185
+
186
+ ```bash
187
+ # Check service status
188
+ cc-channel status
189
+
190
+ # Try running in foreground to see errors
191
+ cc-channel start --foreground
192
+ ```
193
+
194
+ ## Development
195
+
196
+ ```bash
197
+ # Clone the repo
198
+ git clone https://github.com/L-x-C/cc-channel.git
199
+ cd cc-channel
200
+
201
+ # Install dependencies
202
+ npm install
203
+
204
+ # Build
205
+ npm run build
206
+
207
+ # Run locally
208
+ node dist/cli.js init
209
+ ```
210
+
211
+ ## License
212
+
213
+ MIT
@@ -0,0 +1,24 @@
1
+ import { Session } from "../session/store.js";
2
+ export interface ExecuteResult {
3
+ success: boolean;
4
+ output: string;
5
+ error?: string;
6
+ duration: number;
7
+ }
8
+ export interface ExecuteOptions {
9
+ workDir: string;
10
+ timeout: number;
11
+ }
12
+ /**
13
+ * Execute Claude Code CLI with the given prompt
14
+ */
15
+ export declare function executeClaude(prompt: string, options: ExecuteOptions): Promise<ExecuteResult>;
16
+ /**
17
+ * Build a prompt with conversation history for multi-turn context
18
+ */
19
+ export declare function buildPromptWithHistory(session: Session, currentPrompt: string): string;
20
+ /**
21
+ * Check if Claude CLI is available
22
+ */
23
+ export declare function checkClaudeAvailable(): Promise<boolean>;
24
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/claude/executor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAE9C,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CAuExB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAmBtF;AAED;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAmB7D"}
@@ -0,0 +1,109 @@
1
+ import { spawn } from "child_process";
2
+ /**
3
+ * Execute Claude Code CLI with the given prompt
4
+ */
5
+ export async function executeClaude(prompt, options) {
6
+ const startTime = Date.now();
7
+ return new Promise((resolve) => {
8
+ let output = "";
9
+ let errorOutput = "";
10
+ // Create a clean environment, removing CLAUDECODE to allow nested execution
11
+ const cleanEnv = { ...process.env };
12
+ delete cleanEnv.CLAUDECODE;
13
+ const child = spawn("claude", ["--print", prompt], {
14
+ cwd: options.workDir,
15
+ env: {
16
+ ...cleanEnv,
17
+ // Ensure non-interactive mode
18
+ CI: "true",
19
+ TERM: "dumb",
20
+ },
21
+ stdio: ["ignore", "pipe", "pipe"],
22
+ });
23
+ // Set timeout
24
+ const timeoutId = setTimeout(() => {
25
+ child.kill("SIGTERM");
26
+ resolve({
27
+ success: false,
28
+ output: "",
29
+ error: `Execution timed out after ${options.timeout}ms`,
30
+ duration: Date.now() - startTime,
31
+ });
32
+ }, options.timeout);
33
+ child.stdout?.on("data", (data) => {
34
+ output += data.toString();
35
+ });
36
+ child.stderr?.on("data", (data) => {
37
+ errorOutput += data.toString();
38
+ });
39
+ child.on("close", (code) => {
40
+ clearTimeout(timeoutId);
41
+ const duration = Date.now() - startTime;
42
+ if (code === 0) {
43
+ resolve({
44
+ success: true,
45
+ output: output.trim(),
46
+ duration,
47
+ });
48
+ }
49
+ else {
50
+ resolve({
51
+ success: false,
52
+ output: output.trim(),
53
+ error: errorOutput.trim() || `Process exited with code ${code}`,
54
+ duration,
55
+ });
56
+ }
57
+ });
58
+ child.on("error", (err) => {
59
+ clearTimeout(timeoutId);
60
+ resolve({
61
+ success: false,
62
+ output: "",
63
+ error: err.message,
64
+ duration: Date.now() - startTime,
65
+ });
66
+ });
67
+ });
68
+ }
69
+ /**
70
+ * Build a prompt with conversation history for multi-turn context
71
+ */
72
+ export function buildPromptWithHistory(session, currentPrompt) {
73
+ if (session.messages.length === 0) {
74
+ return currentPrompt;
75
+ }
76
+ // Build context from recent messages (limit to prevent context overflow)
77
+ const recentMessages = session.messages.slice(-20); // Last 20 messages
78
+ const historyContext = recentMessages
79
+ .map((msg) => {
80
+ const role = msg.role === "user" ? "User" : "Assistant";
81
+ return `${role}: ${msg.content}`;
82
+ })
83
+ .join("\n\n");
84
+ return `Previous conversation context:
85
+ ${historyContext}
86
+
87
+ Current request: ${currentPrompt}`;
88
+ }
89
+ /**
90
+ * Check if Claude CLI is available
91
+ */
92
+ export async function checkClaudeAvailable() {
93
+ // Create a clean environment, removing CLAUDECODE
94
+ const cleanEnv = { ...process.env };
95
+ delete cleanEnv.CLAUDECODE;
96
+ return new Promise((resolve) => {
97
+ const child = spawn("claude", ["--version"], {
98
+ env: cleanEnv,
99
+ stdio: "ignore",
100
+ });
101
+ child.on("close", (code) => {
102
+ resolve(code === 0);
103
+ });
104
+ child.on("error", () => {
105
+ resolve(false);
106
+ });
107
+ });
108
+ }
109
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/claude/executor.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { readFileSync } from "fs";
4
+ import { fileURLToPath } from "url";
5
+ import { dirname, join } from "path";
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = dirname(__filename);
8
+ // Read version from package.json
9
+ const packageJson = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
10
+ const program = new Command();
11
+ program
12
+ .name("cc-channel")
13
+ .description("Feishu/Lark channel for Claude Code - trigger Claude Code from Feishu messages")
14
+ .version(packageJson.version);
15
+ program
16
+ .command("init")
17
+ .description("Initialize and configure cc-channel")
18
+ .action(async () => {
19
+ const { initCommand } = await import("./commands/init.js");
20
+ await initCommand();
21
+ });
22
+ program
23
+ .command("start")
24
+ .description("Start the cc-channel service")
25
+ .option("-f, --foreground", "Run in foreground instead of background daemon")
26
+ .action(async (options) => {
27
+ const { startCommand } = await import("./commands/start.js");
28
+ await startCommand(options.foreground);
29
+ });
30
+ program
31
+ .command("stop")
32
+ .description("Stop the background daemon")
33
+ .action(async () => {
34
+ const { stopCommand } = await import("./commands/stop.js");
35
+ await stopCommand();
36
+ });
37
+ program
38
+ .command("status")
39
+ .description("Show status and configuration")
40
+ .action(async () => {
41
+ const { statusCommand } = await import("./commands/status.js");
42
+ await statusCommand();
43
+ });
44
+ program
45
+ .command("config")
46
+ .description("View or modify configuration")
47
+ .argument("<action>", "list, set, or path")
48
+ .argument("[key]", "Config key (for set)")
49
+ .argument("[value]", "Config value (for set)")
50
+ .action(async (action, key, value) => {
51
+ const { configCommand } = await import("./commands/config-cmd.js");
52
+ await configCommand(action, key, value);
53
+ });
54
+ program
55
+ .command("logs")
56
+ .description("Show recent logs")
57
+ .option("-f, --follow", "Follow log output")
58
+ .action(async (options) => {
59
+ const { logsCommand } = await import("./commands/logs.js");
60
+ await logsCommand(options);
61
+ });
62
+ program.parse();
63
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function configCommand(action: string, key?: string, value?: string): Promise<void>;
2
+ //# sourceMappingURL=config-cmd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-cmd.d.ts","sourceRoot":"","sources":["../../src/commands/config-cmd.ts"],"names":[],"mappings":"AAUA,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA+B/F"}
@@ -0,0 +1,105 @@
1
+ import chalk from "chalk";
2
+ import { getFeishuConfig, setFeishuConfig, getClaudeConfig, setClaudeConfig, getConfigPath, } from "../config.js";
3
+ export async function configCommand(action, key, value) {
4
+ switch (action) {
5
+ case "list":
6
+ case "show":
7
+ showConfig();
8
+ break;
9
+ case "set":
10
+ if (!key || !value) {
11
+ console.log(chalk.red("Usage: cc-channel config set <key> <value>"));
12
+ console.log();
13
+ console.log("Available keys:");
14
+ console.log(" feishu.appId");
15
+ console.log(" feishu.appSecret");
16
+ console.log(" feishu.verificationToken");
17
+ console.log(" feishu.encryptKey");
18
+ console.log(" feishu.domain");
19
+ console.log(" claude.defaultWorkDir");
20
+ return;
21
+ }
22
+ await setConfigValue(key, value);
23
+ break;
24
+ case "path":
25
+ console.log(getConfigPath());
26
+ break;
27
+ default:
28
+ console.log(chalk.red(`Unknown action: ${action}`));
29
+ console.log("Usage: cc-channel config <list|set|path>");
30
+ }
31
+ }
32
+ function showConfig() {
33
+ console.log(chalk.cyan("\n⚙️ Configuration\n"));
34
+ console.log(`Config file: ${getConfigPath()}`);
35
+ console.log();
36
+ const feishu = getFeishuConfig();
37
+ const claude = getClaudeConfig();
38
+ console.log(chalk.bold("Feishu:"));
39
+ if (feishu) {
40
+ console.log(` appId: ${feishu.appId}`);
41
+ console.log(` appSecret: ${feishu.appSecret ? "********" : "(not set)"}`);
42
+ console.log(` domain: ${feishu.domain}`);
43
+ console.log(` verificationToken: ${feishu.verificationToken ? "********" : "(not set)"}`);
44
+ console.log(` encryptKey: ${feishu.encryptKey ? "********" : "(not set)"}`);
45
+ }
46
+ else {
47
+ console.log(chalk.yellow(" Not configured"));
48
+ }
49
+ console.log();
50
+ console.log(chalk.bold("Claude:"));
51
+ console.log(` defaultWorkDir: ${claude.defaultWorkDir}`);
52
+ console.log();
53
+ }
54
+ async function setConfigValue(key, value) {
55
+ const [section, subkey] = key.split(".");
56
+ if (section === "feishu") {
57
+ const existing = getFeishuConfig();
58
+ if (!existing) {
59
+ console.log(chalk.red("Feishu not configured. Run 'cc-channel init' first."));
60
+ return;
61
+ }
62
+ const feishu = { ...existing };
63
+ switch (subkey) {
64
+ case "appId":
65
+ feishu.appId = value;
66
+ break;
67
+ case "appSecret":
68
+ feishu.appSecret = value;
69
+ break;
70
+ case "verificationToken":
71
+ feishu.verificationToken = value || undefined;
72
+ break;
73
+ case "encryptKey":
74
+ feishu.encryptKey = value || undefined;
75
+ break;
76
+ case "domain":
77
+ if (value !== "feishu" && value !== "lark") {
78
+ console.log(chalk.red("Domain must be 'feishu' or 'lark'"));
79
+ return;
80
+ }
81
+ feishu.domain = value;
82
+ break;
83
+ default:
84
+ console.log(chalk.red(`Unknown key: feishu.${subkey}`));
85
+ return;
86
+ }
87
+ setFeishuConfig(feishu);
88
+ console.log(chalk.green(`✓ Set ${key}`));
89
+ }
90
+ else if (section === "claude") {
91
+ switch (subkey) {
92
+ case "defaultWorkDir":
93
+ setClaudeConfig({ defaultWorkDir: value });
94
+ break;
95
+ default:
96
+ console.log(chalk.red(`Unknown key: claude.${subkey}`));
97
+ return;
98
+ }
99
+ console.log(chalk.green(`✓ Set ${key}`));
100
+ }
101
+ else {
102
+ console.log(chalk.red(`Unknown section: ${section}`));
103
+ }
104
+ }
105
+ //# sourceMappingURL=config-cmd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-cmd.js","sourceRoot":"","sources":["../../src/commands/config-cmd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function initCommand(): Promise<void>;
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAmDA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAiJjD"}