@ibbybuilds/discli 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 +250 -0
- package/dist/cli.js +867 -0
- package/dist/cli.js.map +1 -0
- package/package.json +46 -0
- package/skills/SKILL.md +76 -0
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/utils/config.ts","../src/utils/api.ts","../src/commands/init.ts","../src/utils/output.ts","../src/commands/server.ts","../src/utils/resolve.ts","../src/commands/channel.ts","../src/commands/role.ts","../src/commands/member.ts","../src/commands/permission.ts"],"sourcesContent":["import { Command } from 'commander';\r\nimport { registerInit } from './commands/init.js';\r\nimport { registerServer } from './commands/server.js';\r\nimport { registerChannel } from './commands/channel.js';\r\nimport { registerRole } from './commands/role.js';\r\nimport { registerMember } from './commands/member.js';\r\nimport { registerPermission } from './commands/permission.js';\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name('discli')\r\n .description('discli — Discord server management CLI')\r\n .version('0.1.0')\r\n .option('--format <fmt>', 'Output format: json, yaml, table, auto (auto = yaml when piped, table in terminal)', 'auto')\r\n .option('--server <id>', 'Server ID override');\r\n\r\nregisterInit(program);\r\nregisterServer(program);\r\nregisterChannel(program);\r\nregisterRole(program);\r\nregisterMember(program);\r\nregisterPermission(program);\r\n\r\nprogram.parse();\r\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\r\nimport { homedir } from 'os';\r\nimport { join } from 'path';\r\n\r\nconst CONFIG_DIR = join(homedir(), '.discli');\r\nconst CONFIG_FILE = join(CONFIG_DIR, 'config.json');\r\nconst ENV_FILE = join(CONFIG_DIR, '.env');\r\n\r\ninterface DctlConfig {\r\n default_server_id?: string;\r\n default_server_name?: string;\r\n}\r\n\r\nfunction ensureConfigDir(): void {\r\n if (!existsSync(CONFIG_DIR)) {\r\n mkdirSync(CONFIG_DIR, { recursive: true });\r\n }\r\n}\r\n\r\nexport function loadConfig(): DctlConfig {\r\n if (!existsSync(CONFIG_FILE)) return {};\r\n try {\r\n return JSON.parse(readFileSync(CONFIG_FILE, 'utf-8'));\r\n } catch {\r\n return {};\r\n }\r\n}\r\n\r\nexport function saveConfig(data: DctlConfig): void {\r\n ensureConfigDir();\r\n writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2) + '\\n');\r\n}\r\n\r\nexport function loadToken(): string | null {\r\n if (!existsSync(ENV_FILE)) return null;\r\n const content = readFileSync(ENV_FILE, 'utf-8');\r\n const match = content.match(/^BOT_TOKEN=(.+)$/m);\r\n return match ? match[1].trim() : null;\r\n}\r\n\r\nexport function saveToken(token: string): void {\r\n ensureConfigDir();\r\n writeFileSync(ENV_FILE, `BOT_TOKEN=${token}\\n`);\r\n}\r\n\r\nexport function getDefaultServer(): string | null {\r\n return loadConfig().default_server_id ?? null;\r\n}\r\n\r\nexport function getDefaultServerName(): string | null {\r\n return loadConfig().default_server_name ?? null;\r\n}\r\n\r\nexport function setDefaultServer(id: string, name: string): void {\r\n const cfg = loadConfig();\r\n cfg.default_server_id = id;\r\n cfg.default_server_name = name;\r\n saveConfig(cfg);\r\n}\r\n\r\nexport function requireToken(): string {\r\n const token = loadToken();\r\n if (!token) {\r\n console.error('Error: Not configured. Run \"discli init\" first.');\r\n process.exit(1);\r\n }\r\n return token;\r\n}\r\n\r\nexport function requireServer(override?: string): string {\r\n const server = override || getDefaultServer();\r\n if (!server) {\r\n console.error('Error: No server selected. Run \"discli server select\" or use --server <id>.');\r\n process.exit(1);\r\n }\r\n return server;\r\n}\r\n","const BASE = 'https://discord.com/api/v10';\r\n\r\nexport const PERMISSION: Record<string, bigint> = {\r\n view_channel: 1n << 10n,\r\n send_messages: 1n << 11n,\r\n send_messages_in_threads: 1n << 38n,\r\n create_public_threads: 1n << 35n,\r\n create_private_threads: 1n << 36n,\r\n embed_links: 1n << 14n,\r\n attach_files: 1n << 15n,\r\n add_reactions: 1n << 6n,\r\n use_external_emojis: 1n << 18n,\r\n read_message_history: 1n << 16n,\r\n mention_everyone: 1n << 17n,\r\n manage_messages: 1n << 13n,\r\n manage_channels: 1n << 4n,\r\n manage_roles: 1n << 28n,\r\n connect: 1n << 20n,\r\n speak: 1n << 21n,\r\n mute_members: 1n << 22n,\r\n deafen_members: 1n << 23n,\r\n move_members: 1n << 24n,\r\n use_voice_activity: 1n << 25n,\r\n};\r\n\r\nexport const CHANNEL_TYPE: Record<string, number> = {\r\n text: 0,\r\n voice: 2,\r\n category: 4,\r\n announcement: 5,\r\n stage: 13,\r\n forum: 15,\r\n};\r\n\r\nexport const CHANNEL_TYPE_NAME: Record<number, string> = Object.fromEntries(\r\n Object.entries(CHANNEL_TYPE).map(([k, v]) => [v, k])\r\n);\r\n\r\nexport class DiscordAPI {\r\n private token: string;\r\n\r\n constructor(token: string) {\r\n this.token = token;\r\n }\r\n\r\n private async request(method: string, path: string, body?: unknown): Promise<unknown> {\r\n const headers: Record<string, string> = {\r\n Authorization: `Bot ${this.token}`,\r\n };\r\n if (body) {\r\n headers['Content-Type'] = 'application/json';\r\n }\r\n\r\n const res = await fetch(`${BASE}${path}`, {\r\n method,\r\n headers,\r\n body: body ? JSON.stringify(body) : undefined,\r\n });\r\n\r\n if (res.status === 429) {\r\n const data = (await res.json()) as { retry_after?: number };\r\n console.error(`Rate limited. Retry after ${data.retry_after ?? '?'}s.`);\r\n process.exit(1);\r\n }\r\n if (res.status === 403) {\r\n console.error('403 Forbidden — missing permissions.');\r\n process.exit(4);\r\n }\r\n if (res.status === 404) {\r\n console.error('404 Not found.');\r\n process.exit(3);\r\n }\r\n if (res.status >= 400) {\r\n const text = await res.text();\r\n console.error(`Discord API error ${res.status}: ${text.slice(0, 200)}`);\r\n process.exit(1);\r\n }\r\n\r\n if (res.status === 204) return null;\r\n return res.json();\r\n }\r\n\r\n // ── Guilds ──\r\n\r\n async listGuilds(): Promise<Guild[]> {\r\n return (await this.request('GET', '/users/@me/guilds')) as Guild[];\r\n }\r\n\r\n async getGuild(guildId: string): Promise<GuildFull> {\r\n return (await this.request('GET', `/guilds/${guildId}?with_counts=true`)) as GuildFull;\r\n }\r\n\r\n // ── Channels ──\r\n\r\n async listChannels(guildId: string): Promise<Channel[]> {\r\n return (await this.request('GET', `/guilds/${guildId}/channels`)) as Channel[];\r\n }\r\n\r\n async createChannel(\r\n guildId: string,\r\n opts: { name: string; type?: number; parent_id?: string; topic?: string }\r\n ): Promise<Channel> {\r\n return (await this.request('POST', `/guilds/${guildId}/channels`, opts)) as Channel;\r\n }\r\n\r\n async deleteChannel(channelId: string): Promise<void> {\r\n await this.request('DELETE', `/channels/${channelId}`);\r\n }\r\n\r\n async modifyChannel(channelId: string, data: Record<string, unknown>): Promise<Channel> {\r\n return (await this.request('PATCH', `/channels/${channelId}`, data)) as Channel;\r\n }\r\n\r\n async getChannel(channelId: string): Promise<Channel> {\r\n return (await this.request('GET', `/channels/${channelId}`)) as Channel;\r\n }\r\n\r\n async editChannelPermission(\r\n channelId: string,\r\n overwriteId: string,\r\n data: { allow: string; deny: string; type: number }\r\n ): Promise<void> {\r\n await this.request('PUT', `/channels/${channelId}/permissions/${overwriteId}`, data);\r\n }\r\n\r\n async deleteChannelPermission(channelId: string, overwriteId: string): Promise<void> {\r\n await this.request('DELETE', `/channels/${channelId}/permissions/${overwriteId}`);\r\n }\r\n\r\n // ── Roles ──\r\n\r\n async listRoles(guildId: string): Promise<Role[]> {\r\n return (await this.request('GET', `/guilds/${guildId}/roles`)) as Role[];\r\n }\r\n\r\n async createRole(guildId: string, data: Record<string, unknown>): Promise<Role> {\r\n return (await this.request('POST', `/guilds/${guildId}/roles`, data)) as Role;\r\n }\r\n\r\n async deleteRole(guildId: string, roleId: string): Promise<void> {\r\n await this.request('DELETE', `/guilds/${guildId}/roles/${roleId}`);\r\n }\r\n\r\n async addRoleToMember(guildId: string, userId: string, roleId: string): Promise<void> {\r\n await this.request('PUT', `/guilds/${guildId}/members/${userId}/roles/${roleId}`);\r\n }\r\n\r\n async removeRoleFromMember(guildId: string, userId: string, roleId: string): Promise<void> {\r\n await this.request('DELETE', `/guilds/${guildId}/members/${userId}/roles/${roleId}`);\r\n }\r\n\r\n // ── Members ──\r\n\r\n async listMembers(guildId: string, limit = 100): Promise<Member[]> {\r\n return (await this.request('GET', `/guilds/${guildId}/members?limit=${Math.min(limit, 1000)}`)) as Member[];\r\n }\r\n\r\n async getMember(guildId: string, userId: string): Promise<Member> {\r\n return (await this.request('GET', `/guilds/${guildId}/members/${userId}`)) as Member;\r\n }\r\n\r\n async kickMember(guildId: string, userId: string): Promise<void> {\r\n await this.request('DELETE', `/guilds/${guildId}/members/${userId}`);\r\n }\r\n\r\n async banMember(guildId: string, userId: string): Promise<void> {\r\n await this.request('PUT', `/guilds/${guildId}/bans/${userId}`);\r\n }\r\n\r\n async modifyMember(guildId: string, userId: string, data: Record<string, unknown>): Promise<Member> {\r\n return (await this.request('PATCH', `/guilds/${guildId}/members/${userId}`, data)) as Member;\r\n }\r\n}\r\n\r\n// ── Types ──\r\n\r\nexport interface Guild {\r\n id: string;\r\n name: string;\r\n icon: string | null;\r\n owner: boolean;\r\n permissions: string;\r\n}\r\n\r\nexport interface GuildFull extends Guild {\r\n approximate_member_count?: number;\r\n approximate_presence_count?: number;\r\n description: string | null;\r\n premium_tier: number;\r\n premium_subscription_count: number;\r\n}\r\n\r\nexport interface PermissionOverwrite {\r\n id: string;\r\n type: number; // 0 = role, 1 = member\r\n allow: string;\r\n deny: string;\r\n}\r\n\r\nexport interface Channel {\r\n id: string;\r\n name: string;\r\n type: number;\r\n position: number;\r\n parent_id: string | null;\r\n topic?: string | null;\r\n permission_overwrites?: PermissionOverwrite[];\r\n}\r\n\r\nexport interface Role {\r\n id: string;\r\n name: string;\r\n color: number;\r\n position: number;\r\n permissions: string;\r\n managed: boolean;\r\n mentionable: boolean;\r\n}\r\n\r\nexport interface Member {\r\n user?: {\r\n id: string;\r\n username: string;\r\n global_name: string | null;\r\n };\r\n nick: string | null;\r\n roles: string[];\r\n joined_at: string;\r\n}\r\n","import { Command } from 'commander';\r\nimport { saveToken, setDefaultServer, loadToken } from '../utils/config.js';\r\nimport { DiscordAPI } from '../utils/api.js';\r\nimport { readFileSync } from 'fs';\r\n\r\nexport function registerInit(program: Command): void {\r\n program\r\n .command('init')\r\n .description('Set up discli with your bot token and default server')\r\n .option('--token <token>', 'Bot token (or reads from stdin)')\r\n .action(async (opts) => {\r\n let token = opts.token;\r\n\r\n if (!token) {\r\n // Try reading from stdin if piped\r\n if (!process.stdin.isTTY) {\r\n token = readFileSync(0, 'utf-8').trim();\r\n }\r\n }\r\n\r\n if (!token) {\r\n // Check if already configured\r\n const existing = loadToken();\r\n if (existing) {\r\n console.log('Already configured. Use --token to update.');\r\n token = existing;\r\n } else {\r\n console.error('Usage: discli init --token <your-bot-token>');\r\n console.error(' Get your token from https://discord.com/developers/applications');\r\n process.exit(2);\r\n }\r\n }\r\n\r\n // Validate token\r\n const api = new DiscordAPI(token);\r\n let guilds;\r\n try {\r\n guilds = await api.listGuilds();\r\n } catch {\r\n console.error('Invalid token or cannot connect to Discord.');\r\n process.exit(1);\r\n }\r\n\r\n saveToken(token);\r\n console.log(`Token saved to ~/.discli/.env`);\r\n\r\n if (guilds.length === 0) {\r\n console.log('Bot is not in any servers yet. Add it to a server first.');\r\n return;\r\n }\r\n\r\n console.log('\\nServers:');\r\n guilds.forEach((g, i) => {\r\n console.log(` ${i + 1}. ${g.name} (${g.id})`);\r\n });\r\n\r\n // Auto-select if only one server\r\n if (guilds.length === 1) {\r\n setDefaultServer(guilds[0].id, guilds[0].name);\r\n console.log(`\\nDefault server: ${guilds[0].name}`);\r\n } else {\r\n console.log(`\\nSet default with: discli server select <id>`);\r\n }\r\n\r\n console.log('\\nReady! Try: discli server info');\r\n });\r\n}\r\n","import { stringify as yamlStringify } from 'yaml';\r\n\r\nexport function resolveFormat(explicit: string): string {\r\n if (explicit !== 'auto') return explicit;\r\n return process.stdout.isTTY ? 'table' : 'yaml';\r\n}\r\n\r\nexport function printResult(data: unknown, format: string): void {\r\n const fmt = resolveFormat(format);\r\n\r\n if (fmt === 'json') {\r\n console.log(JSON.stringify(data, null, 2));\r\n return;\r\n }\r\n\r\n if (fmt === 'yaml') {\r\n console.log(yamlStringify(data, { indent: 2 }).trimEnd());\r\n return;\r\n }\r\n\r\n if (Array.isArray(data)) {\r\n if (data.length === 0) {\r\n console.log(' (none)');\r\n return;\r\n }\r\n if (typeof data[0] === 'object') {\r\n printTable(data as Record<string, unknown>[]);\r\n } else {\r\n data.forEach((item) => console.log(` ${item}`));\r\n }\r\n return;\r\n }\r\n\r\n if (typeof data === 'object' && data !== null) {\r\n const obj = data as Record<string, unknown>;\r\n const maxKey = Math.max(...Object.keys(obj).map((k) => k.length));\r\n for (const [k, v] of Object.entries(obj)) {\r\n console.log(` ${k.padEnd(maxKey)} ${v}`);\r\n }\r\n return;\r\n }\r\n\r\n console.log(String(data));\r\n}\r\n\r\nexport function printTable(rows: Record<string, unknown>[], columns?: string[]): void {\r\n if (rows.length === 0) {\r\n console.log(' (none)');\r\n return;\r\n }\r\n\r\n const cols = columns ?? Object.keys(rows[0]);\r\n const widths: Record<string, number> = {};\r\n for (const col of cols) {\r\n widths[col] = col.length;\r\n }\r\n for (const row of rows) {\r\n for (const col of cols) {\r\n widths[col] = Math.max(widths[col], String(row[col] ?? '').length);\r\n }\r\n }\r\n\r\n const header = cols.map((c) => c.toUpperCase().padEnd(widths[c])).join(' ');\r\n const sep = cols.map((c) => '─'.repeat(widths[c])).join(' ');\r\n console.log(` ${header}`);\r\n console.log(` ${sep}`);\r\n\r\n for (const row of rows) {\r\n const line = cols.map((c) => String(row[c] ?? '').padEnd(widths[c])).join(' ');\r\n console.log(` ${line}`);\r\n }\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI } from '../utils/api.js';\r\nimport { requireToken, requireServer, setDefaultServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\n\r\nexport function registerServer(program: Command): void {\r\n const server = program\r\n .command('server')\r\n .description('Manage and inspect servers');\r\n\r\n server\r\n .command('list')\r\n .description('List all servers the bot is in')\r\n .action(async () => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guilds = await api.listGuilds();\r\n\r\n if (fmt !== 'table') {\r\n printResult(guilds, fmt);\r\n return;\r\n }\r\n\r\n const rows = guilds.map((g) => ({\r\n id: g.id,\r\n name: g.name,\r\n owner: g.owner ? 'yes' : 'no',\r\n }));\r\n console.log('\\nServers');\r\n console.log('───────');\r\n printResult(rows, fmt);\r\n });\r\n\r\n server\r\n .command('select')\r\n .description('Set the default server')\r\n .argument('<id>', 'Server ID')\r\n .action(async (id: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guild = await api.getGuild(id);\r\n setDefaultServer(guild.id, guild.name);\r\n console.log(`Default server set to: ${guild.name} (${guild.id})`);\r\n });\r\n\r\n server\r\n .command('info')\r\n .description('Show server details')\r\n .action(async () => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const guild = await api.getGuild(guildId);\r\n\r\n if (fmt !== 'table') {\r\n printResult(guild, fmt);\r\n return;\r\n }\r\n\r\n const info = {\r\n name: guild.name,\r\n id: guild.id,\r\n description: guild.description || '(none)',\r\n members: guild.approximate_member_count ?? '?',\r\n online: guild.approximate_presence_count ?? '?',\r\n boosts: guild.premium_subscription_count,\r\n boost_tier: guild.premium_tier,\r\n };\r\n\r\n console.log(`\\n${guild.name}`);\r\n console.log('─'.repeat(guild.name.length));\r\n printResult(info, fmt);\r\n });\r\n}\r\n","import { DiscordAPI, CHANNEL_TYPE_NAME } from './api.js';\r\nimport type { Channel, Role, Member } from './api.js';\r\n\r\nexport async function resolveChannel(\r\n api: DiscordAPI,\r\n guildId: string,\r\n name: string\r\n): Promise<Channel> {\r\n const channels = await api.listChannels(guildId);\r\n\r\n // Try ID match\r\n const byId = channels.find((c) => c.id === name);\r\n if (byId) return byId;\r\n\r\n // Strip # prefix\r\n const clean = name.replace(/^#/, '');\r\n\r\n const matches = channels.filter((c) => c.name.toLowerCase() === clean.toLowerCase());\r\n if (matches.length === 1) return matches[0];\r\n if (matches.length > 1) {\r\n const names = matches.map((m) => `#${m.name} (${CHANNEL_TYPE_NAME[m.type] ?? '?'})`).join(', ');\r\n console.error(`Ambiguous channel \"${clean}\". Matches: ${names}`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`Channel \"${name}\" not found.`);\r\n process.exit(3);\r\n}\r\n\r\nexport async function resolveCategory(\r\n api: DiscordAPI,\r\n guildId: string,\r\n name: string\r\n): Promise<Channel> {\r\n const channels = await api.listChannels(guildId);\r\n\r\n const byId = channels.find((c) => c.id === name && c.type === 4);\r\n if (byId) return byId;\r\n\r\n const matches = channels.filter(\r\n (c) => c.type === 4 && c.name.toLowerCase() === name.toLowerCase()\r\n );\r\n if (matches.length === 1) return matches[0];\r\n if (matches.length > 1) {\r\n console.error(`Ambiguous category \"${name}\".`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`Category \"${name}\" not found.`);\r\n process.exit(3);\r\n}\r\n\r\nexport async function resolveRole(\r\n api: DiscordAPI,\r\n guildId: string,\r\n name: string\r\n): Promise<Role> {\r\n const roles = await api.listRoles(guildId);\r\n\r\n const byId = roles.find((r) => r.id === name);\r\n if (byId) return byId;\r\n\r\n const clean = name.replace(/^@/, '');\r\n const matches = roles.filter((r) => r.name.toLowerCase() === clean.toLowerCase());\r\n if (matches.length === 1) return matches[0];\r\n if (matches.length > 1) {\r\n const names = matches.map((m) => `@${m.name}`).join(', ');\r\n console.error(`Ambiguous role \"${clean}\". Matches: ${names}`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`Role \"${name}\" not found.`);\r\n process.exit(3);\r\n}\r\n\r\nexport async function resolveMember(\r\n api: DiscordAPI,\r\n guildId: string,\r\n name: string\r\n): Promise<Member> {\r\n // Try as ID\r\n if (/^\\d+$/.test(name)) {\r\n try {\r\n return await api.getMember(guildId, name);\r\n } catch {\r\n // fall through to search\r\n }\r\n }\r\n\r\n const members = await api.listMembers(guildId, 1000);\r\n const clean = name.replace(/^@/, '').toLowerCase();\r\n\r\n const matches = members.filter((m) => {\r\n const username = m.user?.username?.toLowerCase() ?? '';\r\n const globalName = m.user?.global_name?.toLowerCase() ?? '';\r\n const nick = m.nick?.toLowerCase() ?? '';\r\n return username === clean || globalName === clean || nick === clean;\r\n });\r\n\r\n if (matches.length === 1) return matches[0];\r\n if (matches.length > 1) {\r\n const names = matches.map((m) => m.user?.username).join(', ');\r\n console.error(`Ambiguous user \"${name}\". Matches: ${names}`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`Member \"${name}\" not found.`);\r\n process.exit(3);\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI, CHANNEL_TYPE, CHANNEL_TYPE_NAME } from '../utils/api.js';\r\nimport { requireToken, requireServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\nimport { resolveChannel, resolveCategory } from '../utils/resolve.js';\r\n\r\nexport function registerChannel(program: Command): void {\r\n const channel = program\r\n .command('channel')\r\n .description('Manage server channels');\r\n\r\n channel\r\n .command('list')\r\n .description('List all channels grouped by category')\r\n .option('-n <count>', 'Limit number of channels shown', parseInt)\r\n .action(async (opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n let channels = await api.listChannels(guildId);\r\n if (opts.n) channels = channels.slice(0, opts.n);\r\n\r\n if (fmt !== 'table') {\r\n printResult(channels, fmt);\r\n return;\r\n }\r\n\r\n // Group by category\r\n const categories = channels\r\n .filter((c) => c.type === 4)\r\n .sort((a, b) => a.position - b.position);\r\n const uncategorized = channels.filter(\r\n (c) => c.type !== 4 && !c.parent_id\r\n );\r\n\r\n if (uncategorized.length > 0) {\r\n console.log('\\n (no category)');\r\n for (const ch of uncategorized.sort((a, b) => a.position - b.position)) {\r\n const type = CHANNEL_TYPE_NAME[ch.type] ?? '?';\r\n console.log(` ${type === 'text' ? '#' : '🔊'} ${ch.name}`);\r\n }\r\n }\r\n\r\n for (const cat of categories) {\r\n console.log(`\\n ${cat.name.toUpperCase()}`);\r\n const children = channels\r\n .filter((c) => c.parent_id === cat.id && c.type !== 4)\r\n .sort((a, b) => a.position - b.position);\r\n for (const ch of children) {\r\n const type = CHANNEL_TYPE_NAME[ch.type] ?? '?';\r\n const prefix = type === 'voice' || type === 'stage' ? '🔊' : '#';\r\n const topic = ch.topic ? ` — ${ch.topic}` : '';\r\n console.log(` ${prefix} ${ch.name}${topic}`);\r\n }\r\n }\r\n console.log();\r\n });\r\n\r\n channel\r\n .command('create')\r\n .description('Create a new channel')\r\n .argument('<name>', 'Channel name')\r\n .option('--type <type>', 'Channel type: text, voice, category, announcement, stage, forum', 'text')\r\n .option('--category <name>', 'Parent category name or ID')\r\n .option('--topic <topic>', 'Channel topic')\r\n .option('--dry-run', 'Show what would be created without creating it')\r\n .action(async (name: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n\r\n const channelType = CHANNEL_TYPE[opts.type];\r\n if (channelType === undefined) {\r\n console.error(`Unknown channel type: ${opts.type}. Use: ${Object.keys(CHANNEL_TYPE).join(', ')}`);\r\n process.exit(2);\r\n }\r\n\r\n let parentId: string | undefined;\r\n if (opts.category) {\r\n const cat = await resolveCategory(api, guildId, opts.category);\r\n parentId = cat.id;\r\n }\r\n\r\n if (opts.dryRun) {\r\n const result = { action: 'create_channel', name, type: opts.type, category: opts.category ?? null, topic: opts.topic ?? null };\r\n printResult(result, fmt);\r\n return;\r\n }\r\n\r\n const ch = await api.createChannel(guildId, {\r\n name,\r\n type: channelType,\r\n parent_id: parentId,\r\n topic: opts.topic,\r\n });\r\n\r\n if (fmt !== 'table') {\r\n printResult(ch, fmt);\r\n } else {\r\n console.log(`Created #${ch.name} (${CHANNEL_TYPE_NAME[ch.type] ?? '?'}) — ${ch.id}`);\r\n }\r\n });\r\n\r\n channel\r\n .command('delete')\r\n .description('Delete a channel')\r\n .argument('<name>', 'Channel name or ID')\r\n .option('--confirm', 'Required to actually delete')\r\n .action(async (name: string, opts) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, name);\r\n\r\n if (!opts.confirm) {\r\n console.error(`This will delete #${ch.name} (${ch.id}). Add --confirm to proceed.`);\r\n process.exit(2);\r\n }\r\n\r\n await api.deleteChannel(ch.id);\r\n console.log(`Deleted #${ch.name}`);\r\n });\r\n\r\n channel\r\n .command('rename')\r\n .description('Rename a channel')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<new-name>', 'New channel name')\r\n .option('--dry-run', 'Show what would change')\r\n .action(async (channelName: string, newName: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n if (opts.dryRun) {\r\n printResult({ action: 'rename_channel', from: ch.name, to: newName, id: ch.id }, fmt);\r\n return;\r\n }\r\n\r\n await api.modifyChannel(ch.id, { name: newName });\r\n console.log(`Renamed #${ch.name} → #${newName}`);\r\n });\r\n\r\n channel\r\n .command('topic')\r\n .description('Set a channel topic')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<topic>', 'New topic text')\r\n .action(async (channelName: string, topic: string) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n const updated = await api.modifyChannel(ch.id, { topic });\r\n if (fmt !== 'table') {\r\n printResult(updated, fmt);\r\n } else {\r\n console.log(`Set topic for #${ch.name}: ${topic}`);\r\n }\r\n });\r\n\r\n channel\r\n .command('move')\r\n .description('Move a channel to a category')\r\n .argument('<channel>', 'Channel name or ID')\r\n .option('--category <name>', 'Target category name or ID')\r\n .option('--position <n>', 'Position within category', parseInt)\r\n .action(async (channelName: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n const update: Record<string, unknown> = {};\r\n if (opts.category) {\r\n const cat = await resolveCategory(api, guildId, opts.category);\r\n update.parent_id = cat.id;\r\n }\r\n if (opts.position !== undefined) {\r\n update.position = opts.position;\r\n }\r\n\r\n if (Object.keys(update).length === 0) {\r\n console.error('Specify --category and/or --position.');\r\n process.exit(2);\r\n }\r\n\r\n const updated = await api.modifyChannel(ch.id, update);\r\n if (fmt !== 'table') {\r\n printResult(updated, fmt);\r\n } else {\r\n console.log(`Moved #${ch.name}${opts.category ? ` → ${opts.category}` : ''}${opts.position !== undefined ? ` (position ${opts.position})` : ''}`);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI } from '../utils/api.js';\r\nimport { requireToken, requireServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\nimport { resolveRole, resolveMember } from '../utils/resolve.js';\r\n\r\nexport function registerRole(program: Command): void {\r\n const role = program\r\n .command('role')\r\n .description('Manage server roles');\r\n\r\n role\r\n .command('list')\r\n .description('List all roles')\r\n .option('-n <count>', 'Limit number of roles shown', parseInt)\r\n .action(async (opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const roles = await api.listRoles(guildId);\r\n\r\n const sorted = roles.sort((a, b) => b.position - a.position).slice(0, opts.n ?? roles.length);\r\n\r\n if (fmt !== 'table') {\r\n printResult(sorted, fmt);\r\n return;\r\n }\r\n\r\n const rows = sorted.map((r) => ({\r\n name: r.name,\r\n id: r.id,\r\n color: r.color ? `#${r.color.toString(16).padStart(6, '0')}` : '(none)',\r\n managed: r.managed ? 'bot' : '',\r\n position: r.position,\r\n }));\r\n\r\n console.log('\\nRoles');\r\n console.log('─────');\r\n printResult(rows, fmt);\r\n });\r\n\r\n role\r\n .command('create')\r\n .description('Create a new role')\r\n .argument('<name>', 'Role name')\r\n .option('--color <hex>', 'Color hex (e.g. #ff5733)')\r\n .option('--mentionable', 'Allow anyone to mention this role')\r\n .option('--dry-run', 'Show what would be created')\r\n .action(async (name: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n\r\n const data: Record<string, unknown> = { name };\r\n if (opts.color) {\r\n data.color = parseInt(opts.color.replace('#', ''), 16);\r\n }\r\n if (opts.mentionable) {\r\n data.mentionable = true;\r\n }\r\n\r\n if (opts.dryRun) {\r\n printResult({ action: 'create_role', ...data }, fmt);\r\n return;\r\n }\r\n\r\n const r = await api.createRole(guildId, data);\r\n if (fmt !== 'table') {\r\n printResult(r, fmt);\r\n } else {\r\n console.log(`Created role @${r.name} — ${r.id}`);\r\n }\r\n });\r\n\r\n role\r\n .command('delete')\r\n .description('Delete a role')\r\n .argument('<name>', 'Role name or ID')\r\n .option('--confirm', 'Required to actually delete')\r\n .action(async (name: string, opts) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const r = await resolveRole(api, guildId, name);\r\n\r\n if (!opts.confirm) {\r\n console.error(`This will delete @${r.name} (${r.id}). Add --confirm to proceed.`);\r\n process.exit(2);\r\n }\r\n\r\n await api.deleteRole(guildId, r.id);\r\n console.log(`Deleted role @${r.name}`);\r\n });\r\n\r\n role\r\n .command('assign')\r\n .description('Assign a role to a member')\r\n .argument('<role>', 'Role name or ID')\r\n .argument('<user>', 'Username or ID')\r\n .action(async (roleName: string, userName: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const r = await resolveRole(api, guildId, roleName);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n await api.addRoleToMember(guildId, m.user!.id, r.id);\r\n console.log(`Assigned @${r.name} to ${m.user!.username}`);\r\n });\r\n\r\n role\r\n .command('remove')\r\n .description('Remove a role from a member')\r\n .argument('<role>', 'Role name or ID')\r\n .argument('<user>', 'Username or ID')\r\n .action(async (roleName: string, userName: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const r = await resolveRole(api, guildId, roleName);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n await api.removeRoleFromMember(guildId, m.user!.id, r.id);\r\n console.log(`Removed @${r.name} from ${m.user!.username}`);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI } from '../utils/api.js';\r\nimport { requireToken, requireServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\nimport { resolveMember } from '../utils/resolve.js';\r\n\r\nexport function registerMember(program: Command): void {\r\n const member = program\r\n .command('member')\r\n .description('Manage server members');\r\n\r\n member\r\n .command('list')\r\n .description('List server members')\r\n .option('-n, --limit <n>', 'Max members to show', '100')\r\n .action(async (opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const members = await api.listMembers(guildId, parseInt(opts.limit));\r\n\r\n if (fmt !== 'table') {\r\n printResult(members, fmt);\r\n return;\r\n }\r\n\r\n const rows = members.map((m) => ({\r\n username: m.user?.username ?? '?',\r\n display: m.user?.global_name ?? m.nick ?? '',\r\n nick: m.nick ?? '',\r\n roles: m.roles.length,\r\n joined: m.joined_at?.slice(0, 10) ?? '?',\r\n }));\r\n\r\n console.log(`\\nMembers (${members.length})`);\r\n console.log('──────────');\r\n printResult(rows, fmt);\r\n });\r\n\r\n member\r\n .command('info')\r\n .description('Show member details')\r\n .argument('<user>', 'Username or ID')\r\n .action(async (userName: string) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n if (fmt !== 'table') {\r\n printResult(m, fmt);\r\n return;\r\n }\r\n\r\n const roles = await api.listRoles(guildId);\r\n const memberRoles = m.roles\r\n .map((rid) => roles.find((r) => r.id === rid)?.name ?? rid)\r\n .join(', ');\r\n\r\n const info = {\r\n username: m.user?.username ?? '?',\r\n display_name: m.user?.global_name ?? '(none)',\r\n nickname: m.nick ?? '(none)',\r\n id: m.user?.id ?? '?',\r\n roles: memberRoles || '(none)',\r\n joined: m.joined_at?.slice(0, 10) ?? '?',\r\n };\r\n\r\n console.log(`\\n${m.user?.username ?? 'Member'}`);\r\n console.log('─'.repeat((m.user?.username ?? 'Member').length));\r\n printResult(info, fmt);\r\n });\r\n\r\n member\r\n .command('kick')\r\n .description('Kick a member from the server')\r\n .argument('<user>', 'Username or ID')\r\n .option('--reason <text>', 'Reason for kick')\r\n .option('--confirm', 'Required to actually kick')\r\n .action(async (userName: string, opts) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n if (!opts.confirm) {\r\n console.error(`This will kick ${m.user!.username} (${m.user!.id}). Add --confirm to proceed.`);\r\n process.exit(2);\r\n }\r\n\r\n await api.kickMember(guildId, m.user!.id);\r\n console.log(`Kicked ${m.user!.username}${opts.reason ? ` — ${opts.reason}` : ''}`);\r\n });\r\n\r\n member\r\n .command('ban')\r\n .description('Ban a member from the server')\r\n .argument('<user>', 'Username or ID')\r\n .option('--reason <text>', 'Reason for ban')\r\n .option('--confirm', 'Required to actually ban')\r\n .action(async (userName: string, opts) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n if (!opts.confirm) {\r\n console.error(`This will BAN ${m.user!.username} (${m.user!.id}). Add --confirm to proceed.`);\r\n process.exit(2);\r\n }\r\n\r\n await api.banMember(guildId, m.user!.id);\r\n console.log(`Banned ${m.user!.username}${opts.reason ? ` — ${opts.reason}` : ''}`);\r\n });\r\n\r\n member\r\n .command('nick')\r\n .description('Change a member\\'s nickname')\r\n .argument('<user>', 'Username or ID')\r\n .argument('<nickname>', 'New nickname')\r\n .action(async (userName: string, nickname: string) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n await api.modifyMember(guildId, m.user!.id, { nick: nickname });\r\n if (fmt !== 'table') {\r\n printResult({ action: 'nick', user: m.user!.username, nick: nickname }, fmt);\r\n } else {\r\n console.log(`Set nickname for ${m.user!.username} → ${nickname}`);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI, PERMISSION } from '../utils/api.js';\r\nimport { requireToken, requireServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\nimport { resolveChannel, resolveRole } from '../utils/resolve.js';\r\n\r\nfunction parsePermissions(perms: string): bigint {\r\n let bits = 0n;\r\n for (const p of perms.split(',')) {\r\n const name = p.trim().toLowerCase();\r\n const val = PERMISSION[name];\r\n if (val === undefined) {\r\n console.error(`Unknown permission: ${name}`);\r\n console.error(`Available: ${Object.keys(PERMISSION).join(', ')}`);\r\n process.exit(2);\r\n }\r\n bits |= val;\r\n }\r\n return bits;\r\n}\r\n\r\nfunction describePermissions(bitfield: string): string[] {\r\n const bits = BigInt(bitfield);\r\n if (bits === 0n) return [];\r\n return Object.entries(PERMISSION)\r\n .filter(([, val]) => (bits & val) === val)\r\n .map(([name]) => name);\r\n}\r\n\r\nexport function registerPermission(program: Command): void {\r\n const perm = program\r\n .command('permission')\r\n .alias('perm')\r\n .description('Manage channel permissions');\r\n\r\n perm\r\n .command('view')\r\n .description('View permission overwrites for a channel')\r\n .argument('<channel>', 'Channel name or ID')\r\n .action(async (channelName: string) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n const full = await api.getChannel(ch.id);\r\n const overwrites = full.permission_overwrites ?? [];\r\n const roles = await api.listRoles(guildId);\r\n\r\n if (fmt !== 'table') {\r\n printResult(overwrites, fmt);\r\n return;\r\n }\r\n\r\n if (overwrites.length === 0) {\r\n console.log(`\\n#${ch.name}: no permission overwrites (inherits from category/server)`);\r\n return;\r\n }\r\n\r\n console.log(`\\n#${ch.name} — Permission Overwrites`);\r\n console.log('─'.repeat(40));\r\n\r\n for (const ow of overwrites) {\r\n const target = ow.type === 0\r\n ? roles.find((r) => r.id === ow.id)?.name ?? ow.id\r\n : `member:${ow.id}`;\r\n const allowed = describePermissions(ow.allow);\r\n const denied = describePermissions(ow.deny);\r\n\r\n console.log(`\\n @${target} (${ow.type === 0 ? 'role' : 'member'})`);\r\n if (allowed.length > 0) console.log(` ✅ allow: ${allowed.join(', ')}`);\r\n if (denied.length > 0) console.log(` ❌ deny: ${denied.join(', ')}`);\r\n if (allowed.length === 0 && denied.length === 0) console.log(` (neutral)`);\r\n }\r\n console.log();\r\n });\r\n\r\n perm\r\n .command('set')\r\n .description('Set permission overwrite for a role on a channel')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<role>', 'Role name or ID')\r\n .option('--allow <perms>', 'Comma-separated permissions to allow')\r\n .option('--deny <perms>', 'Comma-separated permissions to deny')\r\n .option('--dry-run', 'Show what would change')\r\n .action(async (channelName: string, roleName: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n const role = await resolveRole(api, guildId, roleName);\r\n\r\n if (!opts.allow && !opts.deny) {\r\n console.error('Specify --allow and/or --deny with comma-separated permissions.');\r\n console.error(`Available: ${Object.keys(PERMISSION).join(', ')}`);\r\n process.exit(2);\r\n }\r\n\r\n const allow = opts.allow ? parsePermissions(opts.allow) : 0n;\r\n const deny = opts.deny ? parsePermissions(opts.deny) : 0n;\r\n\r\n if (opts.dryRun) {\r\n printResult({\r\n action: 'set_permission',\r\n channel: ch.name,\r\n role: role.name,\r\n allow: opts.allow ?? '(none)',\r\n deny: opts.deny ?? '(none)',\r\n }, fmt);\r\n return;\r\n }\r\n\r\n await api.editChannelPermission(ch.id, role.id, {\r\n allow: allow.toString(),\r\n deny: deny.toString(),\r\n type: 0, // role\r\n });\r\n\r\n if (fmt !== 'table') {\r\n printResult({ channel: ch.name, role: role.name, allow: allow.toString(), deny: deny.toString() }, fmt);\r\n } else {\r\n console.log(`Set permissions on #${ch.name} for @${role.name}`);\r\n if (opts.allow) console.log(` ✅ allow: ${opts.allow}`);\r\n if (opts.deny) console.log(` ❌ deny: ${opts.deny}`);\r\n }\r\n });\r\n\r\n perm\r\n .command('lock')\r\n .description('Make a channel read-only for @everyone')\r\n .argument('<channel>', 'Channel name or ID')\r\n .option('--dry-run', 'Show what would change')\r\n .action(async (channelName: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n // @everyone role ID = guild ID\r\n const deny = PERMISSION.send_messages\r\n | PERMISSION.send_messages_in_threads\r\n | PERMISSION.create_public_threads;\r\n\r\n if (opts.dryRun) {\r\n printResult({ action: 'lock', channel: ch.name, deny_for: '@everyone' }, fmt);\r\n return;\r\n }\r\n\r\n await api.editChannelPermission(ch.id, guildId, {\r\n allow: '0',\r\n deny: deny.toString(),\r\n type: 0,\r\n });\r\n\r\n console.log(`Locked #${ch.name} — read-only for @everyone`);\r\n });\r\n\r\n perm\r\n .command('unlock')\r\n .description('Remove read-only restriction for @everyone')\r\n .argument('<channel>', 'Channel name or ID')\r\n .action(async (channelName: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n await api.deleteChannelPermission(ch.id, guildId);\r\n console.log(`Unlocked #${ch.name} — @everyone can send messages`);\r\n });\r\n\r\n perm\r\n .command('list')\r\n .description('List all available permission names')\r\n .action(() => {\r\n const fmt = resolveFormat(program.opts().format);\r\n if (fmt !== 'table') {\r\n const perms = Object.entries(PERMISSION).map(([name, val]) => ({ name, bit: val.toString() }));\r\n printResult(perms, fmt);\r\n } else {\r\n console.log('\\nAvailable Permissions');\r\n console.log('────────────────────');\r\n for (const name of Object.keys(PERMISSION)) {\r\n console.log(` ${name}`);\r\n }\r\n }\r\n });\r\n}\r\n"],"mappings":"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","names":["readFileSync","program","program","program","program","program","program"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ibbybuilds/discli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "discli — Discord server management CLI. Control your servers from the terminal. Built for humans and AI agents.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"discli": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"skills",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/ibbybuilds/discli"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup",
|
|
20
|
+
"dev": "tsup --watch",
|
|
21
|
+
"start": "node dist/cli.js",
|
|
22
|
+
"typecheck": "tsc --noEmit"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"discord",
|
|
26
|
+
"cli",
|
|
27
|
+
"server",
|
|
28
|
+
"management",
|
|
29
|
+
"bot",
|
|
30
|
+
"agent"
|
|
31
|
+
],
|
|
32
|
+
"author": "ibbybuilds",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"commander": "^13.1.0",
|
|
36
|
+
"yaml": "^2.8.2"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18.0.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^22.0.0",
|
|
43
|
+
"tsup": "^8.5.1",
|
|
44
|
+
"typescript": "^5.9.3"
|
|
45
|
+
}
|
|
46
|
+
}
|
package/skills/SKILL.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: discli
|
|
3
|
+
description: |
|
|
4
|
+
Discord server management CLI. Use when you need to manage Discord servers —
|
|
5
|
+
create channels, assign roles, manage members, rename channels, set permissions.
|
|
6
|
+
Run discli --help or discli <command> --help to discover subcommands.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# discli — Discord Server Management CLI
|
|
10
|
+
|
|
11
|
+
Control Discord servers from the terminal. Works for both humans and AI agents.
|
|
12
|
+
|
|
13
|
+
## Agent Defaults
|
|
14
|
+
|
|
15
|
+
- Output is auto-detected: YAML when piped (agent), table in terminal (human).
|
|
16
|
+
- YAML is the preferred format for agents — 5x fewer tokens than JSON.
|
|
17
|
+
- Use `-n` to limit results and keep token usage low.
|
|
18
|
+
- Use `--format yaml` to force structured output, `--format json` if you need strict JSON.
|
|
19
|
+
- Use `--dry-run` on create/rename/permission commands to preview changes.
|
|
20
|
+
- Destructive commands (delete, kick, ban) require `--confirm` — they will NOT prompt.
|
|
21
|
+
- See SCHEMA.md for output shapes.
|
|
22
|
+
|
|
23
|
+
## Quick Reference
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
discli init --token <token> # First-time setup
|
|
27
|
+
discli server list # List servers
|
|
28
|
+
discli server select <id> # Set default server
|
|
29
|
+
discli server info # Server overview
|
|
30
|
+
|
|
31
|
+
discli channel list # List channels
|
|
32
|
+
discli channel create <name> # Create channel (--type, --category, --topic)
|
|
33
|
+
discli channel delete <name> # Delete channel (--confirm required)
|
|
34
|
+
discli channel rename <ch> <name> # Rename channel
|
|
35
|
+
discli channel topic <ch> <text> # Set topic
|
|
36
|
+
discli channel move <ch> # Move to category (--category, --position)
|
|
37
|
+
|
|
38
|
+
discli role list # List roles
|
|
39
|
+
discli role create <name> # Create role (--color, --mentionable)
|
|
40
|
+
discli role delete <name> # Delete role (--confirm required)
|
|
41
|
+
discli role assign <role> <user> # Give role to member
|
|
42
|
+
discli role remove <role> <user> # Remove role from member
|
|
43
|
+
|
|
44
|
+
discli member list # List members
|
|
45
|
+
discli member info <user> # Member details
|
|
46
|
+
discli member kick <user> # Kick (--confirm, --reason)
|
|
47
|
+
discli member ban <user> # Ban (--confirm, --reason)
|
|
48
|
+
discli member nick <user> <nick> # Change nickname
|
|
49
|
+
|
|
50
|
+
discli perm view <channel> # View channel permissions
|
|
51
|
+
discli perm set <ch> <role> # Set permissions (--allow, --deny)
|
|
52
|
+
discli perm lock <channel> # Make read-only for @everyone
|
|
53
|
+
discli perm unlock <channel> # Remove read-only
|
|
54
|
+
discli perm list # List available permission names
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Global Flags
|
|
58
|
+
|
|
59
|
+
- `--format <yaml|json|table|auto>` — output format (default: auto = yaml when piped, table in terminal)
|
|
60
|
+
- `--server <id>` — target a specific server instead of default
|
|
61
|
+
- `-n <count>` — limit results on list commands
|
|
62
|
+
|
|
63
|
+
## Exit Codes
|
|
64
|
+
|
|
65
|
+
- `0` — success
|
|
66
|
+
- `1` — general error
|
|
67
|
+
- `2` — usage error
|
|
68
|
+
- `3` — not found
|
|
69
|
+
- `4` — permission denied
|
|
70
|
+
|
|
71
|
+
## Notes
|
|
72
|
+
|
|
73
|
+
- Channel/role/member names are resolved case-insensitively.
|
|
74
|
+
- You can use IDs instead of names to avoid ambiguity.
|
|
75
|
+
- Rate limits: Discord allows ~5 requests/second. Channel renames have a 10-min cooldown per channel.
|
|
76
|
+
- Config stored in `~/.discli/` (token in `.env`, defaults in `config.json`).
|