Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- run: bun install
- run: bun run typecheck
- run: bun test
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules/
dist/
*.log
.DS_Store
151 changes: 151 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# ags

[![CI](https://github.com/moqa-studio/agents-cli/actions/workflows/ci.yml/badge.svg)](https://github.com/moqa-studio/agents-cli/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

One CLI to manage skills, commands, and rules across AI coding assistants.

Your skills are scattered across `~/.claude/skills/`, `.cursor/rules/`, `CLAUDE.md`, `.cursorrules` — different formats, different locations, no visibility into what's actually loaded. **ags** gives you a single command to scan, lint, measure, and manage all of it.

```
$ ags scan

NAME TYPE SCOPE AGENTS TOKENS
──────────────────────────────────────────────────────────
ags-manager skill local ◈ claude 2,847
code-review skill global ◈ claude ⌘ cursor 1,204
api-guidelines rule local ⌘ cursor 892
deploy-helper command global ◈ claude 456

4 items across 2 agents · 5,399 tokens
```

## Install

Requires [Bun](https://bun.sh) v1.0+.

```bash
bun install -g @moqa/ags
```

Or from source:

```bash
git clone https://github.com/moqa-studio/agents-cli.git
cd agents-cli && bun install && bun link
```

### Shell completions

```bash
# Bash
echo 'source /path/to/agents-cli/completions/ags.bash' >> ~/.bashrc

# Zsh
cp completions/_ags /usr/local/share/zsh/site-functions/
```

## Supported agents

| Agent | Flag | Status | What ags manages |
|-------|------|--------|------------------|
| Claude Code | `--agent claude` | Full | Skills, commands, subagents, memory, MCP config |
| Cursor | `--agent cursor` | Core | Skills, rules (`.cursorrules`, `.mdc`) |
| Codex | `--agent codex` | Basic | Skills |

Every command accepts `--agent <name>` to filter. Without it, ags operates across all agents at once.

## Commands

### `ags scan`

Discover everything across all agents.

```
ags scan # all items
ags scan --agent claude # Claude Code only
ags scan --type skill # skills only
ags scan --scope local # project-level only
ags scan --installed # which agents are installed
```

### `ags context`

See what's loaded into your agent's context — config files, skills, commands, memory, MCP servers.

```
ags context # all agents
ags context --agent claude # Claude Code only
```

### `ags lint`

Catch issues: missing frontmatter, short descriptions, oversized files, name conflicts, unsupported keys.

```
ags lint # everything
ags lint --agent cursor # Cursor rules only
```

### `ags skill-cost`

Token budget — per-skill cost ranked by size, context usage bar per agent, suggestions to free tokens.

```
ags skill-cost # full report
ags skill-cost --scope local # project skills only
```

### `ags grab <url>`

Install a skill from GitHub.

```
ags grab https://github.com/org/repo/blob/main/skills/foo/SKILL.md
ags grab <url> --to cursor # install for Cursor
ags grab <url> --dry-run # preview only
```

### `ags rm <name>`

Remove a skill, command, agent, or rule.

```
ags rm my-skill # all agents
ags rm my-skill --agent claude # Claude Code only
```

### `ags stats`

Usage dashboard (Claude Code only).

```
ags stats # last 30 days
ags stats --period 7d # last week
ags stats --period all-time # everything
```

All commands support `--json` for structured output and `--help` for usage details.

## Contributing

```bash
bun test # run tests
bun run typecheck # type-check
```

### Adding support for a new agent

The entire multi-agent system is driven by a single registry in `src/core/agents.ts`. To add an agent:

1. Add an entry to `AGENTS` in `src/core/agents.ts` — paths, binary name, config files, frontmatter keys
2. Add the name to `AgentName` in `src/types.ts`
3. Add a context limit in `getContextLimit()` in `src/core/agents.ts`
4. Add styling in `AGENT_STYLE` in `src/utils/output.ts` — icon and brand color
5. Update completions in `completions/`

All commands (scan, lint, skill-cost, grab, rm, context) work automatically from the registry. Agent-specific features (memory, stats, MCP) are opt-in in the relevant command file.

## License

MIT
51 changes: 51 additions & 0 deletions build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { $ } from "bun";
import { mkdirSync, existsSync, copyFileSync } from "fs";

const targets = [
{ name: "ags-darwin-arm64", target: "bun-darwin-arm64" },
{ name: "ags-darwin-x64", target: "bun-darwin-x64" },
{ name: "ags-linux-x64", target: "bun-linux-x64" },
] as const;

const outDir = "./dist";

async function build() {
if (!existsSync(outDir)) {
mkdirSync(outDir, { recursive: true });
}

// Build binaries
console.log("Building AGS binaries...\n");

for (const { name, target } of targets) {
const outPath = `${outDir}/${name}`;
console.log(` Building ${name}...`);

try {
await $`bun build --compile --target=${target} --outfile=${outPath} ./src/index.ts`.quiet();
console.log(` ✓ ${outPath}`);

const proc = Bun.spawn(["shasum", "-a", "256", outPath], {
stdout: "pipe",
});
await proc.exited;
const sha = (await new Response(proc.stdout).text()).trim();
await Bun.write(`${outPath}.sha256`, sha + "\n");
console.log(` ✓ ${outPath}.sha256`);
} catch (err) {
console.error(` ✗ Failed to build ${name}:`, err);
}

console.log();
}

// Copy completions to dist
mkdirSync(`${outDir}/completions`, { recursive: true });
copyFileSync("completions/_ags", `${outDir}/completions/_ags`);
copyFileSync("completions/ags.bash", `${outDir}/completions/ags.bash`);
console.log(" ✓ dist/completions/ (for Homebrew formula)\n");

console.log("Done!");
}

build();
Binary file added bun.lockb
Binary file not shown.
82 changes: 82 additions & 0 deletions completions/_ags
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#compdef ags

_ags() {
local -a commands
commands=(
'scan:Discover all skills, commands, agents, and rules'
'context:What'\''s loaded into your agent'\''s context'
'lint:Validate skill files for quality issues'
'skill-cost:How much context your skills consume'
'grab:Install skill from GitHub URL'
'rm:Remove a skill, command, agent, or rule'
'stats:Usage stats and activity dashboard'
)

local -a global_opts
global_opts=(
'--json[Output as JSON]'
'--help[Show help]'
'--version[Show version]'
)

if (( CURRENT == 2 )); then
_describe 'command' commands
return
fi

case "${words[2]}" in
scan)
_arguments \
'--agent[Filter by agent]:agent:(claude cursor codex)' \
'--type[Filter by type]:type:(skill command rule agent)' \
'--scope[Filter by scope]:scope:(local global all)' \
'--installed[Show which agents are installed]' \
'--json[Output as JSON]' \
'--help[Show help]'
;;
context)
_arguments \
'--agent[Filter by agent]:agent:(claude cursor codex)' \
'--json[Output as JSON]' \
'--help[Show help]'
;;
lint)
_arguments \
'--agent[Filter by agent]:agent:(claude cursor codex)' \
'--scope[Filter by scope]:scope:(local global all)' \
'--json[Output as JSON]' \
'--help[Show help]'
;;
skill-cost|budget)
_arguments \
'--scope[Filter by scope]:scope:(local global all)' \
'--json[Output as JSON]' \
'--help[Show help]'
;;
grab)
_arguments \
'--to[Target agent]:agent:(claude cursor codex)' \
'--dry-run[Preview without writing files]' \
'--json[Output as JSON]' \
'--help[Show help]'
;;
rm|remove)
_arguments \
'--agent[Filter by agent]:agent:(claude cursor codex)' \
'--dry-run[Preview without deleting files]' \
'--json[Output as JSON]' \
'--help[Show help]'
;;
stats)
_arguments \
'--period[Time range]:period:(7d 14d 30d 90d 6m 1y week month year all-time)' \
'--json[Output as JSON]' \
'--help[Show help]'
;;
*)
_arguments $global_opts
;;
esac
}

_ags "$@"
49 changes: 49 additions & 0 deletions completions/ags.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
_ags() {
local cur prev commands
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
commands="scan context lint skill-cost grab rm stats"

if [[ ${COMP_CWORD} -eq 1 ]]; then
COMPREPLY=( $(compgen -W "${commands}" -- "${cur}") )
return 0
fi

case "${prev}" in
--agent|--to)
COMPREPLY=( $(compgen -W "claude cursor codex" -- "${cur}") )
return 0
;;
--type)
COMPREPLY=( $(compgen -W "skill command rule agent" -- "${cur}") )
return 0
;;
--scope)
COMPREPLY=( $(compgen -W "local global all" -- "${cur}") )
return 0
;;
--period)
COMPREPLY=( $(compgen -W "7d 14d 30d 90d 6m 1y week month year all-time" -- "${cur}") )
return 0
;;
esac

local cmd="${COMP_WORDS[1]}"
local opts="--json --help"

case "${cmd}" in
scan) opts="--agent --type --scope --installed --json --help" ;;
context) opts="--agent --json --help" ;;
lint) opts="--agent --scope --json --help" ;;
skill-cost) opts="--scope --json --help" ;;
grab) opts="--to --dry-run --json --help" ;;
rm|remove) opts="--agent --dry-run --json --help" ;;
stats) opts="--period --json --help" ;;
esac

COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
}

complete -F _ags ags
18 changes: 18 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "@moqa/ags",
"version": "0.1.0",
"type": "module",
"bin": {
"ags": "./src/index.ts"
},
"scripts": {
"dev": "bun run src/index.ts",
"build": "bun run build.ts",
"test": "bun test",
"typecheck": "bun run --bun tsc --noEmit"
},
"license": "MIT",
"devDependencies": {
"bun-types": "^1.3.11"
}
}
Loading
Loading