Skip to content

Commit 5250b42

Browse files
authored
refactor(project): lift project commands to the top-level. (#2397)
* refactor(project): lift project command to the top level * fix(project): preserve lifted command and tui wiring * fix(project): preserve lifted tui behavior * test(project): update unit coverage for top-level commands * test(e2e): update project commands to top level * docs(project): document top-level project commands * test(tui): update root menu navigation expectations * fix(project): update payment manager guidance * fix(project): address top-level command review feedback * test(project): remove cwd regression coverage * refactor(project): wire leaf handlers through middleware config * revert(project): drop noisy add cwd fix
1 parent 326bc9e commit 5250b42

90 files changed

Lines changed: 475 additions & 799 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎CONTRIBUTING.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ npm i -g "./$TARBALL"
8585
- **The CLI looks frozen in a PowerShell window**: legacy conhost pauses all
8686
output while text is selected (the title bar shows `Select`). Press `Esc`.
8787
Windows Terminal does not do this.
88-
- **`project create` refuses a long path**: Windows caps paths at 260 characters
88+
- **`agentcore create` refuses a long path**: Windows caps paths at 260 characters
8989
unless `LongPathsEnabled` is set, and the CDK app's `node_modules` puts its
9090
deepest file 155 characters below the project root (aws-cdk-lib's own shipped
9191
fixtures), so the project root must be at most 104 characters. Create the

‎README.md‎

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,51 +29,51 @@ those details so you can create, deploy, and invoke agents from your terminal.
2929
Create a managed Harness project, deploy it, and send a prompt:
3030

3131
```bash
32-
agentcore project create --name MyAssistant
32+
agentcore create --name MyAssistant
3333
cd MyAssistant
34-
agentcore project deploy
35-
agentcore project invoke harness --prompt "Hey, what can you do for me?"
34+
agentcore deploy
35+
agentcore invoke harness --prompt "Hey, what can you do for me?"
3636
```
3737

3838
To start with code you own instead, create a Runtime project from a template.
3939
Run this alternative from outside an existing project:
4040

4141
```bash
42-
agentcore project create --name MyAgent --template agent-python-strands
42+
agentcore create --name MyAgent --template agent-python-strands
4343
```
4444

4545
## Command Surface
4646

47-
`project` commands manage local project specifications and their deployments.
48-
Resource commands operate on deployed resources without requiring a local project.
49-
50-
| Command | Purpose |
51-
| ---------- | ----------------------------------------------------------------------------- |
52-
| `project` | Create, develop, build, deploy, invoke, and inspect a project |
53-
| `harness` | Manage Harnesses, versions, and endpoints; invoke and inspect them |
54-
| `identity` | Manage credential providers |
55-
| `runtime` | Inspect, invoke, and open a shell in deployed Runtimes |
56-
| `memory` | Inspect Memories, actors, sessions, events, and records |
57-
| `gateway` | Inspect and invoke Gateways, inspect targets and rules, and generate policies |
58-
| `payment` | Inspect payment managers, connectors, sessions, instruments, and balances |
59-
| `eval` | Evaluate agents, manage datasets and configurations, and run experiments |
60-
| `feedback` | Submit feedback |
61-
| `config` | Read and write global CLI settings |
62-
| `update` | Check for and install CLI updates |
47+
Project commands manage local project specifications and their deployments. Resource commands
48+
operate on deployed resources without requiring a local project.
49+
50+
| Command | Purpose |
51+
| -------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
52+
| `create`, `add`, `export`, `remove`, `dev`, `deploy`, `invoke`, `log`, `traces`, `status`, `build` | Create, develop, build, deploy, invoke, and inspect a project |
53+
| `harness` | Manage Harnesses, versions, and endpoints; invoke and inspect them |
54+
| `identity` | Manage credential providers |
55+
| `runtime` | Inspect, invoke, and open a shell in deployed Runtimes |
56+
| `memory` | Inspect Memories, actors, sessions, events, and records |
57+
| `gateway` | Inspect and invoke Gateways, inspect targets and rules, and generate policies |
58+
| `payment` | Inspect payment managers, connectors, sessions, instruments, and balances |
59+
| `eval` | Evaluate agents, manage datasets and configurations, and run experiments |
60+
| `feedback` | Submit feedback |
61+
| `config` | Read and write global CLI settings |
62+
| `update` | Check for and install CLI updates |
6363

6464
Use `--help` for subcommands and flags, or browse the [command reference](command.md):
6565

6666
```bash
6767
agentcore --help
68-
agentcore project --help
68+
agentcore add --help
6969
agentcore runtime invoke --help
7070
```
7171

7272
Supported bare commands open their interactive flows in a terminal. Operation
7373
flags select headless behavior for most commands, but invoke commands can use
7474
selectors such as `--id` and `--session-id` to seed an interactive console.
75-
Run `agentcore project create` for guided setup. To create a default project
76-
without the wizard, run `agentcore project create --name MyAssistant`.
75+
Run `agentcore create` for guided setup. To create a default project without
76+
the wizard, run `agentcore create --name MyAssistant`.
7777

7878
Global flags (declared at the root, available on every command):
7979

@@ -129,14 +129,14 @@ export class AgentCoreStack extends Stack {
129129

130130
For a Harness, use `this.application.harness("<name>")` instead.
131131

132-
Run `agentcore project deploy` to apply your changes. The names passed to
132+
Run `agentcore deploy` to apply your changes. The names passed to
133133
`runtime()` or `harness()` must match the names in your project.
134134

135135
If you use an existing execution role through `executionRoleArn`, CDK cannot
136136
change its permissions. You'll need to add the required permissions to that role
137137
yourself.
138138

139-
Note that `agentcore project status` reports only the resources `agentcore.json`
139+
Note that `agentcore status` reports only the resources `agentcore.json`
140140
declares, not the ones you add in the stack.
141141

142142
## Documentation

‎docs/harness-project-configuration.md‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
## Harness Project Files
1919

20-
`project create` (without `--template`) and `project add harness` share the same
20+
`agentcore create` (without `--template`) and `agentcore add harness` share the same
2121
scaffolding flow. Each harness has `app/<name>/harness.yaml` and
2222
`app/<name>/system-prompt.md`:
2323

@@ -50,7 +50,7 @@ memory:
5050
mode: managed
5151
```
5252
53-
Edit the file, then run `agentcore project deploy` from the project directory to
53+
Edit the file, then run `agentcore deploy` from the project directory to
5454
apply changes. A local edit does not update an already deployed harness.
5555
The examples below are separate alternatives or sections to add to your file.
5656
Replace a section when switching modes rather than keeping fields from both.
@@ -151,7 +151,7 @@ systemPrompt: |
151151
Path-shaped inline values ending in `.md` or `.txt` are rejected by the current
152152
schema. Use the conventional `system-prompt.md` file instead.
153153

154-
`project add harness --system-prompt "Your instructions"` writes the supplied
154+
`agentcore add harness --system-prompt "Your instructions"` writes the supplied
155155
text to `system-prompt.md`, leaving `systemPrompt` out of the generated YAML.
156156

157157
## Memory
@@ -379,7 +379,7 @@ skills:
379379

380380
For a private repository, store its access token in an AgentCore Identity API-key
381381
credential provider. The project deployment path resolves `auth.credentialName`
382-
from the [project credentials](../command.md#agentcore-project-add-credentials) declared in
382+
from the [project credentials](../command.md#agentcore-add-credentials) declared in
383383
`agentcore.json`:
384384

385385
```yaml
@@ -471,7 +471,7 @@ rather than being silently skipped.
471471
Exporting a Harness to a code-owned Runtime has additional limits: filesystem
472472
skills are rejected, and bundled AWS skills are omitted with an explanation in
473473
`EXPORT_NOTES.md`. S3 and Git sources are supported by the exporter. See
474-
[Export a Harness](../command.md#agentcore-project-export-harness).
474+
[Export a Harness](../command.md#agentcore-export-harness).
475475

476476
See [Harness skills](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/harness-skills.html)
477477
and the [Agent Skills format](https://agentskills.io/specification) for source
@@ -551,7 +551,7 @@ dockerfile: Dockerfile
551551
```
552552

553553
The path is relative to the directory containing `harness.yaml`. If supplied
554-
through `project add harness --dockerfile`, the CLI copies the file into the
554+
through `agentcore add harness --dockerfile`, the CLI copies the file into the
555555
harness directory as `Dockerfile`.
556556

557557
Alternatively, reference a pre-built ECR image:

‎e2eTest/project/templates.test.ts‎

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -161,16 +161,7 @@ describe(
161161
const created = parseResult(
162162
ProjectCreatedSchema,
163163
await cli.run(
164-
[
165-
"project",
166-
"create",
167-
"--name",
168-
projectName,
169-
"--template",
170-
"empty",
171-
"--skip-git",
172-
"--json",
173-
],
164+
["create", "--name", projectName, "--template", "empty", "--skip-git", "--json"],
174165
projectRoot,
175166
),
176167
);
@@ -184,16 +175,7 @@ describe(
184175
const added = parseResult(
185176
OperationSchema,
186177
await cli.run(
187-
[
188-
"project",
189-
"add",
190-
"runtime",
191-
"--name",
192-
runtime.name,
193-
"--template",
194-
runtime.template,
195-
"--json",
196-
],
178+
["add", "runtime", "--name", runtime.name, "--template", runtime.template, "--json"],
197179
projectDir,
198180
),
199181
);
@@ -220,7 +202,7 @@ describe(
220202
};
221203

222204
beforeAll(() => {
223-
dev = cli.start(["project", "dev", "--mode", "headless"], projectDir);
205+
dev = cli.start(["dev", "--mode", "headless"], projectDir);
224206
dev.stdout?.on("data", captureDevOutput);
225207
dev.stderr?.on("data", captureDevOutput);
226208
dev.stdout?.resume();
@@ -242,11 +224,11 @@ describe(
242224
// the server may take a bit to get ready, so we retry on a timeout.
243225
const response = await retry(async () => {
244226
if (!dev) {
245-
throw new Error(`project dev did not start. \nstdout/stdout = ${pendingOutput}`);
227+
throw new Error(`agentcore dev did not start. \nstdout/stdout = ${pendingOutput}`);
246228
}
247229
if (dev.exitCode !== null) {
248230
throw new Error(
249-
`project dev exited with code ${dev.exitCode ?? "unknown"}. \nstdout/stdout = ${pendingOutput}`,
231+
`agentcore dev exited with code ${dev.exitCode ?? "unknown"}. \nstdout/stdout = ${pendingOutput}`,
250232
);
251233
}
252234

@@ -261,7 +243,6 @@ describe(
261243
LocalRuntimeInvokeResponseSchema,
262244
await cli.run(
263245
[
264-
"project",
265246
"invoke",
266247
"runtime",
267248
"--local",
@@ -292,7 +273,7 @@ describe(
292273
test("deploys all runtimes", { timeout: TIMEOUT_MS.PROJECT_DEPLOY }, async () => {
293274
const deployment = parseResult(
294275
DeployResponseSchema,
295-
await cli.run(["project", "deploy", "--yes", "--json"], projectDir),
276+
await cli.run(["deploy", "--yes", "--json"], projectDir),
296277
);
297278
expect(deployment.message).toContain("Deployed project");
298279
});
@@ -306,7 +287,6 @@ describe(
306287
RuntimeInvokeResponseSchema,
307288
await cli.run(
308289
[
309-
"project",
310290
"invoke",
311291
"runtime",
312292
"--name",
@@ -335,10 +315,7 @@ describe(
335315
async (runtime) => {
336316
const removed = parseResult(
337317
OperationSchema,
338-
await cli.run(
339-
["project", "remove", "runtime", "--name", runtime.name, "--json"],
340-
projectDir,
341-
),
318+
await cli.run(["remove", "runtime", "--name", runtime.name, "--json"], projectDir),
342319
);
343320
expect(removed.operation).toBe("remove");
344321
},
@@ -350,13 +327,10 @@ describe(
350327
async () => {
351328
parseResult(
352329
JsonObjectSchema,
353-
await cli.run(["project", "remove", "all", "--yes", "--json"], projectDir),
330+
await cli.run(["remove", "all", "--yes", "--json"], projectDir),
354331
);
355332

356-
parseResult(
357-
JsonObjectSchema,
358-
await cli.run(["project", "deploy", "--yes", "--json"], projectDir),
359-
);
333+
parseResult(JsonObjectSchema, await cli.run(["deploy", "--yes", "--json"], projectDir));
360334
},
361335
);
362336
},

‎scripts/generate-command-reference.mjs‎

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,23 @@ const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
99
const REPOSITORY_ROOT = resolve(SCRIPT_DIR, "..");
1010
const DEFAULT_GROUPS = [
1111
{ id: "global-options", title: "Global options", commands: [] },
12-
{ id: "project", title: "Project commands", commands: ["project"] },
12+
{
13+
id: "project",
14+
title: "Project commands",
15+
commands: [
16+
"create",
17+
"add",
18+
"export",
19+
"remove",
20+
"dev",
21+
"deploy",
22+
"invoke",
23+
"log",
24+
"traces",
25+
"status",
26+
"build",
27+
],
28+
},
1329
{ id: "harness", title: "Harness commands", commands: ["harness"] },
1430
{ id: "identity", title: "Identity commands", commands: ["identity"] },
1531
{ id: "runtime", title: "Runtime commands", commands: ["runtime"] },

‎src/assets/cdk/README.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ the conventional `system-prompt.md` file in the harness directory.
1717
You normally do not run this app directly:
1818

1919
```bash
20-
agentcore project build # synthesizes the CloudFormation templates into agentcore/cdk/cdk.out
21-
agentcore project deploy # synthesizes, then deploys the stack for the selected target
22-
agentcore project status # reports the resources agentcore.json declares
20+
agentcore build # synthesizes the CloudFormation templates into agentcore/cdk/cdk.out
21+
agentcore deploy # synthesizes, then deploys the stack for the selected target
22+
agentcore status # reports the resources agentcore.json declares
2323
```
2424

2525
`npm run build` compiles the app, and `npx cdk synth` / `npx cdk diff` work from this directory too.
@@ -43,10 +43,10 @@ checkout.addEnvironmentVariable('ORDERS_TABLE', orders.tableName);
4343
orders.grantReadData(this.application.harness('support')); // any AWS L2 grant works too
4444
```
4545

46-
Then run `agentcore project deploy` again. An unknown name fails at synth and lists the names that exist.
46+
Then run `agentcore deploy` again. An unknown name fails at synth and lists the names that exist.
4747

4848
If a runtime or harness is configured with an `executionRoleArn`, CDK cannot modify that imported role: every grant
4949
emits a synth-time warning listing the permissions that were not attached, and the role must already carry them.
5050

51-
`agentcore project status` reports only the resources `agentcore.json` declares; resources you add here are visible
51+
`agentcore status` reports only the resources `agentcore.json` declares; resources you add here are visible
5252
through CloudFormation (`aws cloudformation describe-stack-resources`).

‎src/assets/evaluators/python-lambda/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ def handler(input: EvaluatorInput, context) -> EvaluatorOutput:
2828
return EvaluatorOutput(value=1.0, label="Pass", explanation="…")
2929
```
3030

31-
Then `agentcore project deploy` packages this directory into the evaluator
31+
Then `agentcore deploy` packages this directory into the evaluator
3232
Lambda and registers the evaluator.

‎src/assets/templates/a2a-python-strands/README.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ def my_tool(param: str) -> str:
2121

2222
## Developing locally
2323

24-
`agentcore project dev` starts the agent locally on `0.0.0.0:9000`. Fetch its agent card at
24+
`agentcore dev` starts the agent locally on `0.0.0.0:9000`. Fetch its agent card at
2525
`http://127.0.0.1:9000/.well-known/agent-card.json` and send it messages by posting A2A
2626
JSON-RPC to `http://127.0.0.1:9000/`.
2727

2828
## Deployment
2929

30-
`agentcore project deploy` deploys the agent into Amazon Bedrock AgentCore. Invoke it with the
30+
`agentcore deploy` deploys the agent into Amazon Bedrock AgentCore. Invoke it with the
3131
AWS CLI (`bedrock-agentcore invoke-agent-runtime`) using an A2A JSON-RPC payload.

‎src/assets/templates/agent-python-langchain/README.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@ session, and streams its response.
1313
between turns.
1414
- `model/load.py`: creates the Bedrock chat model with `init_chat_model`.
1515
- `pyproject.toml`: Python dependencies, managed with
16-
[uv](https://docs.astral.sh/uv/). `agentcore project create` has already run
16+
[uv](https://docs.astral.sh/uv/). `agentcore create` has already run
1717
`uv sync` for you (unless you passed `--skip-install`), so `.venv/` is ready.
1818

1919
## Develop
2020

2121
Run the agent locally from the project root:
2222

2323
```bash
24-
agentcore project dev
25-
agentcore project invoke runtime --local --name {{name}} --payload '{"prompt":"What is 2 plus 3?"}'
24+
agentcore dev
25+
agentcore invoke runtime --local --name {{name}} --payload '{"prompt":"What is 2 plus 3?"}'
2626
```
2727

2828
Environment variables for local development go in `agentcore/.env.local`
@@ -31,8 +31,8 @@ Environment variables for local development go in `agentcore/.env.local`
3131
## Deploy
3232

3333
```bash
34-
agentcore project deploy
35-
agentcore project invoke runtime --payload '{"prompt":"Hello!"}'
34+
agentcore deploy
35+
agentcore invoke runtime --payload '{"prompt":"Hello!"}'
3636
```
3737

3838
Traces are collected automatically: AgentCore Runtime starts the agent under

‎src/assets/templates/agent-python-minimal/README.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ invocation — a starting point you own and grow into a real agent.
99
- `main.py` — the agent. A `BedrockAgentCoreApp` wraps the entrypoint that
1010
receives each invocation payload and returns the response.
1111
- `pyproject.toml` — Python dependencies, managed with
12-
[uv](https://docs.astral.sh/uv/). `agentcore project create` has already run
12+
[uv](https://docs.astral.sh/uv/). `agentcore create` has already run
1313
`uv sync` for you (unless you passed `--skip-install`), so `.venv/` is ready.
1414

1515
## Develop
1616

1717
Run the agent locally from the project root:
1818

1919
```bash
20-
agentcore project dev
20+
agentcore dev
2121
```
2222

2323
Environment variables for local development go in `agentcore/.env.local`
@@ -26,6 +26,6 @@ Environment variables for local development go in `agentcore/.env.local`
2626
## Deploy
2727

2828
```bash
29-
agentcore project deploy
30-
agentcore project invoke runtime --payload '{"prompt":"Hello!"}'
29+
agentcore deploy
30+
agentcore invoke runtime --payload '{"prompt":"Hello!"}'
3131
```

0 commit comments

Comments
 (0)