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
1 change: 1 addition & 0 deletions .github/workflows/nightly-install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ jobs:
run: |
test -e "$HOME/.kiro/agents/study-mentor.json"
test -e "$HOME/.kiro/agents/study-plan-architect.json"
test -e "$HOME/.kiro/agents/studyloop.json"
test -e "$HOME/.claude/agents/socratic-mentor.md"
test -e "$HOME/.claude/agents/study-plan-architect.md"
test -e "$HOME/.pi/agent/AGENTS.md"
Expand Down
31 changes: 19 additions & 12 deletions .secrets.baseline

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,17 @@ experience may change before `1.0.0`.

### Fixed

- Web (ACP) Kiro sessions run StudyLoop's own `studyloop` agent. They started
`kiro-cli acp` with no `--agent`, so each ran under whatever the learner's
default Kiro agent was: Kiro's built-in (its own system prompt, the learner's
personal steering and skills, every MCP server in their global `mcp.json`)
or the learner's own agent. `studyloop install agents` now installs
`~/.kiro/agents/studyloop.json` (StudyLoop's two MCP servers, the persona
agents' session-export hook and command denylist, no persona, no
pre-approved tools), every Kiro ACP launch names it, and `studyloop doctor`
checks that kiro-cli validates and lists it and that no built-in agent
shadows it. Run `studyloop install agents --tool kiro` (or
`studyloop doctor --fix`) once after upgrading.
- The `now` engine counts every "last seen N day(s) ago" from the one clock
it reads per plan. The due-progress collector took its day count from a
second clock inside `history/progress.py`, so under a frozen test clock the
Expand Down
220 changes: 220 additions & 0 deletions agents/kiro/studyloop.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
{
"name": "studyloop",
"description": "StudyLoop's own agent for web (ACP) study and planning sessions: StudyLoop's MCP servers and nothing of the learner's. It carries no persona; the session sends one. Installed by studyloop install agents.",
"tools": [
"@builtin",
"@studyloop",
"@session-db"
],
"mcpServers": {
"studyloop": {
"command": "studyloop-mcp",
"args": []
},
"session-db": {
"command": "session-db-mcp",
"args": []
}
},
"hooks": {
"stop": [
{
"command": "$HOME/.local/bin/session-export --kiro-only >>$HOME/.config/studyloop/export-hook.log 2>&1 || { rc=$?; echo \"$(date -u +%Y-%m-%dT%H:%M:%SZ) session-export --kiro-only FAILED exit=$rc\" >>$HOME/.config/studyloop/export-hook.log; }",
"description": "studyloop:session-export-hook"
}
]
},
"allowedTools": [],
"toolsSettings": {
"execute_bash": {
"deniedCommands": [
".*base64.*/\\.aws/.*",
".*cat.*/\\.aws/.*",
".*cat.*/\\.docker/config\\.json.*",
".*cat.*/\\.git-credentials.*",
".*cat.*/\\.gnupg/.*",
".*cat.*/\\.gpg/.*",
".*cat.*/\\.kube/config.*",
".*cat.*/\\.meshclaw/\\.env.*",
".*cat.*/\\.netrc.*",
".*cat.*/\\.npmrc.*",
".*cat.*/\\.pypirc.*",
".*cat.*/\\.ssh/.*",
".*cp.*/\\.aws/.*",
".*cp.*/\\.ssh/.*",
".*curl.*169\\.254\\.169\\.254.*",
".*curl.*\\$AWS_ACCESS.*",
".*curl.*\\$AWS_SECRET.*",
".*curl.*\\$AWS_SESSION.*",
".*echo.*\\$AWS_ACCESS.*",
".*echo.*\\$AWS_SECRET.*",
".*echo.*\\$AWS_SESSION.*",
".*env.*grep.*AWS.*",
".*head.*/\\.aws/.*",
".*head.*/\\.ssh/.*",
".*less.*/\\.aws/.*",
".*less.*/\\.ssh/.*",
".*more.*/\\.aws/.*",
".*printenv.*AWS.*",
".*python.*boto3.*get_credentials.*",
".*python.*botocore.*credentials.*",
".*python.*open.*/\\.aws/.*",
".*python.*open.*/\\.ssh/.*",
".*strings.*/\\.aws/.*",
".*tail.*/\\.aws/.*",
".*tail.*/\\.ssh/.*",
".*wget.*169\\.254\\.169\\.254.*",
"DROP DATABASE.*",
"DROP TABLE.*",
"TRUNCATE TABLE.*",
"aws autoscaling delete-.*",
"aws cloudformation delete-stack.*",
"aws cloudformation update-termination-protection.*",
"aws dynamodb delete-table.*",
"aws ec2 delete-.*",
"aws ec2 terminate-instances.*",
"aws ecr delete-.*",
"aws ecs delete-.*",
"aws eks delete-cluster.*",
"aws elasticache delete-.*",
"aws elb delete-.*",
"aws elbv2 delete-.*",
"aws glue delete-.*",
"aws iam create-access-key.*",
"aws iam delete-.*",
"aws kinesis delete-.*",
"aws kms schedule-key-deletion.*",
"aws lambda delete-function.*",
"aws logs delete-.*",
"aws opensearch delete-.*",
"aws rds delete-.*",
"aws redshift delete-.*",
"aws route53 delete-.*",
"aws s3 cp .* s3://.*",
"aws s3 mv .* s3://.*",
"aws s3 rb.*",
"aws s3 rm.*",
"aws s3 sync .* s3://.*",
"aws s3api delete-.*",
"aws secretsmanager delete-secret.*",
"aws sns delete-.*",
"aws sqs delete-.*",
"aws stepfunctions delete-.*",
"cdk destroy.*",
"chmod 777.*",
"curl .* \\| bash",
"curl .* \\| sh",
"dd if=.*",
"export AWS_ACCESS.*",
"export AWS_SECRET.*",
"git push.*--force.*",
"git push.*-f .*",
"git reset --hard.*",
"kubectl delete namespace.*",
"mkfs.*",
"nc -e.*",
"ncat -e.*",
"pulumi destroy.*",
"rm -rf /.*",
"rm -rf ~.*",
"terraform destroy.*",
"wget .* \\| bash"
]
},
"shell": {
"deniedCommands": [
".*base64.*/\\.aws/.*",
".*cat.*/\\.aws/.*",
".*cat.*/\\.docker/config\\.json.*",
".*cat.*/\\.git-credentials.*",
".*cat.*/\\.gnupg/.*",
".*cat.*/\\.gpg/.*",
".*cat.*/\\.kube/config.*",
".*cat.*/\\.meshclaw/\\.env.*",
".*cat.*/\\.netrc.*",
".*cat.*/\\.npmrc.*",
".*cat.*/\\.pypirc.*",
".*cat.*/\\.ssh/.*",
".*cp.*/\\.aws/.*",
".*cp.*/\\.ssh/.*",
".*curl.*169\\.254\\.169\\.254.*",
".*curl.*\\$AWS_ACCESS.*",
".*curl.*\\$AWS_SECRET.*",
".*curl.*\\$AWS_SESSION.*",
".*echo.*\\$AWS_ACCESS.*",
".*echo.*\\$AWS_SECRET.*",
".*echo.*\\$AWS_SESSION.*",
".*env.*grep.*AWS.*",
".*head.*/\\.aws/.*",
".*head.*/\\.ssh/.*",
".*less.*/\\.aws/.*",
".*less.*/\\.ssh/.*",
".*more.*/\\.aws/.*",
".*printenv.*AWS.*",
".*python.*boto3.*get_credentials.*",
".*python.*botocore.*credentials.*",
".*python.*open.*/\\.aws/.*",
".*python.*open.*/\\.ssh/.*",
".*strings.*/\\.aws/.*",
".*tail.*/\\.aws/.*",
".*tail.*/\\.ssh/.*",
".*wget.*169\\.254\\.169\\.254.*",
"DROP DATABASE.*",
"DROP TABLE.*",
"TRUNCATE TABLE.*",
"aws autoscaling delete-.*",
"aws cloudformation delete-stack.*",
"aws cloudformation update-termination-protection.*",
"aws dynamodb delete-table.*",
"aws ec2 delete-.*",
"aws ec2 terminate-instances.*",
"aws ecr delete-.*",
"aws ecs delete-.*",
"aws eks delete-cluster.*",
"aws elasticache delete-.*",
"aws elb delete-.*",
"aws elbv2 delete-.*",
"aws glue delete-.*",
"aws iam create-access-key.*",
"aws iam delete-.*",
"aws kinesis delete-.*",
"aws kms schedule-key-deletion.*",
"aws lambda delete-function.*",
"aws logs delete-.*",
"aws opensearch delete-.*",
"aws rds delete-.*",
"aws redshift delete-.*",
"aws route53 delete-.*",
"aws s3 cp .* s3://.*",
"aws s3 mv .* s3://.*",
"aws s3 rb.*",
"aws s3 rm.*",
"aws s3 sync .* s3://.*",
"aws s3api delete-.*",
"aws secretsmanager delete-secret.*",
"aws sns delete-.*",
"aws sqs delete-.*",
"aws stepfunctions delete-.*",
"cdk destroy.*",
"chmod 777.*",
"curl .* \\| bash",
"curl .* \\| sh",
"dd if=.*",
"export AWS_ACCESS.*",
"export AWS_SECRET.*",
"git push.*--force.*",
"git push.*-f .*",
"git reset --hard.*",
"kubectl delete namespace.*",
"mkfs.*",
"nc -e.*",
"ncat -e.*",
"pulumi destroy.*",
"rm -rf /.*",
"rm -rf ~.*",
"terraform destroy.*",
"wget .* \\| bash"
]
}
}
}
4 changes: 4 additions & 0 deletions agents/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
"hash": "ab42104634985d3e",
"updated": "2026-09-23"
},
"kiro/studyloop.json": {
"hash": "50ce9fbb28c32855",
"updated": "2026-09-26"
},
"opencode/plugins/studyloop-session-export.js": {
"hash": "769ed9efdda111a9",
"updated": "2026-09-23"
Expand Down
9 changes: 9 additions & 0 deletions docs/agent-install.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,15 @@ Kiro also receives the `study-plan-architect` agent. Start it directly with:
kiro-cli chat --agent study-plan-architect
```

Kiro also receives `studyloop`, StudyLoop's own agent for web sessions. Every
Study Session or planning session that runs Kiro over ACP starts
`kiro-cli acp --agent studyloop`, so your default Kiro agent — and whatever
prompt, steering, skills or MCP servers it loads — never configures a
StudyLoop session. It carries no persona (the session sends one), reaches only
StudyLoop's `studyloop` and `session-db` MCP servers, and pre-approves no
tools, the same grants ACP sessions had before it existed. You never start it
yourself; `studyloop doctor` checks that kiro-cli validates and lists it.

Kiro also receives the opt-in `studyloop-xtiles-wind-down` skill at `~/.kiro/skills/`, as a symlink to the shared copy described below. It stays silent unless your second-brain provider is `xtiles` and an `xtiles` MCP server is connected.

### Codex
Expand Down
Loading
Loading