@tityra/cli 1.0.0 → 1.1.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.1.1
4
+
5
+ - Update customer-facing audit terminology to describe website content audits.
6
+ - Clarify the content delivery, structure and context covered by the service.
7
+
8
+ ## 1.1.0
9
+
10
+ - Clarify that audit requests use explicit authorisation and validated scope without a second manual staff authority confirmation, while retaining report quality and commercial checks.
11
+ - Add selected-project monitoring reads and confirmed enable, pause, resume and scope changes.
12
+ - Require a new explicit `monitoring:write` grant for changes, preserving revision checks and stable retry keys.
13
+ - Explain that confirmed website and scope authorisation enables monitoring without separate administrator approval.
14
+ - Expose monitoring settings in the interactive project menu without adding write permissions.
15
+ - Show server-provided pricing status, including genuine included weekly audits, in audit tables.
16
+ - Clarify the first-request schedule, automatic admission of overdue audits and organisation Billing Profile eligibility.
17
+ - Clarify Scale and Enterprise workspace plans, monthly and annual Enterprise pricing and
18
+ per-project weekly AX Audit monitoring in the package documentation.
19
+ - Specify that Expert Review always follows the separately paid request and checkout flow.
20
+ - Explain that AX Audit and Expert Review requests submitted with `audits create` are separately priced;
21
+ billing assignment and subscription changes stay in the Tityra application.
22
+
3
23
  ## 1.0.0
4
24
 
5
25
  - Stable `@tityra/cli` release, version `1.0.0`, distributed through npm's `latest` tag.
package/README.md CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Your Tityra workspace, from the terminal. Explore projects, read audit reports and work through findings from the command line, scripts or an AI agent.
4
4
 
5
- The CLI is an API client for the Tityra service. It uses the same account permissions, selected projects and customer workflows as the application.
5
+ Tityra's website content audits review content delivery, structure and available context within an agreed website scope. Reports document findings and supporting evidence. The CLI is an API client for the Tityra service and uses the same account permissions, selected projects and customer workflows as the application.
6
6
 
7
7
  ## Project status
8
8
 
9
- Version `1.0.0` is the stable release. Stable releases use npm's `latest` tag. CI targets Node.js 22 and 24 on Linux, macOS and Windows; local regression tests use isolated fixtures rather than live customer accounts.
9
+ Version `1.1.1` updates the terminology used for Tityra's website content audit service. Version `1.1.0` added project monitoring commands and included-audit pricing status. Stable releases use npm's `latest` tag; check the [npm package page](https://www.npmjs.com/package/@tityra/cli) for the currently published version. CI targets Node.js 22 and 24 on Linux, macOS and Windows; local regression tests use isolated fixtures rather than live customer accounts.
10
10
 
11
11
  ## Basic functionality
12
12
 
@@ -18,13 +18,13 @@ Version `1.0.0` is the stable release. Stable releases use npm's `latest` tag. C
18
18
 
19
19
  ## What it does not do
20
20
 
21
- The CLI does not execute audits locally, approve website authority or replace Tityra's staff review. It does not verify a fix, change technical report evidence, expose private staff notes or grant access to another customer's data. Checkout creates a link; it does not make a payment or authorise automatic charges.
21
+ The CLI does not execute audits locally or independently verify website ownership. Your explicit `authorisation: true` declaration and the validated website scope provide the required request authorisation; no second manual staff confirmation of website authority is required. Individually requested reports retain Tityra's staff quality review. The CLI does not verify a fix, change technical report evidence, expose private staff notes or grant access to another customer's data. Checkout creates a link; it does not make a payment or authorise automatic charges.
22
22
 
23
23
  The interactive workspace offers read-only navigation. Account changes use the explicit commands described below and require reviewed JSON input plus `--yes`.
24
24
 
25
25
  ## Prerequisites and installation
26
26
 
27
- You need **Node.js 22.14 or later**, a Tityra customer account and permission to access the projects you select. Staff and partner operations are not delegated through this connection. Browser login requires the browser to reach the temporary loopback callback on the computer running the CLI.
27
+ You need **Node.js 22.14 or later**, a Tityra customer account and permission to access the projects you select. Staff operations are not delegated through this connection. Browser login requires the browser to reach the temporary loopback callback on the computer running the CLI.
28
28
 
29
29
  Install the stable release:
30
30
 
@@ -73,6 +73,43 @@ tityra audits payment AUDIT_ID
73
73
 
74
74
  Audit options describe the existing eligibility and review rules. A submitted request does not start an instant scan or promise a delivery date. Payment status provides the canonical report reference when available.
75
75
 
76
+ ### Workspace plans and weekly monitoring
77
+
78
+ Scale and Enterprise support unlimited organisations, projects and members. Enterprise offers monthly billing at £3,600 or annual billing at £36,000, excluding VAT, with one scheduled In-Depth Audit per week for each enabled project and up to 500 pages per project. Check [current plans and prices](https://app.tityra.com/customer) in your account before subscribing.
79
+
80
+ Enable **Monitor this project** in the Tityra application, or use the monitoring commands below with an explicitly granted `monitoring:write` permission and current project management access. Confirm that you are authorised to scan the website and selected pages. Eligibility comes from the project's organisation and its explicitly assigned Billing Profile, with an active subscription or explicit complimentary assignment that includes weekly monitoring. Your personal plan or membership in another paying organisation does not supply it. Your confirmed project consent enables monitoring without a separate administrator approval. Reports are delivered automatically after the required checks. You can pause and resume each project separately; existing reports remain available.
81
+
82
+ The first included website content audit is due seven days after the project's first production audit request for its current website, whether that request was Initial Audit, In-Depth Audit or Expert Review. If no request exists, confirmed monitoring consent starts that interval. Enabling or resuming an eligible project whose audit is already due automatically queues one included audit. Later included audits remain at least seven days apart; missed slots do not accumulate. Read the server's `nextScheduledAt` and `history` rather than calculating a new start date locally.
83
+
84
+ Use `audits list` and `reports get` to read released weekly website content audit reports within the projects and permissions you approved. A paid In-Depth Audit submitted through `audits create` is an additional request, charged separately; it does not replace the included weekly audit slot. Expert Review is never included in weekly monitoring and always follows the normal separately paid request and checkout process. Initial Audit requests retain their normal eligibility limits. The CLI cannot choose a payer or change a subscription.
85
+
86
+ Audit lists show the server's pricing status when your connection has `billing:read`; genuine included monitoring requests use `included`. A missing pricing status does not mean a payment is due. Use `audits payment AUDIT_ID` for current payment requirements. Normal report publication and payment checks remain in force.
87
+
88
+ Monitoring commands require version `1.1.0` or later; version `1.0.0` does not include them. Read settings with `projects:read`. To change them, request `monitoring:write` through fresh consent; default scopes and existing connections stay unchanged. The `--scope` list replaces the defaults, so include any other access you still need.
89
+
90
+ The interactive project menu also offers **Weekly monitoring** to read the same settings. It does not change monitoring or request additional permissions.
91
+
92
+ ```sh
93
+ tityra auth login --scope "projects:read monitoring:write"
94
+ tityra projects monitoring get PROJECT_ID --json
95
+ tityra projects monitoring update PROJECT_ID --input monitoring.json --yes --json
96
+ ```
97
+
98
+ For `monitoring.json`, copy the current `revision` and `website` into `expectedRevision` and `expectedWebsite`, and generate a UUID once for the intended action:
99
+
100
+ ```json
101
+ {
102
+ "action": "enable",
103
+ "expectedRevision": 0,
104
+ "expectedWebsite": "https://example.com/",
105
+ "authorisation": true,
106
+ "auditScope": { "mode": "website" },
107
+ "idempotencyKey": "10000000-0000-4000-8000-000000000001"
108
+ }
109
+ ```
110
+
111
+ `enable` also resumes monitoring or changes its scope. To pause, send only `action: "disable"`, the current `expectedRevision` and a new action's `idempotencyKey`. Revision zero is valid for a project without settings. On an uncertain write, retry only the same input and key. The server checks the selected project, current manager, explicit payer, subscription and website. Confirm your authorisation again when changing the website or scope.
112
+
76
113
  ### 3. Read reports, findings and discussions
77
114
 
78
115
  ```sh
@@ -114,18 +151,19 @@ tityra discussions create REPORT_ID FINDING_ID --input discussion.json --yes --j
114
151
 
115
152
  Other write commands use the same confirmation pattern:
116
153
 
117
- | Command | Input fields besides `idempotencyKey` |
118
- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
119
- | `audits create` | `projectId`, `plan` (`free`, `automated`, `human`), `authorisation: true`; optional `notes`, `auditScope` |
120
- | `findings challenge REPORT_ID FINDING_ID` | `reason` (`irrelevant`, `false_positive`, `unclear_other`), `body`, `expectedReportRevision` |
121
- | `discussions create REPORT_ID FINDING_ID` | `body`, `expectedReportRevision` |
122
- | `discussions reply REPORT_ID FINDING_ID THREAD_ID` | `body`, `expectedReportRevision`, `expectedThreadRevision` |
123
- | `findings remediate REPORT_ID FINDING_ID` | `status`, `reason`, `expectedReportRevision`, `expectedTrackingRevision` |
124
- | `reports checkout REPORT_ID` | No additional fields |
154
+ | Command | Input fields besides `idempotencyKey` |
155
+ | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
156
+ | `audits create` | `projectId`, `plan` (`free`, `automated`, `human`), `authorisation: true`; optional `notes`, `auditScope` |
157
+ | `projects monitoring update PROJECT_ID` | `action` (`enable`, `disable`), `expectedRevision`; enable requires `authorisation: true`, `expectedWebsite`, and accepts `auditScope` |
158
+ | `findings challenge REPORT_ID FINDING_ID` | `reason` (`irrelevant`, `false_positive`, `unclear_other`), `body`, `expectedReportRevision` |
159
+ | `discussions create REPORT_ID FINDING_ID` | `body`, `expectedReportRevision` |
160
+ | `discussions reply REPORT_ID FINDING_ID THREAD_ID` | `body`, `expectedReportRevision`, `expectedThreadRevision` |
161
+ | `findings remediate REPORT_ID FINDING_ID` | `status`, `reason`, `expectedReportRevision`, `expectedTrackingRevision` |
162
+ | `reports checkout REPORT_ID` | No additional fields |
125
163
 
126
164
  Read current revision fields using `--json` before changing a record. Discussion and challenge messages contain 3–4,000 characters. Remediation statuses are `open`, `planned`, `in_progress`, `resolved`, `wont_fix` and `not_applicable`; `resolved` remains customer-reported rather than independently verified.
127
165
 
128
- Audit scope is either `{"mode":"website"}` or `{"mode":"specific_urls","urls":["https://example.com/path"]}`. The project supplies the website, and existing authority, scope and commercial checks still apply. Checkout creates a link for the customer to complete.
166
+ Audit scope is either `{"mode":"website"}` or `{"mode":"specific_urls","urls":["https://example.com/path"]}`. The project supplies the website. Normal audit requests record your explicit authorisation for that scope without a separate manual staff authority confirmation. Eligibility, scope and commercial checks still apply, and individually requested reports retain staff quality review. Monitoring reuses the confirmed project consent described above. Checkout creates a link for the customer to complete.
129
167
 
130
168
  ### 5. Use the CLI in scripts or with an agent
131
169
 
@@ -36,7 +36,8 @@ export function registerAuditsCommands(program, context) {
36
36
  });
37
37
  writeOptions(audits
38
38
  .command('create')
39
- .description('Request an audit under the existing eligibility and authority rules')).action(async (_options, command) => {
39
+ .description('Request an additional audit with explicit authorisation for its website scope')
40
+ .addHelpText('after', '\nYour authorisation: true declaration and the validated website scope provide the required request authorisation. No second manual staff confirmation of website authority is required.\nEligibility, scope and commercial checks still apply. Individually requested reports retain staff quality review.\nWeekly monitoring includes the In-Depth Audit only. Additional In-Depth Audits and Expert Review require a separate request and payment through the normal checkout.\nUse projects monitoring get/update for an explicitly authorised project, or manage monitoring in the Tityra application.\n')).action(async (_options, command) => {
40
41
  await write(command, context, 'audit', '/api/agent/audits');
41
42
  });
42
43
  }
@@ -1,11 +1,28 @@
1
- import { read } from './shared.js';
1
+ import { identifier } from '../schema/writeSchema.js';
2
+ import { read, write, writeOptions } from './shared.js';
2
3
  export function registerProjectsCommands(program, context) {
3
- program
4
+ const projects = program
4
5
  .command('projects')
5
- .description('Read the projects selected for this connection')
6
+ .description('Read selected projects and manage authorised weekly monitoring');
7
+ projects
6
8
  .command('list')
7
9
  .description('List accessible projects')
8
10
  .action(async (_options, command) => {
9
11
  await read(command, context, '/api/agent/projects', 'Loading projects');
10
12
  });
13
+ const monitoring = projects
14
+ .command('monitoring')
15
+ .description('Read or change weekly website content audit monitoring for a selected project');
16
+ monitoring
17
+ .command('get <project-id>')
18
+ .description('Read current monitoring settings, scope, revision and report history')
19
+ .action(async (id, _options, command) => {
20
+ await read(command, context, `/api/agent/projects/${identifier(id)}/monitoring`, 'Loading project monitoring');
21
+ });
22
+ writeOptions(monitoring
23
+ .command('update <project-id>')
24
+ .description('Enable, pause, resume or update the scope of weekly website content audits')
25
+ .addHelpText('after', '\nRequires an explicitly granted monitoring:write permission and current project management access.\nRead settings first; include the current expectedRevision and keep the same input and idempotencyKey when retrying an uncertain write.\nUse action enable with authorisation: true and the returned website as expectedWebsite. Use action disable to pause.\nEnabling monitoring records your website and scope authorisation without a separate administrator approval. Confirm that authorisation again after changing the website or scope.\nThe first included audit is due seven days after the first audit request for this project website, or after consent if none exists. Enabling or resuming an overdue eligible project queues its due website content audit automatically. Read nextScheduledAt and history for the current server state.\nThe CLI cannot select a payer or change a subscription.\n')).action(async (id, _options, command) => {
26
+ await write(command, context, 'monitoring', `/api/agent/projects/${identifier(id)}/monitoring`, 'PATCH');
27
+ });
11
28
  }
@@ -38,6 +38,14 @@ export function validateWrite(kind, input) {
38
38
  'idempotencyKey',
39
39
  ],
40
40
  checkout: ['idempotencyKey'],
41
+ monitoring: [
42
+ 'action',
43
+ 'expectedRevision',
44
+ 'idempotencyKey',
45
+ 'authorisation',
46
+ 'expectedWebsite',
47
+ 'auditScope',
48
+ ],
41
49
  };
42
50
  if (Object.keys(body).some((key) => !fields[kind].includes(key)))
43
51
  usage('Input contains an unsupported field. Use the documented request body.');
@@ -51,7 +59,32 @@ export function validateWrite(kind, input) {
51
59
  if (!Number.isSafeInteger(body[key]) || Number(body[key]) < 1)
52
60
  usage(`${key} must be a positive integer from the current server response.`);
53
61
  };
54
- if (kind === 'audit') {
62
+ if (kind === 'monitoring') {
63
+ if (!['enable', 'disable'].includes(String(body.action)))
64
+ usage('Monitoring action must be enable or disable.');
65
+ if (!Number.isSafeInteger(body.expectedRevision) || Number(body.expectedRevision) < 0)
66
+ usage('expectedRevision must be a non-negative integer from the current monitoring response.');
67
+ if (body.action === 'enable') {
68
+ if (body.authorisation !== true)
69
+ usage('Enabling monitoring requires explicit authorisation: true.');
70
+ text('expectedWebsite', 1, 2000);
71
+ let website;
72
+ try {
73
+ website = new URL(body.expectedWebsite);
74
+ }
75
+ catch {
76
+ usage('expectedWebsite must be the website returned by the monitoring response.');
77
+ }
78
+ if (!['http:', 'https:'].includes(website.protocol) || website.username || website.password)
79
+ usage('expectedWebsite must be an HTTP(S) website without credentials.');
80
+ validateAuditScope(body.auditScope);
81
+ }
82
+ else if (body.authorisation !== undefined ||
83
+ body.expectedWebsite !== undefined ||
84
+ body.auditScope !== undefined)
85
+ usage('Pausing monitoring accepts only action, expectedRevision and idempotencyKey.');
86
+ }
87
+ else if (kind === 'audit') {
55
88
  if (typeof body.projectId !== 'string')
56
89
  usage('projectId is required.');
57
90
  identifier(body.projectId);
@@ -61,25 +94,7 @@ export function validateWrite(kind, input) {
61
94
  usage('Audit requests require a plan and explicit authorisation: true.');
62
95
  if (body.notes !== undefined)
63
96
  text('notes', 0, 20000);
64
- if (body.auditScope !== undefined) {
65
- if (!body.auditScope || typeof body.auditScope !== 'object' || Array.isArray(body.auditScope))
66
- usage('auditScope must be an object.');
67
- const scope = body.auditScope;
68
- if (scope.mode === 'website') {
69
- if (Object.keys(scope).length !== 1)
70
- usage('Website auditScope accepts only mode.');
71
- }
72
- else if (scope.mode === 'specific_urls') {
73
- if (Object.keys(scope).some((k) => !['mode', 'urls'].includes(k)) ||
74
- !Array.isArray(scope.urls) ||
75
- scope.urls.length < 1 ||
76
- scope.urls.length > 500 ||
77
- scope.urls.some((url) => typeof url !== 'string' || !url.length || url.length > 2000))
78
- usage('specific_urls requires 1–500 URL strings.');
79
- }
80
- else
81
- usage('auditScope.mode must be website or specific_urls.');
82
- }
97
+ validateAuditScope(body.auditScope);
83
98
  }
84
99
  else if (kind !== 'checkout') {
85
100
  revision('expectedReportRevision');
@@ -101,3 +116,24 @@ export function validateWrite(kind, input) {
101
116
  }
102
117
  return body;
103
118
  }
119
+ function validateAuditScope(value) {
120
+ if (value === undefined)
121
+ return;
122
+ if (!value || typeof value !== 'object' || Array.isArray(value))
123
+ usage('auditScope must be an object.');
124
+ const scope = value;
125
+ if (scope.mode === 'website') {
126
+ if (Object.keys(scope).length !== 1)
127
+ usage('Website auditScope accepts only mode.');
128
+ }
129
+ else if (scope.mode === 'specific_urls') {
130
+ if (Object.keys(scope).some((key) => !['mode', 'urls'].includes(key)) ||
131
+ !Array.isArray(scope.urls) ||
132
+ scope.urls.length < 1 ||
133
+ scope.urls.length > 500 ||
134
+ scope.urls.some((url) => typeof url !== 'string' || !url.length || url.length > 2000))
135
+ usage('specific_urls requires 1–500 URL strings.');
136
+ }
137
+ else
138
+ usage('auditScope.mode must be website or specific_urls.');
139
+ }
@@ -91,9 +91,11 @@ export class ApiClient {
91
91
  : response.status === 403
92
92
  ? 'Your connection does not have permission for this project or action. Review its scopes and project access.'
93
93
  : response.status === 402
94
- ? 'Payment is required before this report is available.'
94
+ ? pathname.endsWith('/monitoring')
95
+ ? 'This project is not currently eligible for monitoring. Review its subscription in Tityra.'
96
+ : 'Payment is required before this report is available.'
95
97
  : response.status === 409
96
- ? 'The report or discussion changed. Read the latest revision and review your input before retrying.'
98
+ ? 'The resource or its authorisation changed. Read the latest revision and review your input before retrying.'
97
99
  : response.status === 429
98
100
  ? 'Tityra rate limited this request. Wait before retrying; preserve the idempotency key for writes.'
99
101
  : response.status === 404
@@ -20,7 +20,7 @@ export function welcomeBanner(version, color = true) {
20
20
  level: color && !('NO_COLOR' in process.env) && supportsColor ? supportsColor.level : 0,
21
21
  });
22
22
  if (process.env.TERM === 'dumb')
23
- return `\nTityra · v${version}\n`;
23
+ return `\nTityra v${version}\n`;
24
24
  const captions = {
25
25
  2: paint.hex('#ed4832').bold('Tityra'),
26
26
  4: (process.stdout.columns || 80) >= 70 ? 'Your workspace, from the terminal.' : '',
@@ -39,7 +39,15 @@ export function createOutput(json = false, color = true) {
39
39
  process.stdout.write(paint.dim('No results.\n'));
40
40
  return;
41
41
  }
42
- const keys = ['id', 'threadId', 'title', 'name', 'status', 'severity'].filter((key) => rows.some((row) => row[key] !== undefined));
42
+ const keys = [
43
+ 'id',
44
+ 'threadId',
45
+ 'title',
46
+ 'name',
47
+ 'status',
48
+ 'severity',
49
+ 'pricingStatus',
50
+ ].filter((key) => rows.some((row) => row[key] !== undefined));
43
51
  if (!keys.length) {
44
52
  process.stdout.write(humanJson(data) + '\n');
45
53
  return;
@@ -53,12 +61,12 @@ export function createOutput(json = false, color = true) {
53
61
  })
54
62
  .join(' ')
55
63
  .trimEnd();
56
- process.stdout.write(paint.bold(rowText(Object.fromEntries(keys.map((key) => [key, key.toUpperCase()])))) + '\n');
64
+ process.stdout.write(paint.bold(rowText(Object.fromEntries(keys.map((key) => [key, key === 'pricingStatus' ? 'PRICING' : key.toUpperCase()])))) + '\n');
57
65
  for (const row of rows)
58
66
  process.stdout.write(rowText(row) + '\n');
59
67
  if (value?.pagination && typeof value.pagination === 'object') {
60
68
  const pagination = value.pagination;
61
- process.stdout.write(paint.dim(`\nPage ${terminalText(pagination.page)} · ${terminalText(pagination.total)} total${pagination.hasMore ? ' · more available' : ''}\n`));
69
+ process.stdout.write(paint.dim(`\nPage ${terminalText(pagination.page)}: ${terminalText(pagination.total)} total${pagination.hasMore ? ', more available' : ''}\n`));
62
70
  }
63
71
  process.stdout.write(paint.dim('Use --json for complete records and revision fields.\n'));
64
72
  },
@@ -56,7 +56,7 @@ async function requestMenu(context, initial, environment) {
56
56
  if (reportId)
57
57
  choices.push({ title: 'Read report', value: 'report' }, { title: 'View findings', value: 'findings' });
58
58
  choices.push({ title: 'Payment status', value: 'payment' }, back);
59
- const action = await environment.choose(`Audit ${terminalText(request.id)} · ${terminalText(request.status)}`, choices);
59
+ const action = await environment.choose(`Audit ${terminalText(request.id)}: ${terminalText(request.status)}`, choices);
60
60
  if (!action || action === 'back')
61
61
  return;
62
62
  if (action === 'status') {
@@ -81,9 +81,16 @@ async function recentAudits(context, projectId, environment) {
81
81
  const result = await load(context, `/api/agent/audits?${query}`);
82
82
  const requests = items(result, 'requests');
83
83
  const choices = requests.map((request, index) => ({
84
- title: `${terminalText(request.packageName || request.id)} · ${terminalText(request.status)}`,
84
+ title: `${terminalText(request.packageName || request.id)}: ${terminalText(request.status)}`,
85
85
  value: `request:${index}`,
86
- description: terminalText(request.receivedAt || request.websiteUrl),
86
+ description: [
87
+ terminalText(request.receivedAt || request.websiteUrl),
88
+ ...(typeof request.pricingStatus === 'string'
89
+ ? [`Pricing: ${terminalText(request.pricingStatus)}`]
90
+ : []),
91
+ ]
92
+ .filter(Boolean)
93
+ .join(' | '),
87
94
  }));
88
95
  if (!requests.length)
89
96
  environment.write('\nNo audit requests on this page.\n');
@@ -95,7 +102,7 @@ async function recentAudits(context, projectId, environment) {
95
102
  if (page > 1)
96
103
  choices.push({ title: 'Previous page', value: 'previous' });
97
104
  choices.push(back);
98
- const selected = await environment.choose(`Recent audits · page ${page}`, choices);
105
+ const selected = await environment.choose(`Recent audits: page ${page}`, choices);
99
106
  if (!selected || selected === 'back')
100
107
  return;
101
108
  if (selected === 'next') {
@@ -145,6 +152,7 @@ async function projectWorkspace(context, projects, environment) {
145
152
  const action = await environment.choose('What would you like to do?', [
146
153
  { title: 'Recent audits', value: 'audits' },
147
154
  { title: 'Audit options', value: 'options' },
155
+ { title: 'Weekly monitoring', value: 'monitoring' },
148
156
  { title: 'Switch project', value: 'switch' },
149
157
  { title: 'Connection status', value: 'status' },
150
158
  exit,
@@ -157,6 +165,8 @@ async function projectWorkspace(context, projects, environment) {
157
165
  context.output(await environment.status(context.auth));
158
166
  else if (action === 'options')
159
167
  context.output(await load(context, `/api/agent/audits/options?${new URLSearchParams({ projectId })}`));
168
+ else if (action === 'monitoring')
169
+ context.output(await load(context, `/api/agent/projects/${projectId}/monitoring`));
160
170
  else if (action === 'audits')
161
171
  await recentAudits(context, projectId, environment);
162
172
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tityra/cli",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Official Tityra CLI for projects, audits, reports and findings. Built for developers, AI agents and automated workflows.",
5
5
  "type": "module",
6
6
  "bin": {